From c3338669ae76da0c69a4a0c93bc4602edd1534b9 Mon Sep 17 00:00:00 2001
From: evandrosaturnino <evandro.saturnino@gmail.com>
Date: Tue, 12 Nov 2024 10:00:22 -0300
Subject: [PATCH 01/46] Update env variables

---
 .env.example                                  |  7 ++--
 .env.production                               |  8 ++--
 .env.test                                     |  4 +-
 .github/workflows/dashboard-ci.yml            | 18 ++++-----
 .github/workflows/dashboard-mainnet.yml       | 12 +++---
 .../workflows/reusable-build-and-publish.yml  | 19 ++++-----
 README.md                                     | 12 +++---
 src/enums/env.ts                              |  8 ++--
 src/utils/getEnvVariable.ts                   |  5 ++-
 src/utils/getThresholdLib.ts                  | 40 ++++++++++++-------
 src/web3/hooks/__tests__/useContract.test.ts  |  4 +-
 11 files changed, 76 insertions(+), 61 deletions(-)

diff --git a/.env.example b/.env.example
index c9ffec237..799828f47 100644
--- a/.env.example
+++ b/.env.example
@@ -1,6 +1,5 @@
-REACT_APP_SUPPORTED_CHAIN_ID=1337
-REACT_APP_ETH_HOSTNAME_HTTP=http://localhost:8545
-REACT_APP_ETH_HOSTNAME_WS=ws://localhost:8545
+REACT_APP_DEFAULT_PROVIDER_CHAIN_ID=1337
+REACT_APP_ALCHEMY_API=$ALCHEMY_API
 REACT_APP_MULTICALL_ADDRESS=$MULTICALL_ADDRESS
 REACT_APP_DAPP_DEVELOPMENT_TESTNET_CONTRACTS=$DAPP_DEVELOPMENT_TESTNET_CONTRACTS
 
@@ -26,4 +25,6 @@ REACT_APP_MOCK_BITCOIN_CLIENT=true
 
 REACT_APP_WALLET_CONNECT_PROJECT_ID=$WALLET_CONNECT_PROJECT_ID
 
+REACT_APP_TBTC_SUBGRAPH_API=$TBTC_SUBGRAPH_API
+
 REACT_APP_TACO_DOMAIN=dashboard
diff --git a/.env.production b/.env.production
index cd79837aa..f60c8564f 100644
--- a/.env.production
+++ b/.env.production
@@ -1,6 +1,5 @@
-REACT_APP_SUPPORTED_CHAIN_ID=$CHAIN_ID
-REACT_APP_ETH_HOSTNAME_HTTP=$ETH_HOSTNAME_HTTP
-REACT_APP_ETH_HOSTNAME_WS=$ETH_HOSTNAME_WS
+REACT_APP_DEFAULT_PROVIDER_CHAIN_ID=$CHAIN_ID
+REACT_APP_ALCHEMY_API=$ALCHEMY_API
 REACT_APP_DAPP_DEVELOPMENT_TESTNET_CONTRACTS=$DAPP_DEVELOPMENT_TESTNET_CONTRACTS
 
 REACT_APP_FEATURE_FLAG_TBTC_V2=true
@@ -26,4 +25,7 @@ REACT_APP_ELECTRUM_PORT=$ELECTRUM_PORT
 REACT_APP_MOCK_BITCOIN_CLIENT=false
 
 REACT_APP_WALLET_CONNECT_PROJECT_ID=$WALLET_CONNECT_PROJECT_ID
+
+REACT_APP_TBTC_SUBGRAPH_API=$TBTC_SUBGRAPH_API
+
 REACT_APP_TACO_DOMAIN=mainnet
\ No newline at end of file
diff --git a/.env.test b/.env.test
index d43a646da..ccece28fe 100644
--- a/.env.test
+++ b/.env.test
@@ -1,3 +1,3 @@
-REACT_APP_SUPPORTED_CHAIN_ID=1337
-REACT_APP_MULTICALL_ADDRESS=0x086813525A7dC7dafFf015Cdf03896Fd276eab60
+REACT_APP_DEFAULT_PROVIDER_CHAIN_ID=1337
+REACT_APP_MULTICALL_ADDRESS=0xcA11bde05977b3631167028862bE2a173976CA11
 REACT_APP_TACO_DOMAIN=dashboard
\ No newline at end of file
diff --git a/.github/workflows/dashboard-ci.yml b/.github/workflows/dashboard-ci.yml
index 27d0e4f4e..a1bdd71a9 100644
--- a/.github/workflows/dashboard-ci.yml
+++ b/.github/workflows/dashboard-ci.yml
@@ -86,14 +86,14 @@ jobs:
         run: yarn build
         env:
           PUBLIC_URL: /${{ github.head_ref }}
-          CHAIN_ID: 11155111
-          ETH_HOSTNAME_HTTP: ${{ secrets.SEPOLIA_ETH_HOSTNAME_HTTP }}
-          ETH_HOSTNAME_WS: ${{ secrets.SEPOLIA_ETH_HOSTNAME_WS }}
+          DEFAULT_PROVIDER_CHAIN_ID: 11155111
+          ALCHEMY_API: ${{ secrets.ALCHEMY_API }}
           NODE_OPTIONS: --max_old_space_size=4096
           ELECTRUM_PROTOCOL: ${{ secrets.TESTNET_ELECTRUMX_PROTOCOL }}
           ELECTRUM_HOST: ${{ secrets.TESTNET_ELECTRUMX_HOST }}
           ELECTRUM_PORT: ${{ secrets.TESTNET_ELECTRUMX_PORT }}
           WALLET_CONNECT_PROJECT_ID: ${{ secrets.WALLET_CONNECT_PROJECT_ID }}
+          TBTC_SUBGRAPH_API: ${{ secrets.TBTC_SUBGRAPH_API }}
 
       # FIXME: Tests are missing, will this step be needed?
       # - name: Test
@@ -121,14 +121,14 @@ jobs:
       gcpBucketPath: ${{ github.head_ref }}
       preview: true
     secrets:
-      ethUrlHttp: ${{ secrets.SEPOLIA_ETH_HOSTNAME_HTTP }}
-      ethUrlWS: ${{ secrets.SEPOLIA_ETH_HOSTNAME_WS }}
+      alchemyApi: ${{ secrets.ALCHEMY_API }}
       gcpServiceKey: ${{ secrets.KEEP_TEST_CI_UPLOAD_DAPP_JSON_KEY_BASE64 }}
       electrumProtocol: ${{ secrets.TESTNET_ELECTRUMX_PROTOCOL }}
       electrumHost: ${{ secrets.TESTNET_ELECTRUMX_HOST }}
       electrumPort: ${{ secrets.TESTNET_ELECTRUMX_PORT }}
       sentryDsn: ${{ secrets.TESTNET_SENTRY_DSN }}
       walletConnectProjectId: ${{ secrets.WALLET_CONNECT_PROJECT_ID }}
+      tbtcSubgraphApi: ${{ secrets.TBTC_SUBGRAPH_API }}
 
   # This job will be triggered via the `workflow_dispatch` event, as part of the
   # CI flow, which gets triggered manually after changes in the contracts,
@@ -152,14 +152,14 @@ jobs:
       gcpBucketName: dashboard.test.threshold.network
       preview: false
     secrets:
-      ethUrlHttp: ${{ secrets.SEPOLIA_ETH_HOSTNAME_HTTP }}
-      ethUrlWS: ${{ secrets.SEPOLIA_ETH_HOSTNAME_WS }}
+      alchemyApi: ${{ secrets.ALCHEMY_API }}
       gcpServiceKey: ${{ secrets.KEEP_TEST_CI_UPLOAD_DAPP_JSON_KEY_BASE64 }}
       electrumProtocol: ${{ secrets.TESTNET_ELECTRUMX_PROTOCOL }}
       electrumHost: ${{ secrets.TESTNET_ELECTRUMX_HOST }}
       electrumPort: ${{ secrets.TESTNET_ELECTRUMX_PORT }}
       sentryDsn: ${{ secrets.TESTNET_SENTRY_DSN }}
       walletConnectProjectId: ${{ secrets.WALLET_CONNECT_PROJECT_ID }}
+      tbtcSubgraphApi: ${{ secrets.TBTC_SUBGRAPH_API }}
 
   # This job will be triggered after merges of PRs to the `main` branch. As the
   # triggering is not related to the changes in the contracts / client code, we
@@ -178,11 +178,11 @@ jobs:
       gcpBucketName: dashboard.test.threshold.network
       preview: false
     secrets:
-      ethUrlHttp: ${{ secrets.SEPOLIA_ETH_HOSTNAME_HTTP }}
-      ethUrlWS: ${{ secrets.SEPOLIA_ETH_HOSTNAME_WS }}
+      alchemyApi: ${{ secrets.ALCHEMY_API }}
       gcpServiceKey: ${{ secrets.KEEP_TEST_CI_UPLOAD_DAPP_JSON_KEY_BASE64 }}
       electrumProtocol: ${{ secrets.TESTNET_ELECTRUMX_PROTOCOL }}
       electrumHost: ${{ secrets.TESTNET_ELECTRUMX_HOST }}
       electrumPort: ${{ secrets.TESTNET_ELECTRUMX_PORT }}
       sentryDsn: ${{ secrets.TESTNET_SENTRY_DSN }}
       walletConnectProjectId: ${{ secrets.WALLET_CONNECT_PROJECT_ID }}
+      tbtcSubgraphApi: ${{ secrets.TBTC_SUBGRAPH_API }}
diff --git a/.github/workflows/dashboard-mainnet.yml b/.github/workflows/dashboard-mainnet.yml
index 5071f28d3..9f43cccfe 100644
--- a/.github/workflows/dashboard-mainnet.yml
+++ b/.github/workflows/dashboard-mainnet.yml
@@ -48,9 +48,8 @@ jobs:
         run: yarn build
         env:
           PUBLIC_URL: /${{ github.ref_name }}
-          CHAIN_ID: 1
-          ETH_HOSTNAME_HTTP: ${{ secrets.MAINNET_ETH_HOSTNAME_HTTP }}
-          ETH_HOSTNAME_WS: ${{ secrets.MAINNET_ETH_HOSTNAME_WS }}
+          DEFAULT_PROVIDER_CHAIN_ID: 1
+          ALCHEMY_API: ${{ secrets.ALCHEMY_API }}
           NODE_OPTIONS: --max_old_space_size=4096
           ELECTRUM_PROTOCOL: ${{ secrets.MAINNET_ELECTRUMX_PROTOCOL }}
           ELECTRUM_HOST: ${{ secrets.MAINNET_ELECTRUMX_HOST }}
@@ -59,6 +58,7 @@ jobs:
           SENTRY_DSN: ${{ secrets.MAINNET_SENTRY_DSN }}
           TRM_SUPPORT: ${{ secrets.TRM_SUPPORT }}
           WALLET_CONNECT_PROJECT_ID: ${{ secrets.WALLET_CONNECT_PROJECT_ID }}
+          TBTC_SUBGRAPH_API: ${{ secrets.TBTC_SUBGRAPH_API }}
           GOOGLE_TAG_MANAGER_SUPPORT: false
           GOOGLE_TAG_MANAGER_ID: ${{ secrets.GOOGLE_TAG_MANAGER_ID }}
 
@@ -67,9 +67,8 @@ jobs:
         run: yarn build
         env:
           PUBLIC_URL: /
-          CHAIN_ID: 1
-          ETH_HOSTNAME_HTTP: ${{ secrets.MAINNET_ETH_HOSTNAME_HTTP }}
-          ETH_HOSTNAME_WS: ${{ secrets.MAINNET_ETH_HOSTNAME_WS }}
+          DEFAULT_PROVIDER_CHAIN_ID: 1
+          ALCHEMY_API: ${{ secrets.ALCHEMY_API }}
           NODE_OPTIONS: --max_old_space_size=4096
           POSTHOG_SUPPORT: true
           POSTHOG_API_KEY: ${{ secrets.MAINNET_POSTHOG_API_KEY }}
@@ -81,6 +80,7 @@ jobs:
           SENTRY_DSN: ${{ secrets.MAINNET_SENTRY_DSN }}
           TRM_SUPPORT: ${{ secrets.TRM_SUPPORT }}
           WALLET_CONNECT_PROJECT_ID: ${{ secrets.WALLET_CONNECT_PROJECT_ID }}
+          TBTC_SUBGRAPH_API: ${{ secrets.TBTC_SUBGRAPH_API }}
           GOOGLE_TAG_MANAGER_SUPPORT: true
           GOOGLE_TAG_MANAGER_ID: ${{ secrets.GOOGLE_TAG_MANAGER_ID }}
 
diff --git a/.github/workflows/reusable-build-and-publish.yml b/.github/workflows/reusable-build-and-publish.yml
index 49f1d119c..175347f20 100644
--- a/.github/workflows/reusable-build-and-publish.yml
+++ b/.github/workflows/reusable-build-and-publish.yml
@@ -49,11 +49,8 @@ on:
         default: false
         type: boolean
     secrets:
-      ethUrlHttp:
-        description: The HTTP ETH API URL.
-        required: true
-      ethUrlWS:
-        description: The WebSocket ETH API URL.
+      alchemyApi:
+        description: The Alchemy API Key.
         required: true
       gcpServiceKey:
         description: JSON key for Google Cloud Platform service account.
@@ -161,9 +158,8 @@ jobs:
         run: yarn build
         env:
           PUBLIC_URL: /
-          CHAIN_ID: ${{ env.NETWORK_ID }}
-          ETH_HOSTNAME_HTTP: ${{ secrets.ethUrlHttp }}
-          ETH_HOSTNAME_WS: ${{ secrets.ethUrlWS }}
+          DEFAULT_PROVIDER_CHAIN_ID: ${{ env.NETWORK_ID }}
+          ALCHEMY_API: ${{ secrets.alchemyApi }}
           NODE_OPTIONS: --max_old_space_size=4096
           ELECTRUM_PROTOCOL: ${{ secrets.electrumProtocol }}
           ELECTRUM_HOST: ${{ secrets.electrumHost }}
@@ -171,6 +167,7 @@ jobs:
           SENTRY_SUPPORT: true
           SENTRY_DSN: ${{ secrets.sentryDsn }}
           WALLET_CONNECT_PROJECT_ID: ${{ secrets.walletConnectProjectId }}
+          TBTC_SUBGRAPH_API: ${{ secrets.tbtcSubgraphApi }}
           DAPP_DEVELOPMENT_TESTNET_CONTRACTS: ${{ inputs.preview == true }}
 
       - name: Build
@@ -179,9 +176,8 @@ jobs:
         run: yarn build
         env:
           PUBLIC_URL: /${{ inputs.gcpBucketPath }}
-          CHAIN_ID: ${{ env.NETWORK_ID }}
-          ETH_HOSTNAME_HTTP: ${{ secrets.ethUrlHttp }}
-          ETH_HOSTNAME_WS: ${{ secrets.ethUrlWS }}
+          DEFAULT_PROVIDER_CHAIN_ID: ${{ env.NETWORK_ID }}
+          ALCHEMY_API: ${{ secrets.alchemyApi }}
           NODE_OPTIONS: --max_old_space_size=4096
           ELECTRUM_PROTOCOL: ${{ secrets.electrumProtocol }}
           ELECTRUM_HOST: ${{ secrets.electrumHost }}
@@ -189,6 +185,7 @@ jobs:
           SENTRY_SUPPORT: true
           SENTRY_DSN: ${{ secrets.sentryDsn }}
           WALLET_CONNECT_PROJECT_ID: ${{ secrets.walletConnectProjectId }}
+          TBTC_SUBGRAPH_API: ${{ secrets.tbtcSubgraphApi }}
           DAPP_DEVELOPMENT_TESTNET_CONTRACTS: ${{ inputs.preview == true }}
 
       - name: Deploy to GCP
diff --git a/README.md b/README.md
index a7ee0c939..3d6ca5375 100644
--- a/README.md
+++ b/README.md
@@ -11,9 +11,8 @@ This project was bootstrapped with [Create React App](https://github.com/faceboo
 ## Update the `.env` file:
 
 ```
-REACT_APP_SUPPORTED_CHAIN_ID=11155111
-REACT_APP_ETH_HOSTNAME_HTTP=<your http ETH hostname- eg. Infura>
-REACT_APP_ETH_HOSTNAME_WS=<your ws ETH hostname- eg. Infura>
+REACT_APP_DEFAULT_PROVIDER_CHAIN_ID=11155111
+REACT_APP_ALCHEMY_API=<your Alchemy API key>
 // We can skip this env variable- the dapp uses the correct address
 // of Multicall contract for Sepolia under the hood.
 REACT_APP_MULTICALL_ADDRESS=$MULTICALL_ADDRESS
@@ -109,9 +108,8 @@ The following procedure allows to deploy T token dashboard to production:
 Update `.env` to contain:
 
 ```
-REACT_APP_SUPPORTED_CHAIN_ID=11155111
-REACT_APP_ETH_HOSTNAME_HTTP=https://sepolia.infura.io/v3/<your API key here>
-REACT_APP_ETH_HOSTNAME_WS=wss://sepolia.infura.io/v3/<your API key here>
+REACT_APP_DEFAULT_PROVIDER_CHAIN_ID=11155111
+REACT_APP_ALCHEMY_API=<your Alchemy API key here>
 REACT_APP_MULTICALL_ADDRESS=$MULTICALL_ADDRESS
 
 REACT_APP_FEATURE_FLAG_TBTC_V2=true
@@ -136,6 +134,8 @@ REACT_APP_MOCK_BITCOIN_CLIENT=false
 
 REACT_APP_WALLET_CONNECT_PROJECT_ID=$WALLET_CONNECT_PROJECT_ID
 
+REACT_APP_TBTC_SUBGRAPH_API=$TBTC_SUBGRAPH_API
+
 REACT_APP_TACO_DOMAIN=dashboard
 ```
 
diff --git a/src/enums/env.ts b/src/enums/env.ts
index 39e8a99aa..21373a683 100644
--- a/src/enums/env.ts
+++ b/src/enums/env.ts
@@ -1,7 +1,7 @@
 const envVariables = [
-  "SUPPORTED_CHAIN_ID",
-  "ETH_HOSTNAME_HTTP",
-  "ETH_HOSTNAME_WS",
+  "DEFAULT_PROVIDER_CHAIN_ID",
+  "ALCHEMY_API",
+  "TBTC_SUBGRAPH_API",
   "FEATURE_FLAG_TBTC_V2",
   "FEATURE_FLAG_TBTC_V2_REDEMPTION",
   "FEATURE_FLAG_MULTI_APP_STAKING",
@@ -26,7 +26,7 @@ const envVariables = [
 export type EnvVariableKey = typeof envVariables[number]
 
 // In order not to break the previous enum API, so using eg.
-// `EnvVariable.ETH_HOSTNAME_HTTP` is still valid.
+// `EnvVariable.ALCHEMY_API` is still valid.
 export const EnvVariable: Record<EnvVariableKey, EnvVariableKey> =
   envVariables.reduce((reducer, envKey) => {
     reducer[envKey] = envKey
diff --git a/src/utils/getEnvVariable.ts b/src/utils/getEnvVariable.ts
index 4b8943cc2..91a5544e6 100644
--- a/src/utils/getEnvVariable.ts
+++ b/src/utils/getEnvVariable.ts
@@ -13,7 +13,10 @@ export const getEnvVariable = (envVar: EnvVariableKey) => {
   return envMap[envVar]
 }
 
-export const supportedChainId = getEnvVariable(EnvVariable.SUPPORTED_CHAIN_ID)
+export const getDefaultProviderChainId = () => {
+  const chainIdInString = getEnvVariable(EnvVariable.DEFAULT_PROVIDER_CHAIN_ID)
+  return Number(chainIdInString)
+}
 
 export const shouldUseTestnetDevelopmentContracts =
   getEnvVariable(EnvVariable.DAPP_DEVELOPMENT_TESTNET_CONTRACTS) === "true"
diff --git a/src/utils/getThresholdLib.ts b/src/utils/getThresholdLib.ts
index c49153e7a..9b8850370 100644
--- a/src/utils/getThresholdLib.ts
+++ b/src/utils/getThresholdLib.ts
@@ -1,12 +1,17 @@
 import { JsonRpcProvider, Provider } from "@ethersproject/providers"
 import { Signer } from "ethers"
 import { Threshold } from "../threshold-ts"
-import { ChainID, EnvVariable } from "../enums"
+import { EnvVariable } from "../enums"
 import {
+  getDefaultProviderChainId,
   getEnvVariable,
   shouldUseTestnetDevelopmentContracts,
-  supportedChainId,
 } from "../utils/getEnvVariable"
+import {
+  isSupportedNetwork,
+  isTestnetNetwork,
+} from "../networks/utils/connectedNetwork"
+import { getRpcUrl } from "../networks/utils/getRpcUrl"
 import { MockBitcoinClient } from "../tbtc/mock-bitcoin-client"
 import {
   BitcoinConfig,
@@ -14,24 +19,27 @@ import {
   BitcoinClientCredentials,
   EthereumConfig,
 } from "../threshold-ts/types"
+import { SupportedChainIds } from "../networks/enums/networks"
+
+const defaultProviderChainId = getDefaultProviderChainId()
 
 function getInitialEthereumConfig(
   providerOrSigner?: Provider | Signer
 ): EthereumConfig {
   return {
-    chainId: supportedChainId,
-    providerOrSigner: providerOrSigner || getDefaultThresholdLibProvider(),
+    chainId: getDefaultProviderChainId(),
+    providerOrSigner:
+      providerOrSigner || getThresholdLibProvider(defaultProviderChainId),
     shouldUseTestnetDevelopmentContracts:
-      supportedChainId === ChainID.Sepolia.toString() &&
+      defaultProviderChainId === SupportedChainIds.Sepolia &&
       shouldUseTestnetDevelopmentContracts,
   }
 }
 
 function getInitialBitcoinConfig(): BitcoinConfig {
-  const network =
-    supportedChainId === ChainID.Ethereum.toString()
-      ? BitcoinNetwork.Mainnet
-      : BitcoinNetwork.Testnet
+  const network = isTestnetNetwork(defaultProviderChainId)
+    ? BitcoinNetwork.Testnet
+    : BitcoinNetwork.Mainnet
 
   const shouldMockBitcoinClient =
     getEnvVariable(EnvVariable.MOCK_BITCOIN_CLIENT) === "true"
@@ -53,8 +61,14 @@ function getInitialBitcoinConfig(): BitcoinConfig {
   }
 }
 
-export const getDefaultThresholdLibProvider = () => {
-  return new JsonRpcProvider(getEnvVariable(EnvVariable.ETH_HOSTNAME_HTTP))
+export const getThresholdLibProvider = (chainId?: number | string) => {
+  const supportedChainId = isSupportedNetwork(chainId)
+    ? Number(chainId)
+    : getDefaultProviderChainId()
+
+  const rpcUrl = getRpcUrl(supportedChainId)
+
+  return new JsonRpcProvider(rpcUrl, supportedChainId)
 }
 
 export const getThresholdLib = (providerOrSigner?: Provider | Signer) => {
@@ -64,6 +78,4 @@ export const getThresholdLib = (providerOrSigner?: Provider | Signer) => {
   })
 }
 
-export const threshold = getThresholdLib(
-  new JsonRpcProvider(getEnvVariable(EnvVariable.ETH_HOSTNAME_HTTP))
-)
+export const threshold = getThresholdLib(getThresholdLibProvider())
diff --git a/src/web3/hooks/__tests__/useContract.test.ts b/src/web3/hooks/__tests__/useContract.test.ts
index 41e202d44..1e156a9b4 100644
--- a/src/web3/hooks/__tests__/useContract.test.ts
+++ b/src/web3/hooks/__tests__/useContract.test.ts
@@ -4,7 +4,7 @@ import { JsonRpcProvider } from "@ethersproject/providers"
 import { useContract } from "../useContract"
 import { getContract } from "../../../utils/getContract"
 import { getEnvVariable } from "../../../utils/getEnvVariable"
-import { EnvVariable } from "../../../enums"
+import { getRpcUrl } from "../../../networks/utils"
 
 jest.mock("../../../utils/getContract", () => ({
   ...(jest.requireActual("../../../utils/getContract") as {}),
@@ -62,7 +62,7 @@ describe("Test the `useContract` hook", () => {
 
       const { result } = renderHook(() => useContract(address, abi))
 
-      expect(getEnvVariable).toHaveBeenCalledWith(EnvVariable.ETH_HOSTNAME_HTTP)
+      expect(getEnvVariable).toHaveBeenCalledWith(getRpcUrl())
       expect(JsonRpcProvider).toHaveBeenCalledWith(mockedEthNodeUrl)
       expect(result.current).toEqual(mockedContract)
     })

From 86711bdb724e153c84d83908960795c90f960e83 Mon Sep 17 00:00:00 2001
From: evandrosaturnino <evandro.saturnino@gmail.com>
Date: Tue, 12 Nov 2024 10:01:10 -0300
Subject: [PATCH 02/46] Update tbtc sdk version in package json

---
 package.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/package.json b/package.json
index 3d87f0b88..6668fb35d 100644
--- a/package.json
+++ b/package.json
@@ -18,7 +18,7 @@
     "@keep-network/keep-ecdsa": "development",
     "@keep-network/random-beacon": "development",
     "@keep-network/tbtc": "development",
-    "@keep-network/tbtc-v2.ts": "^2.4.1",
+    "@keep-network/tbtc-v2.ts": "^2.5.0-dev.8",
     "@ledgerhq/connect-kit-loader": "1.1.8",
     "@ledgerhq/wallet-api-client": "^1.2.0",
     "@ledgerhq/wallet-api-client-react": "^1.1.1",

From 17d11d033fd41f0216203b77684e6b8438e3b199 Mon Sep 17 00:00:00 2001
From: evandrosaturnino <evandro.saturnino@gmail.com>
Date: Tue, 12 Nov 2024 10:12:15 -0300
Subject: [PATCH 03/46] Update explorer links based on network

---
 src/components/CopyToClipboard/index.tsx      |  2 +-
 src/components/Link/SharedLinks.tsx           |  2 +-
 .../index.tsx                                 |  2 +-
 .../DeauthorizationCompleted.tsx              |  2 +-
 .../IncreaseAuthorizationSuccess.tsx          |  2 +-
 .../StakingApplicationsAuthorized.tsx         |  2 +-
 .../StakingSuccessModal/StakeSuccessOld.tsx   |  2 +-
 .../Modal/StakingSuccessModal/index.tsx       |  2 +-
 .../TransactionModal/TransactionFailed.tsx    |  5 ++-
 src/components/ViewInBlockExplorer.tsx        | 32 +++++++++++++------
 src/components/tBTC/Links.tsx                 | 13 ++++++--
 src/components/tBTC/RecentDeposits.tsx        |  2 +-
 src/pages/tBTC/Bridge/DepositDetails.tsx      |  5 ++-
 src/pages/tBTC/Bridge/UnmintDetails.tsx       |  2 +-
 .../Bridge/components/BridgeProcessStep.tsx   |  7 ++--
 src/pages/tBTC/Explorer/index.tsx             |  2 +-
 16 files changed, 56 insertions(+), 28 deletions(-)

diff --git a/src/components/CopyToClipboard/index.tsx b/src/components/CopyToClipboard/index.tsx
index d0cb9f7c9..fd0e4e91b 100644
--- a/src/components/CopyToClipboard/index.tsx
+++ b/src/components/CopyToClipboard/index.tsx
@@ -12,7 +12,7 @@ import shortenAddress from "../../utils/shortenAddress"
 import ViewInBlockExplorer, {
   ViewInBlockExplorerProps,
 } from "../ViewInBlockExplorer"
-import { ExplorerDataType } from "../../utils/createEtherscanLink"
+import { ExplorerDataType } from "../../networks/enums/networks"
 
 type CopyToClipboardProps = {
   textToCopy: string
diff --git a/src/components/Link/SharedLinks.tsx b/src/components/Link/SharedLinks.tsx
index 8c64b4d28..01808aaeb 100644
--- a/src/components/Link/SharedLinks.tsx
+++ b/src/components/Link/SharedLinks.tsx
@@ -3,7 +3,7 @@ import { useColorModeValue } from "@chakra-ui/react"
 import { BodySm } from "@threshold-network/components"
 import ViewInBlockExplorer from "../ViewInBlockExplorer"
 import { useTStakingContract } from "../../web3/hooks"
-import { ExplorerDataType } from "../../utils/createEtherscanLink"
+import { ExplorerDataType } from "../../networks/enums/networks"
 
 type StakingContractLearnMoreProps = ComponentProps<typeof BodySm>
 
diff --git a/src/components/Modal/MapOperatorToStakingProviderSuccessModal/index.tsx b/src/components/Modal/MapOperatorToStakingProviderSuccessModal/index.tsx
index 71d4ddc57..1d3a881db 100644
--- a/src/components/Modal/MapOperatorToStakingProviderSuccessModal/index.tsx
+++ b/src/components/Modal/MapOperatorToStakingProviderSuccessModal/index.tsx
@@ -5,7 +5,7 @@ import { BaseModalProps } from "../../../types"
 import { StakingAppName } from "../../../store/staking-applications"
 import TransactionSuccessModal from "../TransactionSuccessModal"
 import shortenAddress from "../../../utils/shortenAddress"
-import { ExplorerDataType } from "../../../utils/createEtherscanLink"
+import { ExplorerDataType } from "../../../networks/enums/networks"
 import ViewInBlockExplorer from "../../ViewInBlockExplorer"
 
 export type OperatorMappedSuccessTx = {
diff --git a/src/components/Modal/StakingApplications/DeauthorizationCompleted.tsx b/src/components/Modal/StakingApplications/DeauthorizationCompleted.tsx
index c5de66845..20cf2d3cb 100644
--- a/src/components/Modal/StakingApplications/DeauthorizationCompleted.tsx
+++ b/src/components/Modal/StakingApplications/DeauthorizationCompleted.tsx
@@ -16,7 +16,7 @@ import ViewInBlockExplorer from "../../ViewInBlockExplorer"
 import withBaseModal from "../withBaseModal"
 import shortenAddress from "../../../utils/shortenAddress"
 import { formatTokenAmount } from "../../../utils/formatAmount"
-import { ExplorerDataType } from "../../../utils/createEtherscanLink"
+import { ExplorerDataType } from "../../../networks/enums/networks"
 import { BaseModalProps } from "../../../types"
 import ModalCloseButton from "../ModalCloseButton"
 
diff --git a/src/components/Modal/StakingApplications/IncreaseAuthorizationSuccess.tsx b/src/components/Modal/StakingApplications/IncreaseAuthorizationSuccess.tsx
index 1307a2909..0b0cee1e3 100644
--- a/src/components/Modal/StakingApplications/IncreaseAuthorizationSuccess.tsx
+++ b/src/components/Modal/StakingApplications/IncreaseAuthorizationSuccess.tsx
@@ -16,7 +16,7 @@ import ViewInBlockExplorer from "../../ViewInBlockExplorer"
 import withBaseModal from "../withBaseModal"
 import shortenAddress from "../../../utils/shortenAddress"
 import { formatTokenAmount } from "../../../utils/formatAmount"
-import { ExplorerDataType } from "../../../utils/createEtherscanLink"
+import { ExplorerDataType } from "../../../networks/enums/networks"
 import { BaseModalProps } from "../../../types"
 import ModalCloseButton from "../ModalCloseButton"
 
diff --git a/src/components/Modal/StakingApplications/StakingApplicationsAuthorized.tsx b/src/components/Modal/StakingApplications/StakingApplicationsAuthorized.tsx
index a79c88104..7e4b2407e 100644
--- a/src/components/Modal/StakingApplications/StakingApplicationsAuthorized.tsx
+++ b/src/components/Modal/StakingApplications/StakingApplicationsAuthorized.tsx
@@ -29,7 +29,7 @@ import {
 } from "../../../utils/percentage"
 import shortenAddress from "../../../utils/shortenAddress"
 import { formatTokenAmount } from "../../../utils/formatAmount"
-import { ExplorerDataType } from "../../../utils/createEtherscanLink"
+import { ExplorerDataType } from "../../../networks/enums/networks"
 import { ExternalHref } from "../../../enums"
 import { BaseModalProps } from "../../../types"
 import { getStakingAppNameFromAppAddress } from "../../../utils/getStakingAppLabel"
diff --git a/src/components/Modal/StakingSuccessModal/StakeSuccessOld.tsx b/src/components/Modal/StakingSuccessModal/StakeSuccessOld.tsx
index f97b4fd76..e8ed60555 100644
--- a/src/components/Modal/StakingSuccessModal/StakeSuccessOld.tsx
+++ b/src/components/Modal/StakingSuccessModal/StakeSuccessOld.tsx
@@ -17,7 +17,7 @@ import { BaseModalProps } from "../../../types"
 import StakingStats from "../../StakingStats"
 import { useStakingState } from "../../../hooks/useStakingState"
 import ViewInBlockExplorer from "../../ViewInBlockExplorer"
-import { ExplorerDataType } from "../../../utils/createEtherscanLink"
+import { ExplorerDataType } from "../../../networks/enums/networks"
 import InfoBox from "../../InfoBox"
 import { TacoSetupSteps } from "../../StakingTimeline"
 import ModalCloseButton from "../ModalCloseButton"
diff --git a/src/components/Modal/StakingSuccessModal/index.tsx b/src/components/Modal/StakingSuccessModal/index.tsx
index c8b6c829d..b251c9b54 100644
--- a/src/components/Modal/StakingSuccessModal/index.tsx
+++ b/src/components/Modal/StakingSuccessModal/index.tsx
@@ -20,7 +20,7 @@ import { BaseModalProps } from "../../../types"
 import StakingStats from "../../StakingStats"
 import { useStakingState } from "../../../hooks/useStakingState"
 import ViewInBlockExplorer from "../../ViewInBlockExplorer"
-import { ExplorerDataType } from "../../../utils/createEtherscanLink"
+import { ExplorerDataType } from "../../../networks/enums/networks"
 import InfoBox from "../../InfoBox"
 import { useModal } from "../../../hooks/useModal"
 import { ModalType } from "../../../enums"
diff --git a/src/components/Modal/TransactionModal/TransactionFailed.tsx b/src/components/Modal/TransactionModal/TransactionFailed.tsx
index cea9ffbf7..529b24a2b 100644
--- a/src/components/Modal/TransactionModal/TransactionFailed.tsx
+++ b/src/components/Modal/TransactionModal/TransactionFailed.tsx
@@ -18,10 +18,11 @@ import { BodySm } from "@threshold-network/components"
 import { ExternalHref } from "../../../enums"
 import { BaseModalProps } from "../../../types"
 import ViewInBlockExplorer from "../../ViewInBlockExplorer"
-import { ExplorerDataType } from "../../../utils/createEtherscanLink"
+import { ExplorerDataType } from "../../../networks/enums/networks"
 import withBaseModal from "../withBaseModal"
 import Link from "../../Link"
 import ModalCloseButton from "../ModalCloseButton"
+import { useIsActive } from "../../../hooks/useIsActive"
 
 interface TransactionFailedProps extends BaseModalProps {
   transactionHash?: string
@@ -36,6 +37,7 @@ const TransactionFailed: FC<TransactionFailedProps> = ({
   transactionHash,
 }) => {
   const { isOpen, onToggle } = useDisclosure()
+  const { chainId } = useIsActive()
 
   const errorTitle = "Error"
 
@@ -113,6 +115,7 @@ const TransactionFailed: FC<TransactionFailedProps> = ({
             <ViewInBlockExplorer
               id={transactionHash}
               type={ExplorerDataType.TRANSACTION}
+              ethereumNetworkChainId={chainId}
               text="View"
             />
             transaction on Etherscan
diff --git a/src/components/ViewInBlockExplorer.tsx b/src/components/ViewInBlockExplorer.tsx
index 8a149eb70..479b7532e 100644
--- a/src/components/ViewInBlockExplorer.tsx
+++ b/src/components/ViewInBlockExplorer.tsx
@@ -1,37 +1,44 @@
 import { FC } from "react"
 import { LinkProps } from "@chakra-ui/react"
 import Link from "./Link"
-import createEtherscanLink, {
+import { ExplorerDataType } from "../networks/enums/networks"
+import { isTestnetNetwork } from "../networks/utils"
+import {
   createBlockExplorerLink,
-  ExplorerDataType,
-} from "../utils/createEtherscanLink"
-import { supportedChainId } from "../utils/getEnvVariable"
+  createExplorerLink,
+} from "../networks/utils/createExplorerLink"
 
 export type Chain = "bitcoin" | "ethereum"
 
 export const createLinkToBlockExplorerForChain: Record<
   Chain,
-  (id: string, type: ExplorerDataType) => string
+  (
+    id: string,
+    type: ExplorerDataType,
+    ethereumNetworkChainId?: string | number
+  ) => string
 > = {
-  bitcoin: (id, type) => {
+  bitcoin: (id, type, ethereumNetworkChainId = 1) => {
     const prefix = `https://blockstream.info${
-      Number(supportedChainId) !== 1 ? "/testnet" : ""
+      isTestnetNetwork(Number(ethereumNetworkChainId)) ? "/testnet" : ""
     }`
 
     return createBlockExplorerLink(prefix, id, type)
   },
-  ethereum: (id, type) =>
-    createEtherscanLink(Number(supportedChainId), id, type),
+  ethereum: (id, type, ethereumNetworkChainId = 1) =>
+    createExplorerLink(Number(ethereumNetworkChainId), id, type),
 }
 
 type ConditionalProps =
   | {
       chain?: Extract<Chain, "bitcoin">
       type: Exclude<ExplorerDataType, ExplorerDataType.TOKEN>
+      ethereumNetworkChainId?: string | number | never
     }
   | {
       chain?: Extract<Chain, "ethereum"> | never
       type: ExplorerDataType
+      ethereumNetworkChainId?: string | number | never
     }
 
 type CommonProps = {
@@ -48,9 +55,14 @@ const ViewInBlockExplorer: FC<ViewInBlockExplorerProps> = ({
   type,
   text = "View in Block Explorer",
   chain = "ethereum",
+  ethereumNetworkChainId,
   ...restProps
 }) => {
-  const link = createLinkToBlockExplorerForChain[chain](id, type)
+  const link = createLinkToBlockExplorerForChain[chain](
+    id,
+    type,
+    ethereumNetworkChainId
+  )
 
   return (
     <Link isExternal href={link} {...restProps}>
diff --git a/src/components/tBTC/Links.tsx b/src/components/tBTC/Links.tsx
index 3640395e9..0491be04f 100644
--- a/src/components/tBTC/Links.tsx
+++ b/src/components/tBTC/Links.tsx
@@ -1,8 +1,9 @@
 import { FC, ComponentProps } from "react"
 import { useTBTCBridgeContractAddress } from "../../hooks/useTBTCBridgeContractAddress"
-import { ExplorerDataType } from "../../utils/createEtherscanLink"
+import { ExplorerDataType } from "../../networks/enums/networks"
 import ViewInBlockExplorer from "../ViewInBlockExplorer"
 import { useTBTCTokenAddress } from "../../hooks/useTBTCTokenAddress"
+import { useIsActive } from "../../hooks/useIsActive"
 
 type Props = Omit<
   ComponentProps<typeof ViewInBlockExplorer>,
@@ -16,7 +17,7 @@ export const BridgeContractLink: FC<Props> = ({
   ...props
 }) => {
   const address = useTBTCBridgeContractAddress()
-  return (
+  return address ? (
     <ViewInBlockExplorer
       id={address}
       type={ExplorerDataType.ADDRESS}
@@ -24,6 +25,8 @@ export const BridgeContractLink: FC<Props> = ({
       {...props}
       data-ph-capture-attribute-button-name={`Bridge contract link (Deposit flow)`}
     />
+  ) : (
+    <></>
   )
 }
 
@@ -31,13 +34,17 @@ export const TBTCTokenContractLink: FC<Props> = ({
   text = "token address",
   ...props
 }) => {
+  const { chainId } = useIsActive()
   const address = useTBTCTokenAddress()
-  return (
+  return address ? (
     <ViewInBlockExplorer
       id={address}
       type={ExplorerDataType.ADDRESS}
       text={text}
+      ethereumNetworkChainId={chainId}
       {...props}
     />
+  ) : (
+    <></>
   )
 }
diff --git a/src/components/tBTC/RecentDeposits.tsx b/src/components/tBTC/RecentDeposits.tsx
index 51ca5036b..42d70242a 100644
--- a/src/components/tBTC/RecentDeposits.tsx
+++ b/src/components/tBTC/RecentDeposits.tsx
@@ -16,7 +16,7 @@ import { InlineTokenBalance } from "../TokenBalance"
 import { getRelativeTime } from "../../utils/date"
 import { RecentDeposit } from "../../hooks/tbtc/useFetchRecentDeposits"
 import { createLinkToBlockExplorerForChain } from "../ViewInBlockExplorer"
-import { ExplorerDataType } from "../../utils/createEtherscanLink"
+import { ExplorerDataType } from "../../networks/enums/networks"
 
 export type RecentDepositsProps = {
   deposits: RecentDeposit[]
diff --git a/src/pages/tBTC/Bridge/DepositDetails.tsx b/src/pages/tBTC/Bridge/DepositDetails.tsx
index cbdfaaeb5..d46396d10 100644
--- a/src/pages/tBTC/Bridge/DepositDetails.tsx
+++ b/src/pages/tBTC/Bridge/DepositDetails.tsx
@@ -63,13 +63,14 @@ import {
   useSubscribeToOptimisticMintingFinalizedEventBase,
 } from "../../../hooks/tbtc"
 import { tbtcSlice } from "../../../store/tbtc"
-import { ExplorerDataType } from "../../../utils/createEtherscanLink"
+import { ExplorerDataType } from "../../../networks/enums/networks"
 import { PageComponent } from "../../../types"
 import { CurveFactoryPoolId, ExternalHref } from "../../../enums"
 import { ExternalPool } from "../../../components/tBTC/ExternalPool"
 import { useFetchExternalPoolData } from "../../../hooks/useFetchExternalPoolData"
 import { TransactionDetailsAmountItem } from "../../../components/TransactionDetails"
 import { BridgeProcessDetailsPageSkeleton } from "./components/BridgeProcessDetailsPageSkeleton"
+import { useIsActive } from "../../../hooks/useIsActive"
 
 export const DepositDetails: PageComponent = () => {
   const { depositKey } = useParams()
@@ -82,6 +83,7 @@ export const DepositDetails: PageComponent = () => {
     "curve",
     CurveFactoryPoolId.TBTC_WBTC_SBTC
   )
+  const { chainId } = useIsActive()
 
   const [mintingProgressStep, setMintingProgressStep] =
     useState<DepositDetailsTimelineStep>("bitcoin-confirmations")
@@ -271,6 +273,7 @@ export const DepositDetails: PageComponent = () => {
                             id={item.txHash!}
                             type={ExplorerDataType.TRANSACTION}
                             chain={item.chain}
+                            ethereumNetworkChainId={chainId}
                             text="transaction"
                           />
                           .
diff --git a/src/pages/tBTC/Bridge/UnmintDetails.tsx b/src/pages/tBTC/Bridge/UnmintDetails.tsx
index a410727f7..1dabcf867 100644
--- a/src/pages/tBTC/Bridge/UnmintDetails.tsx
+++ b/src/pages/tBTC/Bridge/UnmintDetails.tsx
@@ -45,7 +45,7 @@ import {
   BridgeLayoutAsideSection,
   BridgeLayoutMainSection,
 } from "./BridgeLayout"
-import { ExplorerDataType } from "../../../utils/createEtherscanLink"
+import { ExplorerDataType } from "../../../networks/enums/networks"
 import { PageComponent } from "../../../types"
 import { dateToUnixTimestamp, dateAs } from "../../../utils/date"
 import { CopyAddressToClipboard } from "../../../components/CopyToClipboard"
diff --git a/src/pages/tBTC/Bridge/components/BridgeProcessStep.tsx b/src/pages/tBTC/Bridge/components/BridgeProcessStep.tsx
index 3cf86ced0..74086aed1 100644
--- a/src/pages/tBTC/Bridge/components/BridgeProcessStep.tsx
+++ b/src/pages/tBTC/Bridge/components/BridgeProcessStep.tsx
@@ -10,8 +10,9 @@ import {
 import ViewInBlockExplorer, {
   Chain as ViewInBlockExplorerChain,
 } from "../../../../components/ViewInBlockExplorer"
-import { ExplorerDataType } from "../../../../utils/createEtherscanLink"
+import { ExplorerDataType } from "../../../../networks/enums/networks"
 import { ONE_SEC_IN_MILISECONDS } from "../../../../utils/date"
+import { useIsActive } from "../../../../hooks/useIsActive"
 
 export type BridgeProcessStepProps = {
   title: string
@@ -40,6 +41,7 @@ export const BridgeProcessStep: FC<BridgeProcessStepProps> = ({
   children,
 }) => {
   const titleTextColor = useColorModeValue("gray.700", "gray.300")
+  const { chainId } = useIsActive()
 
   useEffect(() => {
     if (!isCompleted) return
@@ -85,9 +87,10 @@ export const BridgeProcessStep: FC<BridgeProcessStepProps> = ({
         <BodySm mt="auto" mb="8" color="gray.500" textAlign="center">
           See transaction on{" "}
           <ViewInBlockExplorer
-            text={chain === "bitcoin" ? "blockstream" : "etherscan"}
+            text={chain === "bitcoin" ? "blockstream" : "network explorer"}
             chain={chain}
             id={txHash}
+            ethereumNetworkChainId={chainId}
             type={ExplorerDataType.TRANSACTION}
           />
         </BodySm>
diff --git a/src/pages/tBTC/Explorer/index.tsx b/src/pages/tBTC/Explorer/index.tsx
index 392f24fa3..17008590d 100644
--- a/src/pages/tBTC/Explorer/index.tsx
+++ b/src/pages/tBTC/Explorer/index.tsx
@@ -41,7 +41,7 @@ import { InlineTokenBalance } from "../../../components/TokenBalance"
 import shortenAddress from "../../../utils/shortenAddress"
 import { getRelativeTime } from "../../../utils/date"
 import { createLinkToBlockExplorerForChain } from "../../../components/ViewInBlockExplorer"
-import { ExplorerDataType } from "../../../utils/createEtherscanLink"
+import { ExplorerDataType } from "../../../networks/enums/networks"
 import {
   RecentDeposit,
   useFetchRecentDeposits,

From a54ccb5eb9c45fbe1a1696b78a45e0914d0027da Mon Sep 17 00:00:00 2001
From: evandrosaturnino <evandro.saturnino@gmail.com>
Date: Tue, 12 Nov 2024 10:20:16 -0300
Subject: [PATCH 04/46] Fix ledger support

---
 src/pages/tBTC/HowItWorks/ContractsCard.tsx | 48 ++++++------
 src/utils/getLedgerLiveAppEthereumSigner.ts | 17 ++---
 src/utils/ledger.ts                         | 83 +++++++++++++++++++++
 src/web3/connectors/ledgerLive.ts           | 46 +++++++-----
 src/web3/hooks/useGetBlock.ts               |  4 +-
 5 files changed, 146 insertions(+), 52 deletions(-)
 create mode 100644 src/utils/ledger.ts

diff --git a/src/pages/tBTC/HowItWorks/ContractsCard.tsx b/src/pages/tBTC/HowItWorks/ContractsCard.tsx
index cdd13e55d..fe387f227 100644
--- a/src/pages/tBTC/HowItWorks/ContractsCard.tsx
+++ b/src/pages/tBTC/HowItWorks/ContractsCard.tsx
@@ -3,39 +3,43 @@ import { List } from "@chakra-ui/react"
 import { Card, LabelSm } from "@threshold-network/components"
 import DetailedLinkListItem from "../../../components/DetailedLinkListItem"
 import { useTBTCTokenAddress } from "../../../hooks/useTBTCTokenAddress"
-import createEtherscanLink, {
-  ExplorerDataType,
-} from "../../../utils/createEtherscanLink"
-import { supportedChainId } from "../../../utils/getEnvVariable"
 import { IoLinkSharp } from "react-icons/all"
 import { useTBTCBridgeContractAddress } from "../../../hooks/useTBTCBridgeContractAddress"
+import { useIsActive } from "../../../hooks/useIsActive"
+import { ExplorerDataType } from "../../../networks/enums/networks"
+import { createExplorerLink } from "../../../networks/utils/createExplorerLink"
 
 export const ContractsCard: FC<ComponentProps<typeof Card>> = (props) => {
   const tbtcTokenContractAddress = useTBTCTokenAddress()
   const bridgeContractAddress = useTBTCBridgeContractAddress()
+  const { chainId } = useIsActive()
 
   return (
     <Card {...props}>
       <LabelSm mb={8}>Contracts</LabelSm>
       <List spacing="2">
-        <DetailedLinkListItem
-          icon={IoLinkSharp}
-          title="Token Contract"
-          href={createEtherscanLink(
-            Number(supportedChainId),
-            tbtcTokenContractAddress,
-            ExplorerDataType.ADDRESS
-          )}
-        />
-        <DetailedLinkListItem
-          icon={IoLinkSharp}
-          title="Bridge Contract"
-          href={createEtherscanLink(
-            Number(supportedChainId),
-            bridgeContractAddress,
-            ExplorerDataType.ADDRESS
-          )}
-        />
+        {tbtcTokenContractAddress && (
+          <DetailedLinkListItem
+            icon={IoLinkSharp}
+            title="Token Contract"
+            href={createExplorerLink(
+              chainId,
+              tbtcTokenContractAddress,
+              ExplorerDataType.ADDRESS
+            )}
+          />
+        )}
+        {bridgeContractAddress && (
+          <DetailedLinkListItem
+            icon={IoLinkSharp}
+            title="Bridge Contract"
+            href={createExplorerLink(
+              chainId,
+              bridgeContractAddress,
+              ExplorerDataType.ADDRESS
+            )}
+          />
+        )}
       </List>
     </Card>
   )
diff --git a/src/utils/getLedgerLiveAppEthereumSigner.ts b/src/utils/getLedgerLiveAppEthereumSigner.ts
index 1c99d4fb2..04438d62c 100644
--- a/src/utils/getLedgerLiveAppEthereumSigner.ts
+++ b/src/utils/getLedgerLiveAppEthereumSigner.ts
@@ -1,12 +1,9 @@
-import { JsonRpcProvider, Provider } from "@ethersproject/providers"
-import { EnvVariable } from "../enums"
-import { LedgerLiveEthereumSigner } from "@keep-network/tbtc-v2.ts"
-import { getEnvVariable } from "./getEnvVariable"
+import { LedgerLiveSigner } from "./ledger"
+import { getThresholdLibProvider } from "./getThresholdLib"
+import { getDefaultProviderChainId } from "./getEnvVariable"
 
-export const getLedgerLiveAppEthereumSigner = (provider: Provider) => {
-  return new LedgerLiveEthereumSigner(provider)
+export const getLedgerLiveAppEthereumSigner = (chainId?: number | string) => {
+  const providerChainId = chainId || getDefaultProviderChainId()
+  const provider = getThresholdLibProvider(providerChainId)
+  return new LedgerLiveSigner(provider)
 }
-
-export const ledgerLiveAppEthereumSigner = getLedgerLiveAppEthereumSigner(
-  new JsonRpcProvider(getEnvVariable(EnvVariable.ETH_HOSTNAME_HTTP))
-)
diff --git a/src/utils/ledger.ts b/src/utils/ledger.ts
new file mode 100644
index 000000000..83a48d0e1
--- /dev/null
+++ b/src/utils/ledger.ts
@@ -0,0 +1,83 @@
+import { Signer, providers, utils } from "ethers"
+import {
+  Account,
+  EthereumTransaction,
+  WalletAPIClient,
+  WindowMessageTransport,
+} from "@ledgerhq/wallet-api-client"
+import BigNumber from "bignumber.js"
+
+export class LedgerLiveSigner extends Signer {
+  private walletApiClient: WalletAPIClient
+  private account: Account | undefined
+
+  constructor(provider?: providers.Provider) {
+    super()
+    utils.defineReadOnly(this, "provider", provider)
+    const transport = new WindowMessageTransport()
+    this.walletApiClient = new WalletAPIClient(transport)
+  }
+
+  async getAddress(): Promise<string> {
+    if (!this.account) throw new Error("Account not set")
+    return this.account.address
+  }
+
+  setAccount(account: Account | undefined) {
+    this.account = account
+  }
+
+  async signMessage(message: string | utils.Bytes): Promise<string> {
+    if (!this.account) throw new Error("Account not set")
+    const signedMessage = await this.walletApiClient.message.sign(
+      this.account.id,
+      Buffer.from(utils.arrayify(message))
+    )
+    return utils.hexlify(signedMessage)
+  }
+
+  async signTransaction(
+    transaction: providers.TransactionRequest
+  ): Promise<string> {
+    if (!this.account) throw new Error("Account not set")
+    const tx: EthereumTransaction = {
+      family: "ethereum",
+      amount: new BigNumber(transaction.value?.toString() || "0"),
+      recipient: transaction.to || "",
+      nonce: transaction.nonce ? Number(transaction.nonce) : undefined,
+      data: transaction.data
+        ? Buffer.from(utils.arrayify(transaction.data))
+        : undefined,
+      gasPrice: transaction.gasPrice
+        ? new BigNumber(transaction.gasPrice.toString())
+        : undefined,
+      gasLimit: transaction.gasLimit
+        ? new BigNumber(transaction.gasLimit.toString())
+        : undefined,
+      maxFeePerGas: transaction.maxFeePerGas
+        ? new BigNumber(transaction.maxFeePerGas.toString())
+        : undefined,
+      maxPriorityFeePerGas: transaction.maxPriorityFeePerGas
+        ? new BigNumber(transaction.maxPriorityFeePerGas.toString())
+        : undefined,
+    }
+
+    const signedTx = await this.walletApiClient.transaction.sign(
+      this.account.id,
+      tx
+    )
+    return utils.hexlify(signedTx)
+  }
+
+  async sendTransaction(
+    transaction: providers.TransactionRequest
+  ): Promise<providers.TransactionResponse> {
+    if (!this.provider) throw new Error("Provider not set")
+    const signedTx = await this.signTransaction(transaction)
+    return this.provider.sendTransaction(signedTx)
+  }
+
+  connect(provider: providers.Provider): LedgerLiveSigner {
+    return new LedgerLiveSigner(provider)
+  }
+}
diff --git a/src/web3/connectors/ledgerLive.ts b/src/web3/connectors/ledgerLive.ts
index 966129b83..abc77ee1c 100644
--- a/src/web3/connectors/ledgerLive.ts
+++ b/src/web3/connectors/ledgerLive.ts
@@ -1,6 +1,6 @@
 import { AbstractConnector } from "@web3-react/abstract-connector"
 import { AbstractConnectorArguments, ConnectorUpdate } from "@web3-react/types"
-import { getEnvVariable, supportedChainId } from "../../utils/getEnvVariable"
+import { getEnvVariable } from "../../utils/getEnvVariable"
 import {
   LedgerConnectKit,
   SupportedProviders,
@@ -8,7 +8,15 @@ import {
   EthereumProvider,
 } from "@ledgerhq/connect-kit-loader"
 import { EnvVariable } from "../../enums"
-import chainIdToNetworkName from "../../utils/chainIdToNetworkName"
+import {
+  getRpcUrl,
+  networks,
+  supportedNetworksMap,
+  getChainIdToNetworkName,
+} from "../../networks/utils"
+import { EthereumRpcMap } from "../../networks/types/networks"
+
+const supportedNetworks = Object.keys(supportedNetworksMap).map(Number)
 
 interface LedgerLiveConnectorArguments extends AbstractConnectorArguments {
   rpc: {
@@ -23,15 +31,15 @@ export class LedgerLiveConnector extends AbstractConnector {
   private connectKitPromise: Promise<LedgerConnectKit>
   private walletConnectProjectId: string
 
-  constructor(args: Required<LedgerLiveConnectorArguments>) {
-    super({
-      supportedChainIds: Object.keys(args.rpc).map((chainId) =>
-        Number(chainId)
-      ),
-    })
+  constructor({
+    supportedChainIds,
+    rpc,
+    walletConnectProjectId,
+  }: Required<LedgerLiveConnectorArguments>) {
+    super({ supportedChainIds })
 
-    this.rpc = args.rpc
-    this.walletConnectProjectId = args.walletConnectProjectId
+    this.rpc = rpc
+    this.walletConnectProjectId = walletConnectProjectId
 
     this.handleNetworkChanged = this.handleNetworkChanged.bind(this)
     this.handleChainChanged = this.handleChainChanged.bind(this)
@@ -57,6 +65,10 @@ export class LedgerLiveConnector extends AbstractConnector {
     this.emitDeactivate()
   }
 
+  public async switchNetwork(chainId: string | number): Promise<void> {
+    this.handleChainChanged(chainId.toString())
+  }
+
   public async activate(): Promise<ConnectorUpdate> {
     if (!this.supportedChainIds) {
       throw new Error("Supported chain ids are not defined.")
@@ -80,7 +92,7 @@ export class LedgerLiveConnector extends AbstractConnector {
 
     if (!checkSupportResult.isChainIdSupported) {
       throw new Error(
-        `The ${chainIdToNetworkName(
+        `The ${getChainIdToNetworkName(
           chainId
         )} network is not supported by LedgerLive.`
       )
@@ -130,14 +142,12 @@ export class LedgerLiveConnector extends AbstractConnector {
   }
 }
 
-const rpcUrl = getEnvVariable(EnvVariable.ETH_HOSTNAME_HTTP)
-const chainId = +supportedChainId
-
 export const ledgerLive = new LedgerLiveConnector({
-  supportedChainIds: [chainId],
-  rpc: {
-    [Number(supportedChainId)]: rpcUrl as string,
-  },
+  supportedChainIds: supportedNetworks,
+  rpc: networks.reduce((acc, network) => {
+    acc[network.chainId] = getRpcUrl(network.chainId)
+    return acc
+  }, {} as EthereumRpcMap),
   walletConnectProjectId: getEnvVariable(EnvVariable.WALLET_CONNECT_PROJECT_ID),
 })
 
diff --git a/src/web3/hooks/useGetBlock.ts b/src/web3/hooks/useGetBlock.ts
index 99a159c3a..530aa013c 100644
--- a/src/web3/hooks/useGetBlock.ts
+++ b/src/web3/hooks/useGetBlock.ts
@@ -3,7 +3,7 @@ import { BlockTag } from "@ethersproject/abstract-provider"
 import { Web3Provider } from "@ethersproject/providers"
 import { useThreshold } from "../../contexts/ThresholdContext"
 import { getProviderOrSigner } from "../../threshold-ts/utils"
-import { LedgerLiveEthereumSigner } from "@keep-network/tbtc-v2.ts"
+import { LedgerLiveSigner } from "../../utils/ledger"
 
 export const useGetBlock = () => {
   const threshold = useThreshold()
@@ -11,7 +11,7 @@ export const useGetBlock = () => {
 
   return useCallback(
     async (blockTag: BlockTag) => {
-      if (providerOrSigner instanceof LedgerLiveEthereumSigner) {
+      if (providerOrSigner instanceof LedgerLiveSigner) {
         return providerOrSigner.provider!.getBlock(blockTag)
       }
       const provider = getProviderOrSigner(

From 722badd862f5dbc998317f463ea8175f0a7df6ab Mon Sep 17 00:00:00 2001
From: evandrosaturnino <evandro.saturnino@gmail.com>
Date: Tue, 12 Nov 2024 10:26:36 -0300
Subject: [PATCH 05/46] Add networks centralized folder

---
 .../components/IncorrectNetwork.tsx           |   4 +-
 .../components/WalletConnectStatusAlert.tsx   |   2 +-
 .../TransactionModal/TransactionIsPending.tsx |   6 +-
 .../Modal/TransactionSuccessModal/index.tsx   |   5 +-
 .../Modal/UpgradeToTModal/TransactionIdle.tsx |  16 +-
 .../Navbar/WalletConnectionAlert.tsx          |   8 +-
 src/contexts/LedgerLiveAppContext.tsx         |  47 +++++-
 src/enums/web3.ts                             |   6 -
 src/networks/constants/networks.ts            |   7 +
 src/networks/enums/networks.ts                |  57 +++++++
 .../hooks/useDefaultOrConnectedChainId.ts     |   9 ++
 src/networks/types/networks.ts                |  44 ++++++
 .../network.ts => networks/utils/chainId.ts}  |   2 +-
 src/networks/utils/chainIdToTrmNetworkName.ts |  17 +++
 src/networks/utils/connectedNetwork.ts        |  31 ++++
 src/networks/utils/createExplorerLink.ts      |  46 ++++++
 src/networks/utils/getChainIdToNetworkName.ts |  15 ++
 .../utils/getMainnetOrTestnetChainId.ts       |   8 +
 src/networks/utils/getRpcUrl.ts               |  17 +++
 src/networks/utils/index.ts                   |  11 ++
 src/networks/utils/mappings.ts                |  35 +++++
 src/networks/utils/networks.ts                | 142 ++++++++++++++++++
 src/networks/utils/networksAlchemyConfig.ts   |  29 ++++
 .../utils/validateL2TransactionType.ts        |  11 ++
 src/utils/chainIdToNetworkName.ts             |  18 ---
 src/utils/createEtherscanLink.ts              |  45 ------
 src/utils/isSupportedNetwork.ts               |   7 -
 27 files changed, 542 insertions(+), 103 deletions(-)
 create mode 100644 src/networks/constants/networks.ts
 create mode 100644 src/networks/enums/networks.ts
 create mode 100644 src/networks/hooks/useDefaultOrConnectedChainId.ts
 create mode 100644 src/networks/types/networks.ts
 rename src/{web3/utils/network.ts => networks/utils/chainId.ts} (80%)
 create mode 100644 src/networks/utils/chainIdToTrmNetworkName.ts
 create mode 100644 src/networks/utils/connectedNetwork.ts
 create mode 100644 src/networks/utils/createExplorerLink.ts
 create mode 100644 src/networks/utils/getChainIdToNetworkName.ts
 create mode 100644 src/networks/utils/getMainnetOrTestnetChainId.ts
 create mode 100644 src/networks/utils/getRpcUrl.ts
 create mode 100644 src/networks/utils/index.ts
 create mode 100644 src/networks/utils/mappings.ts
 create mode 100644 src/networks/utils/networks.ts
 create mode 100644 src/networks/utils/networksAlchemyConfig.ts
 create mode 100644 src/networks/utils/validateL2TransactionType.ts
 delete mode 100644 src/utils/chainIdToNetworkName.ts
 delete mode 100644 src/utils/createEtherscanLink.ts
 delete mode 100644 src/utils/isSupportedNetwork.ts

diff --git a/src/components/Modal/SelectWalletModal/components/IncorrectNetwork.tsx b/src/components/Modal/SelectWalletModal/components/IncorrectNetwork.tsx
index 49f4a0ea1..355d16888 100644
--- a/src/components/Modal/SelectWalletModal/components/IncorrectNetwork.tsx
+++ b/src/components/Modal/SelectWalletModal/components/IncorrectNetwork.tsx
@@ -6,8 +6,6 @@ import {
   AlertTitle,
   Stack,
 } from "@chakra-ui/react"
-import chainIdToNetworkName from "../../../../utils/chainIdToNetworkName"
-import { supportedChainId } from "../../../../utils/getEnvVariable"
 
 const IncorrectNetworkAlert: FC = () => {
   return (
@@ -16,7 +14,7 @@ const IncorrectNetworkAlert: FC = () => {
       <Stack>
         <AlertTitle>Incorrect Network</AlertTitle>
         <AlertDescription mt={2}>
-          Please connect to {chainIdToNetworkName(supportedChainId)}
+          Please connect to a supported network.
         </AlertDescription>
       </Stack>
     </Alert>
diff --git a/src/components/Modal/SelectWalletModal/components/WalletConnectStatusAlert.tsx b/src/components/Modal/SelectWalletModal/components/WalletConnectStatusAlert.tsx
index 6e9ddfc5d..ed4a6c3d4 100644
--- a/src/components/Modal/SelectWalletModal/components/WalletConnectStatusAlert.tsx
+++ b/src/components/Modal/SelectWalletModal/components/WalletConnectStatusAlert.tsx
@@ -1,7 +1,7 @@
 import { FC } from "react"
 import { AccountSuccessAlert, WalletInitializeAlert } from "./index"
 import WalletRejectedAlert from "./WalletRejectedAlert"
-import isSupportedNetwork from "../../../../utils/isSupportedNetwork"
+import { isSupportedNetwork } from "../../../../networks/utils"
 import { useWeb3React } from "@web3-react/core"
 import IncorrectNetwork from "./IncorrectNetwork"
 
diff --git a/src/components/Modal/TransactionModal/TransactionIsPending.tsx b/src/components/Modal/TransactionModal/TransactionIsPending.tsx
index 3e69e4b02..98da05470 100644
--- a/src/components/Modal/TransactionModal/TransactionIsPending.tsx
+++ b/src/components/Modal/TransactionModal/TransactionIsPending.tsx
@@ -2,12 +2,13 @@ import { FC } from "react"
 import { Box, ModalBody, ModalHeader, ModalFooter } from "@chakra-ui/react"
 import { BodyLg, BodySm } from "@threshold-network/components"
 import ViewInBlockExplorer from "../../ViewInBlockExplorer"
-import { ExplorerDataType } from "../../../utils/createEtherscanLink"
+import { ExplorerDataType } from "../../../networks/enums/networks"
 import withBaseModal from "../withBaseModal"
 import { BaseModalProps } from "../../../types"
 import InfoBox from "../../InfoBox"
 import { ThresholdSpinner } from "../../ThresholdSpinner/ThresholdSpinner"
 import ModalCloseButton from "../ModalCloseButton"
+import { useIsActive } from "../../../hooks/useIsActive"
 
 interface TransactionIsPendingProps extends BaseModalProps {
   pendingText?: string
@@ -18,6 +19,8 @@ const TransactionIsPending: FC<TransactionIsPendingProps> = ({
   transactionHash,
   pendingText = "Pending...",
 }) => {
+  const { chainId } = useIsActive()
+
   return (
     <>
       <ModalHeader>Confirm (pending)</ModalHeader>
@@ -36,6 +39,7 @@ const TransactionIsPending: FC<TransactionIsPendingProps> = ({
             text="View"
             id={transactionHash}
             type={ExplorerDataType.TRANSACTION}
+            ethereumNetworkChainId={chainId}
           />{" "}
           transaction on Etherscan
         </BodySm>
diff --git a/src/components/Modal/TransactionSuccessModal/index.tsx b/src/components/Modal/TransactionSuccessModal/index.tsx
index 7336b6c85..18329e0ff 100644
--- a/src/components/Modal/TransactionSuccessModal/index.tsx
+++ b/src/components/Modal/TransactionSuccessModal/index.tsx
@@ -13,10 +13,11 @@ import Confetti from "react-confetti"
 import Threshold from "../../../static/icons/Ttoken"
 import { BodySm, H5, LineDivider } from "@threshold-network/components"
 import ViewInBlockExplorer from "../../ViewInBlockExplorer"
-import { ExplorerDataType } from "../../../utils/createEtherscanLink"
+import { ExplorerDataType } from "../../../networks/enums/networks"
 import { useModal } from "../../../hooks/useModal"
 import InfoBox from "../../InfoBox"
 import ModalCloseButton from "../ModalCloseButton"
+import { useIsActive } from "../../../hooks/useIsActive"
 
 interface SuccessModalProps {
   title?: string
@@ -32,6 +33,7 @@ const StakingSuccessModal: FC<SuccessModalProps> = ({
   transactionHash,
 }) => {
   const { closeModal } = useModal()
+  const { chainId } = useIsActive()
 
   return (
     <>
@@ -69,6 +71,7 @@ const StakingSuccessModal: FC<SuccessModalProps> = ({
               text="View"
               id={transactionHash}
               type={ExplorerDataType.TRANSACTION}
+              ethereumNetworkChainId={chainId}
             />{" "}
             transaction on Etherscan
           </BodySm>
diff --git a/src/components/Modal/UpgradeToTModal/TransactionIdle.tsx b/src/components/Modal/UpgradeToTModal/TransactionIdle.tsx
index 900aa8f3a..3dcad19ea 100644
--- a/src/components/Modal/UpgradeToTModal/TransactionIdle.tsx
+++ b/src/components/Modal/UpgradeToTModal/TransactionIdle.tsx
@@ -16,7 +16,7 @@ import { useTConvertedAmount } from "../../../hooks/useTConvertedAmount"
 import { useTExchangeRate } from "../../../hooks/useTExchangeRate"
 import { useVendingMachineContract } from "../../../web3/hooks/useVendingMachineContract"
 import { useUpgradeToT } from "../../../web3/hooks/useUpgradeToT"
-import { ExplorerDataType } from "../../../utils/createEtherscanLink"
+import { ExplorerDataType } from "../../../networks/enums/networks"
 import withBaseModal from "../withBaseModal"
 import { BaseModalProps, UpgredableToken } from "../../../types"
 import InfoBox from "../../InfoBox"
@@ -65,11 +65,15 @@ const TransactionIdle: FC<TransactionIdleProps> = ({
           mt="2rem"
         >
           This action is reversible via the{" "}
-          <ViewInBlockExplorer
-            id={contract!.address}
-            type={ExplorerDataType.ADDRESS}
-            text="vending machine contract."
-          />
+          {contract ? (
+            <ViewInBlockExplorer
+              id={contract.address}
+              type={ExplorerDataType.ADDRESS}
+              text="vending machine contract."
+            />
+          ) : (
+            "vending machine contract."
+          )}
         </BodySm>
         <LineDivider />
       </ModalBody>
diff --git a/src/components/Navbar/WalletConnectionAlert.tsx b/src/components/Navbar/WalletConnectionAlert.tsx
index a1f5b9f6d..ac27e287d 100644
--- a/src/components/Navbar/WalletConnectionAlert.tsx
+++ b/src/components/Navbar/WalletConnectionAlert.tsx
@@ -6,9 +6,7 @@ import {
   CloseButton,
 } from "@chakra-ui/react"
 import { FC, useEffect, useState } from "react"
-import isSupportedNetwork from "../../utils/isSupportedNetwork"
-import chainIdToNetworkName from "../../utils/chainIdToNetworkName"
-import { supportedChainId } from "../../utils/getEnvVariable"
+import { isSupportedNetwork } from "../../networks/utils"
 import { useWeb3React } from "@web3-react/core"
 
 const WalletConnectionAlert: FC<{
@@ -36,9 +34,7 @@ const WalletConnectionAlert: FC<{
 
     if (!isSupportedNetwork(chainId)) {
       setAlertDescription(
-        `Your wallet is on an unsupported network. Switch to the ${chainIdToNetworkName(
-          supportedChainId
-        )} network`
+        `Your wallet is on an unsupported network. Switch to a supported network`
       )
       setAlertStatus("warning")
       setHideAlert(false)
diff --git a/src/contexts/LedgerLiveAppContext.tsx b/src/contexts/LedgerLiveAppContext.tsx
index 78f701f18..65f9c5fed 100644
--- a/src/contexts/LedgerLiveAppContext.tsx
+++ b/src/contexts/LedgerLiveAppContext.tsx
@@ -1,14 +1,23 @@
 import { Account } from "@ledgerhq/wallet-api-client"
-import React, { createContext, useCallback, useContext, useState } from "react"
-import { LedgerLiveEthereumSigner } from "@keep-network/tbtc-v2.ts"
-import { ledgerLiveAppEthereumSigner } from "../utils/getLedgerLiveAppEthereumSigner"
+import React, {
+  createContext,
+  useCallback,
+  useContext,
+  useEffect,
+  useMemo,
+  useState,
+} from "react"
+import { LedgerLiveSigner } from "../utils/ledger"
+import { useIsActive } from "../hooks/useIsActive"
+import { getLedgerLiveAppEthereumSigner } from "../utils/getLedgerLiveAppEthereumSigner"
 
 interface LedgerLiveAppContextState {
   ethAccount: Account | undefined
   btcAccount: Account | undefined
   setEthAccount: (ethAccount: Account | undefined) => void
   setBtcAccount: (btcAccount: Account | undefined) => void
-  ledgerLiveAppEthereumSigner: LedgerLiveEthereumSigner | undefined
+  ethAccountChainId: number | undefined
+  ledgerLiveAppEthereumSigner: LedgerLiveSigner | undefined
 }
 
 export const useLedgerLiveApp = () => {
@@ -20,17 +29,38 @@ const LedgerLiveAppContext = createContext<LedgerLiveAppContextState>({
   btcAccount: undefined,
   setEthAccount: () => {},
   setBtcAccount: () => {},
+  ethAccountChainId: undefined,
   ledgerLiveAppEthereumSigner: undefined,
 })
 
 export const LedgerLiveAppProvider: React.FC = ({ children }) => {
+  const { chainId } = useIsActive()
   const [ethAccount, _setEthAccount] = useState<Account | undefined>(undefined)
+  const [ethAccountChainId, setEthAccountChainId] = useState<
+    number | undefined
+  >(undefined)
   const [btcAccount, setBtcAccount] = useState<Account | undefined>(undefined)
 
-  const setEthAccount = useCallback((ethAccount: Account | undefined) => {
-    ledgerLiveAppEthereumSigner.setAccount(ethAccount)
-    _setEthAccount(ethAccount)
-  }, [])
+  const ledgerLiveAppEthereumSigner = useMemo(() => {
+    return getLedgerLiveAppEthereumSigner(chainId)
+  }, [chainId])
+
+  const setEthAccount = useCallback(
+    async (ethAccount: Account | undefined) => {
+      ledgerLiveAppEthereumSigner.setAccount(ethAccount)
+      const chainId = await ledgerLiveAppEthereumSigner.getChainId()
+      setEthAccountChainId(chainId)
+      _setEthAccount(ethAccount)
+    },
+    [ledgerLiveAppEthereumSigner]
+  )
+
+  // Effect to set the account on the signer whenever the signer or account changes
+  useEffect(() => {
+    if (ethAccount) {
+      setEthAccount(ethAccount)
+    }
+  }, [ledgerLiveAppEthereumSigner, setEthAccount])
 
   return (
     <LedgerLiveAppContext.Provider
@@ -39,6 +69,7 @@ export const LedgerLiveAppProvider: React.FC = ({ children }) => {
         setEthAccount,
         btcAccount,
         setBtcAccount,
+        ethAccountChainId,
         ledgerLiveAppEthereumSigner,
       }}
     >
diff --git a/src/enums/web3.ts b/src/enums/web3.ts
index 752ece5ad..11c6686f1 100644
--- a/src/enums/web3.ts
+++ b/src/enums/web3.ts
@@ -1,9 +1,3 @@
-export enum ChainID {
-  Ethereum = 1,
-  Sepolia = 11155111,
-  Localhost = 1337,
-}
-
 export enum ConnectionError {
   MetamaskNotInstalled = "No Ethereum provider was found on window.ethereum",
   RejectedMetamaskConnection = "The user rejected the request.",
diff --git a/src/networks/constants/networks.ts b/src/networks/constants/networks.ts
new file mode 100644
index 000000000..8e571b10a
--- /dev/null
+++ b/src/networks/constants/networks.ts
@@ -0,0 +1,7 @@
+import { AllowedL2TransactionTypes } from "../enums/networks"
+
+export const DECIMALS = 18
+export const ETH_SYMBOL = "ETH"
+export const ALLOWED_L2_TRANSACTIONS: AllowedL2TransactionTypes[] = [
+  AllowedL2TransactionTypes.mint,
+]
diff --git a/src/networks/enums/networks.ts b/src/networks/enums/networks.ts
new file mode 100644
index 000000000..0580aaa12
--- /dev/null
+++ b/src/networks/enums/networks.ts
@@ -0,0 +1,57 @@
+export enum AllowedL2TransactionTypes {
+  mint = "MINT",
+}
+
+export enum TrmNetworksChainId {
+  ethereum = 1,
+  arbitrum = 42161,
+  base = 8453,
+}
+
+export enum SupportedChainIds {
+  Ethereum = 1,
+  Sepolia = 11155111,
+  Localhost = 1337,
+  Arbitrum = 42161,
+  ArbitrumSepolia = 421614,
+  Base = 8453,
+  BaseSepolia = 84532,
+}
+
+export enum AlchemyName {
+  Ethereum = "eth",
+  Arbitrum = "arb",
+  Base = "base",
+}
+
+export enum NetworkType {
+  Mainnet = "mainnet",
+  Testnet = "sepolia",
+}
+
+export enum Layer {
+  L1 = "L1",
+  L2 = "L2",
+}
+
+export enum NativeCurrency {
+  Ether = "Ether",
+  SepoliaEther = "Sepolia Ether",
+}
+
+export enum ExplorerDataType {
+  TRANSACTION = "transaction",
+  TOKEN = "token",
+  ADDRESS = "address",
+  BLOCK = "block",
+}
+
+export enum PublicRpcUrls {
+  Ethereum = "https://eth.drpc.org",
+  Sepolia = "https://sepolia.drpc.org",
+  Localhost = "http://localhost:8545",
+  Arbitrum = "https://arbitrum.drpc.org",
+  ArbitrumSepolia = "https://arbitrum-sepolia.drpc.org",
+  Base = "https://base.drpc.org",
+  BaseSepolia = "https://base-sepolia.drpc.org",
+}
diff --git a/src/networks/hooks/useDefaultOrConnectedChainId.ts b/src/networks/hooks/useDefaultOrConnectedChainId.ts
new file mode 100644
index 000000000..fe023a21f
--- /dev/null
+++ b/src/networks/hooks/useDefaultOrConnectedChainId.ts
@@ -0,0 +1,9 @@
+import { useIsActive } from "../../hooks/useIsActive"
+import { getDefaultProviderChainId } from "../../utils/getEnvVariable"
+
+export const useDefaultOrConnectedChainId = () => {
+  const { chainId } = useIsActive()
+  const defaultOrConnectedChainId = chainId ?? getDefaultProviderChainId()
+
+  return defaultOrConnectedChainId
+}
diff --git a/src/networks/types/networks.ts b/src/networks/types/networks.ts
new file mode 100644
index 000000000..4c6e630be
--- /dev/null
+++ b/src/networks/types/networks.ts
@@ -0,0 +1,44 @@
+import { Chains } from "@keep-network/tbtc-v2.ts"
+import {
+  Layer,
+  NetworkType,
+  SupportedChainIds,
+  AlchemyName,
+} from "../enums/networks"
+
+export interface NetworksAlchemyConfig {
+  [chainId: number]: {
+    name: AlchemyName
+    type: NetworkType
+  }
+}
+
+export interface EthereumRpcMap {
+  [chainId: string]: string
+}
+
+export type NetworkName = keyof typeof SupportedChainIds
+export interface Network {
+  chainId: SupportedChainIds
+  name: keyof typeof Chains
+  layer: Layer
+  networkType: NetworkType
+  chainParameters: {
+    chainId: string
+    chainName: string
+    nativeCurrency: {
+      name: string
+      symbol: string
+      decimals: number
+    }
+    rpcUrls: string[]
+    blockExplorerUrls: string[]
+  }
+  alchemyName?: AlchemyName
+}
+
+export type TrmNetworksMap = {
+  [chainId: number]: string
+}
+
+export type NetworkMapping = Record<number, NetworkName>
diff --git a/src/web3/utils/network.ts b/src/networks/utils/chainId.ts
similarity index 80%
rename from src/web3/utils/network.ts
rename to src/networks/utils/chainId.ts
index bccf6f080..807fe3d4a 100644
--- a/src/web3/utils/network.ts
+++ b/src/networks/utils/chainId.ts
@@ -1,7 +1,7 @@
 import { ethers } from "ethers"
 
 export const toHex = (value: string | number): string =>
-  ethers.utils.hexlify(value)
+  ethers.utils.hexValue(ethers.BigNumber.from(value))
 
 export const isSameChainId = (
   chainId1: string | number,
diff --git a/src/networks/utils/chainIdToTrmNetworkName.ts b/src/networks/utils/chainIdToTrmNetworkName.ts
new file mode 100644
index 000000000..05d144864
--- /dev/null
+++ b/src/networks/utils/chainIdToTrmNetworkName.ts
@@ -0,0 +1,17 @@
+import { SupportedChainIds, TrmNetworksChainId } from "../enums/networks"
+import { TrmNetworksMap } from "../types/networks"
+
+export const trmNetworksMap: TrmNetworksMap = {
+  [TrmNetworksChainId.ethereum]: "ethereum",
+  [TrmNetworksChainId.arbitrum]: "arbitrum",
+  [TrmNetworksChainId.base]: "base",
+}
+
+export const chainIdToTrmNetworkName = (
+  chainId?: string | number
+): TrmNetworksMap => {
+  const network =
+    trmNetworksMap[Number(chainId)] ||
+    trmNetworksMap[SupportedChainIds.Ethereum]
+  return network
+}
diff --git a/src/networks/utils/connectedNetwork.ts b/src/networks/utils/connectedNetwork.ts
new file mode 100644
index 000000000..f0a54d1ce
--- /dev/null
+++ b/src/networks/utils/connectedNetwork.ts
@@ -0,0 +1,31 @@
+import { getChainIdToNetworkName } from "./getChainIdToNetworkName"
+import {
+  l1MainnetNetworksMap,
+  l1TestNetworksMap,
+  l2MainnetNetworksMap,
+  l2TestNetworksMap,
+  testNetworksMap,
+} from "./mappings"
+
+export const isSupportedNetwork = (chainId?: string | number): boolean => {
+  return getChainIdToNetworkName(chainId) !== "Unsupported"
+}
+
+export const isTestnetNetwork = (networkChainId: string | number): boolean => {
+  return !!testNetworksMap[Number(networkChainId)]
+}
+
+export const isL2Network = (networkChainId?: string | number): boolean => {
+  const chainId = Number(networkChainId)
+  return !!l2MainnetNetworksMap[chainId] || !!l2TestNetworksMap[chainId]
+}
+
+export const isL1Network = (networkChainId?: string | number): boolean => {
+  const chainId = Number(networkChainId)
+  return !!l1MainnetNetworksMap[chainId] || !!l1TestNetworksMap[chainId]
+}
+
+export const isL1Mainnet = (networkChainId?: string | number): boolean => {
+  const chainId = Number(networkChainId)
+  return !!l1MainnetNetworksMap[chainId]
+}
diff --git a/src/networks/utils/createExplorerLink.ts b/src/networks/utils/createExplorerLink.ts
new file mode 100644
index 000000000..1d6c8db7f
--- /dev/null
+++ b/src/networks/utils/createExplorerLink.ts
@@ -0,0 +1,46 @@
+import { ExplorerDataType, SupportedChainIds } from "../enums/networks"
+
+export const createBlockExplorerLink = (
+  prefix: string,
+  id: string,
+  type: ExplorerDataType
+) => {
+  switch (type) {
+    case ExplorerDataType.TRANSACTION: {
+      return `${prefix}/tx/${id}`
+    }
+    case ExplorerDataType.TOKEN: {
+      return `${prefix}/token/${id}`
+    }
+    case ExplorerDataType.BLOCK: {
+      return `${prefix}/block/${id}`
+    }
+    case ExplorerDataType.ADDRESS:
+    default: {
+      return `${prefix}/address/${id}`
+    }
+  }
+}
+
+export const createExplorerPrefix = (
+  chainId: number | string | undefined
+): string => {
+  const prefixMap: { [key: number]: string } = {
+    [SupportedChainIds.Sepolia]: "https://sepolia.etherscan.io",
+    [SupportedChainIds.Arbitrum]: "https://arbiscan.io",
+    [SupportedChainIds.ArbitrumSepolia]: "https://sepolia.arbiscan.io",
+    [SupportedChainIds.Base]: "https://basescan.org",
+    [SupportedChainIds.BaseSepolia]: "https://sepolia.basescan.org",
+  }
+
+  return prefixMap[Number(chainId)] || "https://etherscan.io"
+}
+
+export const createExplorerLink = (
+  chainId: number | string | undefined,
+  address: string,
+  type: ExplorerDataType
+): string => {
+  const prefix = createExplorerPrefix(chainId)
+  return createBlockExplorerLink(prefix, address, type)
+}
diff --git a/src/networks/utils/getChainIdToNetworkName.ts b/src/networks/utils/getChainIdToNetworkName.ts
new file mode 100644
index 000000000..9c5f977b2
--- /dev/null
+++ b/src/networks/utils/getChainIdToNetworkName.ts
@@ -0,0 +1,15 @@
+import { networks } from "./networks"
+
+export function getChainIdToNetworkName(chainId?: number | string): string {
+  const network = networks.find(
+    (network) => network.chainId === Number(chainId)
+  )
+  return network ? network.name : "Unsupported"
+}
+
+export const chainIdToChainParameterName = (chainId?: string | number) => {
+  const network = networks.find(
+    (network) => network.chainId === Number(chainId)
+  )
+  return network?.chainParameters?.chainName || "Unsupported"
+}
diff --git a/src/networks/utils/getMainnetOrTestnetChainId.ts b/src/networks/utils/getMainnetOrTestnetChainId.ts
new file mode 100644
index 000000000..cda5009c9
--- /dev/null
+++ b/src/networks/utils/getMainnetOrTestnetChainId.ts
@@ -0,0 +1,8 @@
+import { SupportedChainIds } from "../enums/networks"
+import { isTestnetNetwork } from "../utils"
+
+export const getMainnetOrTestnetChainId = (chainId: number | string) => {
+  return isTestnetNetwork(chainId)
+    ? SupportedChainIds.Sepolia
+    : SupportedChainIds.Ethereum
+}
diff --git a/src/networks/utils/getRpcUrl.ts b/src/networks/utils/getRpcUrl.ts
new file mode 100644
index 000000000..fc05d6337
--- /dev/null
+++ b/src/networks/utils/getRpcUrl.ts
@@ -0,0 +1,17 @@
+import { EnvVariable } from "../../enums"
+import { getEnvVariable } from "../../utils/getEnvVariable"
+import { SupportedChainIds } from "../enums/networks"
+import { networksAlchemyConfig } from "./networksAlchemyConfig"
+
+const MAIN_ALCHEMY_URL = "g.alchemy.com/v2/"
+
+export const getRpcUrl = (chainId?: number | string) => {
+  const alchemyApi = getEnvVariable(EnvVariable.ALCHEMY_API)
+  const defaultChainId = SupportedChainIds.Ethereum
+  const chainIdNum = Number(chainId) || defaultChainId
+  const alchemyConfig = networksAlchemyConfig[chainIdNum]
+
+  return alchemyConfig?.name
+    ? `https://${alchemyConfig.name}-${alchemyConfig.type}.${MAIN_ALCHEMY_URL}${alchemyApi}`
+    : `http://localhost:8545`
+}
diff --git a/src/networks/utils/index.ts b/src/networks/utils/index.ts
new file mode 100644
index 000000000..bb8a72361
--- /dev/null
+++ b/src/networks/utils/index.ts
@@ -0,0 +1,11 @@
+export * from "./chainId"
+export * from "./getChainIdToNetworkName"
+export * from "./chainIdToTrmNetworkName"
+export * from "./connectedNetwork"
+export * from "./createExplorerLink"
+export * from "./getRpcUrl"
+export * from "./mappings"
+export * from "./networks"
+export * from "./validateL2TransactionType"
+export * from "./networksAlchemyConfig"
+export * from "./getMainnetOrTestnetChainId"
diff --git a/src/networks/utils/mappings.ts b/src/networks/utils/mappings.ts
new file mode 100644
index 000000000..2c0bda024
--- /dev/null
+++ b/src/networks/utils/mappings.ts
@@ -0,0 +1,35 @@
+import { Layer, NetworkType } from "../enums/networks"
+import { NetworkMapping } from "../types/networks"
+import { networks } from "./networks"
+
+export const supportedNetworksMap: NetworkMapping = {}
+export const l1TestNetworksMap: NetworkMapping = {}
+export const l1MainnetNetworksMap: NetworkMapping = {}
+export const l2TestNetworksMap: NetworkMapping = {}
+export const l2MainnetNetworksMap: NetworkMapping = {}
+export const testNetworksMap: NetworkMapping = {}
+
+networks.forEach((network) => {
+  const { chainId, name, layer, networkType } = network
+  supportedNetworksMap[chainId] = name
+
+  if (layer === Layer.L1 && networkType === NetworkType.Testnet) {
+    l1TestNetworksMap[chainId] = name
+  }
+
+  if (layer === Layer.L1 && networkType === NetworkType.Mainnet) {
+    l1MainnetNetworksMap[chainId] = name
+  }
+
+  if (layer === Layer.L2 && networkType === NetworkType.Testnet) {
+    l2TestNetworksMap[chainId] = name
+  }
+
+  if (layer === Layer.L2 && networkType === NetworkType.Mainnet) {
+    l2MainnetNetworksMap[chainId] = name
+  }
+
+  if (networkType === NetworkType.Testnet) {
+    testNetworksMap[chainId] = name
+  }
+})
diff --git a/src/networks/utils/networks.ts b/src/networks/utils/networks.ts
new file mode 100644
index 000000000..8d37d6268
--- /dev/null
+++ b/src/networks/utils/networks.ts
@@ -0,0 +1,142 @@
+import {
+  AlchemyName,
+  Layer,
+  NetworkType,
+  SupportedChainIds,
+  NativeCurrency,
+  PublicRpcUrls,
+} from "../enums/networks"
+import { Network } from "../types/networks"
+import { DECIMALS, ETH_SYMBOL } from "../constants/networks"
+import { toHex } from "./chainId"
+import { createExplorerPrefix } from "./createExplorerLink"
+
+export const networks: Network[] = [
+  {
+    chainId: SupportedChainIds.Ethereum,
+    name: "Ethereum",
+    layer: Layer.L1,
+    networkType: NetworkType.Mainnet,
+    alchemyName: AlchemyName.Ethereum,
+    chainParameters: {
+      chainId: toHex(SupportedChainIds.Ethereum),
+      chainName: "Ethereum Mainnet",
+      nativeCurrency: {
+        name: NativeCurrency.Ether,
+        symbol: ETH_SYMBOL,
+        decimals: DECIMALS,
+      },
+      rpcUrls: [PublicRpcUrls.Ethereum],
+      blockExplorerUrls: [createExplorerPrefix(SupportedChainIds.Ethereum)],
+    },
+  },
+  {
+    chainId: SupportedChainIds.Arbitrum,
+    name: "Arbitrum",
+    layer: Layer.L2,
+    networkType: NetworkType.Mainnet,
+    alchemyName: AlchemyName.Arbitrum,
+    chainParameters: {
+      chainId: toHex(SupportedChainIds.Arbitrum),
+      chainName: "Arbitrum One",
+      nativeCurrency: {
+        name: NativeCurrency.Ether,
+        symbol: ETH_SYMBOL,
+        decimals: DECIMALS,
+      },
+      rpcUrls: [PublicRpcUrls.Arbitrum],
+      blockExplorerUrls: [createExplorerPrefix(SupportedChainIds.Arbitrum)],
+    },
+  },
+  {
+    chainId: SupportedChainIds.Localhost,
+    name: "Ethereum",
+    layer: Layer.L1,
+    networkType: NetworkType.Testnet,
+    chainParameters: {
+      chainId: toHex(SupportedChainIds.Localhost),
+      chainName: "Localhost",
+      nativeCurrency: {
+        name: NativeCurrency.Ether,
+        symbol: ETH_SYMBOL,
+        decimals: DECIMALS,
+      },
+      rpcUrls: [PublicRpcUrls.Localhost],
+      blockExplorerUrls: ["http://localhost:8545"],
+    },
+  },
+  // {
+  //   chainId: SupportedChainIds.Base,
+  //   name: "Base",
+  //   layer: Layer.L2,
+  //   networkType: NetworkType.Mainnet,
+  //   alchemyName: AlchemyName.Base,
+  //   chainParameters: {
+  //     chainId: toHex(SupportedChainIds.Base),
+  //     chainName: "Base Mainnet",
+  //     nativeCurrency: {
+  //       name: NativeCurrency.Ether,
+  //       symbol: ETH_SYMBOL,
+  //       decimals: DECIMALS,
+  //     },
+  //     rpcUrls: [PublicRpcUrls.Base],
+  //     blockExplorerUrls: [createExplorerPrefix(SupportedChainIds.Base)],
+  //   },
+  // },
+  {
+    chainId: SupportedChainIds.Sepolia,
+    name: "Ethereum",
+    layer: Layer.L1,
+    networkType: NetworkType.Testnet,
+    alchemyName: AlchemyName.Ethereum,
+    chainParameters: {
+      chainId: toHex(SupportedChainIds.Sepolia),
+      chainName: "Sepolia Testnet",
+      nativeCurrency: {
+        name: NativeCurrency.SepoliaEther,
+        symbol: ETH_SYMBOL,
+        decimals: DECIMALS,
+      },
+      rpcUrls: [PublicRpcUrls.Sepolia],
+      blockExplorerUrls: [createExplorerPrefix(SupportedChainIds.Sepolia)],
+    },
+  },
+  {
+    chainId: SupportedChainIds.ArbitrumSepolia,
+    name: "Arbitrum",
+    layer: Layer.L2,
+    networkType: NetworkType.Testnet,
+    alchemyName: AlchemyName.Arbitrum,
+    chainParameters: {
+      chainId: toHex(SupportedChainIds.ArbitrumSepolia),
+      chainName: "Arbitrum Sepolia",
+      nativeCurrency: {
+        name: NativeCurrency.SepoliaEther,
+        symbol: ETH_SYMBOL,
+        decimals: DECIMALS,
+      },
+      rpcUrls: [PublicRpcUrls.ArbitrumSepolia],
+      blockExplorerUrls: [
+        createExplorerPrefix(SupportedChainIds.ArbitrumSepolia),
+      ],
+    },
+  },
+  {
+    chainId: SupportedChainIds.BaseSepolia,
+    name: "Base",
+    layer: Layer.L2,
+    networkType: NetworkType.Testnet,
+    alchemyName: AlchemyName.Base,
+    chainParameters: {
+      chainId: toHex(SupportedChainIds.BaseSepolia),
+      chainName: "Base Sepolia",
+      nativeCurrency: {
+        name: NativeCurrency.SepoliaEther,
+        symbol: ETH_SYMBOL,
+        decimals: DECIMALS,
+      },
+      rpcUrls: [PublicRpcUrls.BaseSepolia],
+      blockExplorerUrls: [createExplorerPrefix(SupportedChainIds.BaseSepolia)],
+    },
+  },
+]
diff --git a/src/networks/utils/networksAlchemyConfig.ts b/src/networks/utils/networksAlchemyConfig.ts
new file mode 100644
index 000000000..b21543d11
--- /dev/null
+++ b/src/networks/utils/networksAlchemyConfig.ts
@@ -0,0 +1,29 @@
+import { AlchemyName, NetworkType, SupportedChainIds } from "../enums/networks"
+import { NetworksAlchemyConfig } from "../types/networks"
+
+export const networksAlchemyConfig: NetworksAlchemyConfig = {
+  [SupportedChainIds.Ethereum]: {
+    name: AlchemyName.Ethereum,
+    type: NetworkType.Mainnet,
+  },
+  [SupportedChainIds.Sepolia]: {
+    name: AlchemyName.Ethereum,
+    type: NetworkType.Testnet,
+  },
+  [SupportedChainIds.Arbitrum]: {
+    name: AlchemyName.Arbitrum,
+    type: NetworkType.Mainnet,
+  },
+  [SupportedChainIds.ArbitrumSepolia]: {
+    name: AlchemyName.Arbitrum,
+    type: NetworkType.Testnet,
+  },
+  [SupportedChainIds.Base]: {
+    name: AlchemyName.Base,
+    type: NetworkType.Mainnet,
+  },
+  [SupportedChainIds.BaseSepolia]: {
+    name: AlchemyName.Base,
+    type: NetworkType.Testnet,
+  },
+}
diff --git a/src/networks/utils/validateL2TransactionType.ts b/src/networks/utils/validateL2TransactionType.ts
new file mode 100644
index 000000000..0af9f1c62
--- /dev/null
+++ b/src/networks/utils/validateL2TransactionType.ts
@@ -0,0 +1,11 @@
+import { ALLOWED_L2_TRANSACTIONS } from "../constants/networks"
+import { AllowedL2TransactionTypes } from "../enums/networks"
+
+export function isValidL2Transaction<T = AllowedL2TransactionTypes>(
+  type?: T
+): boolean {
+  if (!type) return false
+  return ALLOWED_L2_TRANSACTIONS.includes(
+    type as unknown as AllowedL2TransactionTypes
+  )
+}
diff --git a/src/utils/chainIdToNetworkName.ts b/src/utils/chainIdToNetworkName.ts
deleted file mode 100644
index 1067d29e5..000000000
--- a/src/utils/chainIdToNetworkName.ts
+++ /dev/null
@@ -1,18 +0,0 @@
-import { ChainID } from "../enums"
-
-type NetworkMap = {
-  [chainId: number]: string
-}
-
-const networkMap: NetworkMap = {
-  [ChainID.Ethereum]: "Ethereum",
-  [ChainID.Sepolia]: "Sepolia Test",
-  [ChainID.Localhost]: "Localhost",
-}
-
-const chainIdToNetworkName = (chainId: string | number = 1): string => {
-  const network = networkMap[Number(chainId)]
-  return network || "Unsupported"
-}
-
-export default chainIdToNetworkName
diff --git a/src/utils/createEtherscanLink.ts b/src/utils/createEtherscanLink.ts
deleted file mode 100644
index 78e9a0373..000000000
--- a/src/utils/createEtherscanLink.ts
+++ /dev/null
@@ -1,45 +0,0 @@
-const ETHERSCAN_PREFIXES: { [chainId: number]: string } = {
-  1: "",
-  11155111: "sepolia.",
-}
-
-export enum ExplorerDataType {
-  TRANSACTION = "transaction",
-  TOKEN = "token",
-  ADDRESS = "address",
-  BLOCK = "block",
-}
-
-export const createBlockExplorerLink = (
-  prefix: string,
-  id: string,
-  type: ExplorerDataType
-) => {
-  switch (type) {
-    case ExplorerDataType.TRANSACTION: {
-      return `${prefix}/tx/${id}`
-    }
-    case ExplorerDataType.TOKEN: {
-      return `${prefix}/token/${id}`
-    }
-    case ExplorerDataType.BLOCK: {
-      return `${prefix}/block/${id}`
-    }
-    case ExplorerDataType.ADDRESS:
-    default: {
-      return `${prefix}/address/${id}`
-    }
-  }
-}
-
-const createEtherscanLink = (
-  chainId: number,
-  address: string,
-  type: ExplorerDataType
-): string => {
-  const prefix = `https://${ETHERSCAN_PREFIXES[chainId] ?? ""}etherscan.io`
-
-  return createBlockExplorerLink(prefix, address, type)
-}
-
-export default createEtherscanLink
diff --git a/src/utils/isSupportedNetwork.ts b/src/utils/isSupportedNetwork.ts
deleted file mode 100644
index 48d7dceb8..000000000
--- a/src/utils/isSupportedNetwork.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-import { supportedChainId } from "./getEnvVariable"
-
-const isSupportedNetwork = (networkChainId?: number) => {
-  return networkChainId === Number(supportedChainId)
-}
-
-export default isSupportedNetwork

From 921f48eb813a933aced5b0f26f3522e99d8c8cc5 Mon Sep 17 00:00:00 2001
From: evandrosaturnino <evandro.saturnino@gmail.com>
Date: Tue, 12 Nov 2024 10:36:44 -0300
Subject: [PATCH 06/46] Update contract initialization handling

---
 .../index.tsx                                 |    5 +
 src/contexts/TokenContext.tsx                 |   17 +-
 .../useAuthorizeMultipleAppsTransaction.ts    |    2 +-
 .../useBondOperatorTransaction.ts             |    2 +-
 .../useConfirmDeatuhorizationTransaction.ts   |    2 +-
 .../useIncreaseAuthorizationTransaction.ts    |    2 +-
 .../useInitiateDeauthorization.ts             |    2 +-
 .../useRegisterOperatorTransaction.ts         |    2 +-
 .../useStakingAppContract.ts                  |   14 +-
 .../useStakingApplicationAddress.ts           |    5 +-
 ...eSubscribeToAuthorizationIncreasedEvent.ts |    7 +
 .../useUpdateOperatorStatus.tsx               |    2 +-
 src/hooks/tbtc/useFetchDepositDetails.ts      |    8 +-
 src/hooks/useCheckBonusEligibility.ts         |   17 +-
 src/hooks/useFetchOwnerStakes.ts              |    2 +-
 src/hooks/useFetchStakingRewards.ts           |    6 +-
 src/hooks/useFetchTvl.ts                      |  128 +-
 src/hooks/useTBTCBridgeContractAddress.ts     |    2 +-
 src/hooks/useTBTCTokenAddress.ts              |    2 +-
 src/hooks/useTokensBalanceCall.ts             |    4 +-
 .../StakingOverview/LegacyStakesCard.tsx      |    2 +-
 .../StakingOverview/ThresholdStakesCard.tsx   |    2 +-
 src/store/account/effects.ts                  |    7 +-
 src/store/staking-applications/effects.ts     |    9 +-
 src/store/staking/effects.ts                  |    3 +-
 .../TacoRegistry.json                         | 1352 +++++++
 src/threshold-ts/mas/index.ts                 |   38 +-
 .../mas/mainnet-artifacts/TacoRegistry.json   | 1646 +++++++++
 .../mas/sepolia-artifacts/TacoRegistry.json   | 1431 ++++++++
 .../multicall/__test__/multicall.test.ts      |    4 +-
 src/threshold-ts/multicall/index.ts           |   14 +-
 .../LegacyKeepStaking.json                    |  915 +++++
 .../TokenStaking.json                         | 1591 ++++++++
 src/threshold-ts/staking/index.ts             |   31 +-
 .../mainnet-artifacts/LegacyKeepStaking.json  |  915 +++++
 .../mainnet-artifacts/TokenStaking.json       | 1591 ++++++++
 .../sepolia-artifacts/LegacyKeepStaking.json  |  915 +++++
 .../sepolia-artifacts/TokenStaking.json       | 1591 ++++++++
 .../RandomBeacon.json                         | 3269 +++++++++++++++++
 .../tbtc/mainnet-artifacts/RandomBeacon.json  | 3269 +++++++++++++++++
 .../tbtc/sepolia-artifacts/RandomBeacon.json  | 3269 +++++++++++++++++
 src/threshold-ts/utils/contract.ts            |   41 +-
 src/threshold-ts/vending-machine/index.ts     |    2 +-
 src/utils/getStakingAppLabel.ts               |   25 +-
 src/web3/abi/TokenStaking.json                | 1588 ++++++++
 .../hooks/useCheckDuplicateProviderAddress.ts |   12 +-
 src/web3/hooks/useContract.ts                 |    8 +-
 src/web3/hooks/useERC20.ts                    |    2 +-
 src/web3/hooks/useKeep.ts                     |   16 +-
 src/web3/hooks/useKeepBondingContract.ts      |   19 +-
 src/web3/hooks/useKeepTokenStakingContract.ts |   20 +-
 src/web3/hooks/useMerkleDropContract.ts       |   29 +-
 src/web3/hooks/useMulticall.ts                |   20 +-
 src/web3/hooks/useMulticallContract.ts        |   21 +-
 src/web3/hooks/useNu.ts                       |   25 +-
 src/web3/hooks/useNuStakingEscrowContract.ts  |    2 +-
 src/web3/hooks/usePREContract.ts              |   22 +-
 src/web3/hooks/useT.ts                        |   14 +-
 src/web3/hooks/useTBTCTokenContract.ts        |   16 +-
 src/web3/hooks/useTBTCv2TokenContract.ts      |   22 +-
 src/web3/hooks/useTStakingContract.ts         |   32 +-
 src/web3/hooks/useVendingMachineContract.ts   |    4 +
 src/web3/hooks/useVendingMachineRatio.ts      |   19 +-
 src/web3/utils/index.ts                       |    1 -
 64 files changed, 23800 insertions(+), 255 deletions(-)
 create mode 100644 src/threshold-ts/mas/dapp-development-sepolia-artifacts/TacoRegistry.json
 create mode 100644 src/threshold-ts/mas/mainnet-artifacts/TacoRegistry.json
 create mode 100644 src/threshold-ts/mas/sepolia-artifacts/TacoRegistry.json
 create mode 100644 src/threshold-ts/staking/dapp-development-sepolia-artifacts/LegacyKeepStaking.json
 create mode 100644 src/threshold-ts/staking/dapp-development-sepolia-artifacts/TokenStaking.json
 create mode 100644 src/threshold-ts/staking/mainnet-artifacts/LegacyKeepStaking.json
 create mode 100644 src/threshold-ts/staking/mainnet-artifacts/TokenStaking.json
 create mode 100644 src/threshold-ts/staking/sepolia-artifacts/LegacyKeepStaking.json
 create mode 100644 src/threshold-ts/staking/sepolia-artifacts/TokenStaking.json
 create mode 100644 src/threshold-ts/tbtc/dapp-development-sepolia-artifacts/RandomBeacon.json
 create mode 100644 src/threshold-ts/tbtc/mainnet-artifacts/RandomBeacon.json
 create mode 100644 src/threshold-ts/tbtc/sepolia-artifacts/RandomBeacon.json
 create mode 100644 src/web3/abi/TokenStaking.json

diff --git a/src/components/Modal/MapOperatorToStakingProviderModal/index.tsx b/src/components/Modal/MapOperatorToStakingProviderModal/index.tsx
index e7d967f74..174cdd689 100644
--- a/src/components/Modal/MapOperatorToStakingProviderModal/index.tsx
+++ b/src/components/Modal/MapOperatorToStakingProviderModal/index.tsx
@@ -72,6 +72,11 @@ const MapOperatorToStakingProviderModal: FC<
     appName: string
   ) => Promise<boolean> = async (operator: string, appName: string) => {
     let stakingProviderMapped
+    if (!threshold.multiAppStaking) {
+      console.warn("MultiAppStaking contract is not available")
+      return false
+    }
+
     switch (appName) {
       case "tbtc":
         const stakingProviderMappedEcdsa =
diff --git a/src/contexts/TokenContext.tsx b/src/contexts/TokenContext.tsx
index a3ac62878..663485bf6 100644
--- a/src/contexts/TokenContext.tsx
+++ b/src/contexts/TokenContext.tsx
@@ -1,7 +1,6 @@
 import React, { createContext } from "react"
 import { Contract } from "@ethersproject/contracts"
 import { AddressZero } from "@ethersproject/constants"
-import { useWeb3React } from "@web3-react/core"
 import { useKeep } from "../web3/hooks/useKeep"
 import { useNu } from "../web3/hooks/useNu"
 import { useT } from "../web3/hooks/useT"
@@ -15,6 +14,7 @@ import { useFetchOwnerStakes } from "../hooks/useFetchOwnerStakes"
 import { useTBTCv2TokenContract } from "../web3/hooks/useTBTCv2TokenContract"
 import { featureFlags } from "../constants"
 import { useIsActive } from "../hooks/useIsActive"
+import { isL1Network } from "../networks/utils/connectedNetwork"
 
 interface TokenContextState extends TokenState {
   contract: Contract | null
@@ -56,9 +56,12 @@ export const TokenContextProvider: React.FC = ({ children }) => {
     tbtcv2: tbtcv2Data,
   } = useTokenState()
 
-  const tokenContracts = [keep.contract!, nu.contract!, t.contract!]
-
-  if (featureFlags.TBTC_V2) tokenContracts.push(tbtcv2)
+  const tokenContracts = [
+    keep.contract!,
+    nu.contract!,
+    t.contract!,
+    tbtcv2.contract!,
+  ]
 
   const fetchBalances = useTokensBalanceCall(
     tokenContracts,
@@ -89,13 +92,13 @@ export const TokenContextProvider: React.FC = ({ children }) => {
   // FETCH BALANCES ON WALLET LOAD OR NETWORK SWITCH
   //
   React.useEffect(() => {
-    if (isActive) {
+    if (isActive && isL1Network(chainId)) {
       setTokenLoading(Token.Keep, true)
       setTokenLoading(Token.Nu, true)
       setTokenLoading(Token.T, true)
       setTokenLoading(Token.TBTCV2, true)
       fetchBalances().then(
-        ([keepBalance, nuBalance, tBalance, tbtcv2Balance]) => {
+        ([keepBalance = 0, nuBalance = 0, tBalance = 0, tbtcv2Balance = 0]) => {
           setTokenBalance(Token.Keep, keepBalance.toString())
           setTokenLoading(Token.Keep, false)
           setTokenIsLoadedFromConnectedAccount(Token.Keep, true)
@@ -154,7 +157,7 @@ export const TokenContextProvider: React.FC = ({ children }) => {
           ...tbtcData,
         },
         [Token.TBTCV2]: {
-          contract: tbtcv2,
+          ...tbtcv2,
           ...tbtcv2Data,
         },
       }}
diff --git a/src/hooks/staking-applications/useAuthorizeMultipleAppsTransaction.ts b/src/hooks/staking-applications/useAuthorizeMultipleAppsTransaction.ts
index 77fc0cb60..716eacea4 100644
--- a/src/hooks/staking-applications/useAuthorizeMultipleAppsTransaction.ts
+++ b/src/hooks/staking-applications/useAuthorizeMultipleAppsTransaction.ts
@@ -14,7 +14,7 @@ export const useAuthorizeMultipleAppsTransaction = () => {
   const { openModal } = useModal()
 
   const { sendTransaction, status } = useSendTransactionFromFn(
-    threshold.staking.increaseAuthorization
+    threshold.staking!.increaseAuthorization
   )
 
   const authorizeMultipleApps = useCallback(
diff --git a/src/hooks/staking-applications/useBondOperatorTransaction.ts b/src/hooks/staking-applications/useBondOperatorTransaction.ts
index 7ee43a7d5..f2a4eb177 100644
--- a/src/hooks/staking-applications/useBondOperatorTransaction.ts
+++ b/src/hooks/staking-applications/useBondOperatorTransaction.ts
@@ -15,7 +15,7 @@ export const useBondOperatorTransaction = (
   const threshold = useThreshold()
 
   return useSendTransactionFromFn(
-    threshold.multiAppStaking[stakingAppNameToThresholdAppService[appName]]
+    threshold.multiAppStaking![stakingAppNameToThresholdAppService[appName]]
       .bondOperator,
     onSuccess,
     onError
diff --git a/src/hooks/staking-applications/useConfirmDeatuhorizationTransaction.ts b/src/hooks/staking-applications/useConfirmDeatuhorizationTransaction.ts
index 9dd274dfd..1fec0902d 100644
--- a/src/hooks/staking-applications/useConfirmDeatuhorizationTransaction.ts
+++ b/src/hooks/staking-applications/useConfirmDeatuhorizationTransaction.ts
@@ -15,7 +15,7 @@ export const useConfirmDeatuhorizationTransaction = (
   const threshold = useThreshold()
 
   return useSendTransactionFromFn(
-    threshold.multiAppStaking[stakingAppNameToThresholdAppService[appName]]
+    threshold.multiAppStaking![stakingAppNameToThresholdAppService[appName]]
       .approveAuthorizationDecrease,
     onSuccess,
     onError
diff --git a/src/hooks/staking-applications/useIncreaseAuthorizationTransaction.ts b/src/hooks/staking-applications/useIncreaseAuthorizationTransaction.ts
index 384d8b8e5..74a56af5e 100644
--- a/src/hooks/staking-applications/useIncreaseAuthorizationTransaction.ts
+++ b/src/hooks/staking-applications/useIncreaseAuthorizationTransaction.ts
@@ -15,7 +15,7 @@ export const useIncreaseAuthorizationTransaction = (
   const threshold = useThreshold()
 
   return useSendTransactionFromFn(
-    threshold.multiAppStaking[stakingAppNameToThresholdAppService[appName]]
+    threshold.multiAppStaking![stakingAppNameToThresholdAppService[appName]]
       .increaseAuthorization,
     onSuccess,
     onError
diff --git a/src/hooks/staking-applications/useInitiateDeauthorization.ts b/src/hooks/staking-applications/useInitiateDeauthorization.ts
index 7797eab4e..42e80a686 100644
--- a/src/hooks/staking-applications/useInitiateDeauthorization.ts
+++ b/src/hooks/staking-applications/useInitiateDeauthorization.ts
@@ -42,7 +42,7 @@ export const useInitiateDeauthorization = (
     sendTransaction: requestAuthorizationDecrease,
     status: deauthorizationTxStatus,
   } = useSendTransactionFromFn(
-    threshold.multiAppStaking[stakingAppNameToThresholdAppService[appName]]
+    threshold.multiAppStaking![stakingAppNameToThresholdAppService[appName]]
       .requestAuthorizationDecrease,
     onSuccess,
     onErrorRequestAuthorizationDecrease
diff --git a/src/hooks/staking-applications/useRegisterOperatorTransaction.ts b/src/hooks/staking-applications/useRegisterOperatorTransaction.ts
index cdf7b5cc5..7f5bea0a4 100644
--- a/src/hooks/staking-applications/useRegisterOperatorTransaction.ts
+++ b/src/hooks/staking-applications/useRegisterOperatorTransaction.ts
@@ -15,7 +15,7 @@ export const useRegisterOperatorTransaction = (
   const threshold = useThreshold()
 
   return useSendTransactionFromFn(
-    threshold.multiAppStaking[stakingAppNameToThresholdAppService[appName]]
+    threshold.multiAppStaking![stakingAppNameToThresholdAppService[appName]]
       .registerOperator,
     onSuccess,
     onError
diff --git a/src/hooks/staking-applications/useStakingAppContract.ts b/src/hooks/staking-applications/useStakingAppContract.ts
index f80845305..58636ee9b 100644
--- a/src/hooks/staking-applications/useStakingAppContract.ts
+++ b/src/hooks/staking-applications/useStakingAppContract.ts
@@ -1,5 +1,6 @@
 import { StakingAppName } from "../../store/staking-applications"
 import { useThreshold } from "../../contexts/ThresholdContext"
+import { Contract } from "ethers"
 
 export const stakingAppNameToThresholdAppService: Record<
   StakingAppName,
@@ -10,8 +11,13 @@ export const stakingAppNameToThresholdAppService: Record<
   taco: "taco",
 }
 
-export const useStakingAppContract = (appName: StakingAppName) => {
-  return useThreshold().multiAppStaking[
-    stakingAppNameToThresholdAppService[appName]
-  ].contract
+export const useStakingAppContract = (
+  appName: StakingAppName
+): Contract | null => {
+  const threshold = useThreshold()
+
+  if (!threshold.multiAppStaking) return null
+
+  return threshold.multiAppStaking[stakingAppNameToThresholdAppService[appName]]
+    .contract
 }
diff --git a/src/hooks/staking-applications/useStakingApplicationAddress.ts b/src/hooks/staking-applications/useStakingApplicationAddress.ts
index e08df8aa3..20721999f 100644
--- a/src/hooks/staking-applications/useStakingApplicationAddress.ts
+++ b/src/hooks/staking-applications/useStakingApplicationAddress.ts
@@ -5,7 +5,8 @@ import { stakingAppNameToThresholdAppService } from "./useStakingAppContract"
 
 export const useStakingApplicationAddress = (appName: StakingAppName) => {
   return (
-    useThreshold().multiAppStaking[stakingAppNameToThresholdAppService[appName]]
-      ?.address ?? AddressZero
+    useThreshold().multiAppStaking![
+      stakingAppNameToThresholdAppService[appName]
+    ]?.address ?? AddressZero
   )
 }
diff --git a/src/hooks/staking-applications/useSubscribeToAuthorizationIncreasedEvent.ts b/src/hooks/staking-applications/useSubscribeToAuthorizationIncreasedEvent.ts
index b0b5c415c..1b76264ed 100644
--- a/src/hooks/staking-applications/useSubscribeToAuthorizationIncreasedEvent.ts
+++ b/src/hooks/staking-applications/useSubscribeToAuthorizationIncreasedEvent.ts
@@ -17,6 +17,13 @@ export const useSubscribeToAuthorizationIncreasedEvent = () => {
     async (stakingProvider, application, fromAmount, toAmount) => {
       const appName = getStakingAppNameFromAppAddress(application)
 
+      if (!appName) {
+        console.warn(
+          `Could not determine staking app name for address: ${application}`
+        )
+        return
+      }
+
       dispatch(
         stakingApplicationsSlice.actions.authorizationIncreased({
           stakingProvider,
diff --git a/src/hooks/staking-applications/useUpdateOperatorStatus.tsx b/src/hooks/staking-applications/useUpdateOperatorStatus.tsx
index bb20862dc..1f8739d4a 100644
--- a/src/hooks/staking-applications/useUpdateOperatorStatus.tsx
+++ b/src/hooks/staking-applications/useUpdateOperatorStatus.tsx
@@ -7,7 +7,7 @@ export const useUpdateOperatorStatus = (appName: StakingAppName) => {
   const threshold = useThreshold()
 
   return useSendTransactionFromFn(
-    threshold.multiAppStaking[stakingAppNameToThresholdAppService[appName]]
+    threshold.multiAppStaking![stakingAppNameToThresholdAppService[appName]]
       .updateOperatorStatus
   )
 }
diff --git a/src/hooks/tbtc/useFetchDepositDetails.ts b/src/hooks/tbtc/useFetchDepositDetails.ts
index b476d031b..7668f04e8 100644
--- a/src/hooks/tbtc/useFetchDepositDetails.ts
+++ b/src/hooks/tbtc/useFetchDepositDetails.ts
@@ -25,7 +25,7 @@ export const useFetchDepositDetails = (depositKey: string | undefined) => {
     const fetch = async () => {
       setIsFetching(true)
       try {
-        const { depositor } = (await threshold.tbtc.bridgeContract.deposits(
+        const { depositor } = (await threshold.tbtc.bridgeContract!.deposits(
           depositKey
         )) as {
           depositor: string
@@ -49,7 +49,7 @@ export const useFetchDepositDetails = (depositKey: string | undefined) => {
         }
 
         const optimisticMintingRequestedEvents = await getContractPastEvents(
-          threshold.tbtc.vaultContract,
+          threshold.tbtc.vaultContract!,
           {
             eventName: "OptimisticMintingRequested",
             fromBlock: deposit.blockNumber,
@@ -58,7 +58,7 @@ export const useFetchDepositDetails = (depositKey: string | undefined) => {
         )
 
         const optimisticMintingFinalizedEvents = await getContractPastEvents(
-          threshold.tbtc.vaultContract,
+          threshold.tbtc.vaultContract!,
           {
             eventName: "OptimisticMintingFinalized",
             fromBlock: deposit.blockNumber,
@@ -95,7 +95,7 @@ export const useFetchDepositDetails = (depositKey: string | undefined) => {
       setIsFetching(false)
     }
 
-    if (depositKey) {
+    if (depositKey && !threshold.tbtc.isCrossChain) {
       fetch()
     }
   }, [depositKey, threshold, reverseTxHash])
diff --git a/src/hooks/useCheckBonusEligibility.ts b/src/hooks/useCheckBonusEligibility.ts
index e1d982b6a..fe3d00148 100644
--- a/src/hooks/useCheckBonusEligibility.ts
+++ b/src/hooks/useCheckBonusEligibility.ts
@@ -1,21 +1,19 @@
 import { useEffect } from "react"
 import { BigNumber, BigNumberish, Event, constants } from "ethers"
-import {
-  T_STAKING_CONTRACT_DEPLOYMENT_BLOCK,
-  useTStakingContract,
-} from "../web3/hooks"
+import { getTStakingDeploymentBlock, useTStakingContract } from "../web3/hooks"
 import { getAddress, getContractPastEvents } from "../web3/utils"
 import { BonusEligibility } from "../types"
 import { calculateStakingBonusReward } from "../utils/stakingBonus"
 import { stakingBonus } from "../constants"
 import {
   useMerkleDropContract,
-  DEPLOYMENT_BLOCK,
+  getMerkleDropDeploymentBlock,
 } from "../web3/hooks/useMerkleDropContract"
 import { selectStakingProviders } from "../store/staking"
 import { useDispatch, useSelector } from "react-redux"
 import { RootState } from "../store"
 import { setStakingBonus } from "../store/rewards"
+import { useIsActive } from "./useIsActive"
 
 interface BonusEligibilityResult {
   [address: string]: BonusEligibility
@@ -26,6 +24,7 @@ export const useCheckBonusEligibility = () => {
   const { hasFetched, isFetching } = useSelector(
     (state: RootState) => state.rewards.stakingBonus
   )
+  const { chainId } = useIsActive()
   const dispatch = useDispatch()
   const merkleDropContract = useMerkleDropContract()
   const tStakingContract = useTStakingContract()
@@ -46,7 +45,7 @@ export const useCheckBonusEligibility = () => {
         (
           await getContractPastEvents(merkleDropContract, {
             eventName: "Claimed",
-            fromBlock: DEPLOYMENT_BLOCK,
+            fromBlock: getMerkleDropDeploymentBlock(),
             filterParams: [stakingProviders],
           })
         ).map((_) => getAddress(_.args?.stakingProvider as string))
@@ -54,19 +53,19 @@ export const useCheckBonusEligibility = () => {
 
       const stakedEvents = await getContractPastEvents(tStakingContract, {
         eventName: "Staked",
-        fromBlock: T_STAKING_CONTRACT_DEPLOYMENT_BLOCK,
+        fromBlock: getTStakingDeploymentBlock(),
         filterParams: [null, null, stakingProviders],
       })
 
       const toppedUpEvents = await getContractPastEvents(tStakingContract, {
         eventName: "ToppedUp",
-        fromBlock: T_STAKING_CONTRACT_DEPLOYMENT_BLOCK,
+        fromBlock: getTStakingDeploymentBlock(),
         filterParams: [stakingProviders],
       })
 
       const unstakedEvents = await getContractPastEvents(tStakingContract, {
         eventName: "Unstaked",
-        fromBlock: T_STAKING_CONTRACT_DEPLOYMENT_BLOCK,
+        fromBlock: getTStakingDeploymentBlock(),
         filterParams: [stakingProviders],
       })
 
diff --git a/src/hooks/useFetchOwnerStakes.ts b/src/hooks/useFetchOwnerStakes.ts
index defba8cf0..f4cfd1349 100644
--- a/src/hooks/useFetchOwnerStakes.ts
+++ b/src/hooks/useFetchOwnerStakes.ts
@@ -10,7 +10,7 @@ export const useFetchOwnerStakes = () => {
 
   return useCallback(
     async (address?: string): Promise<StakeData[]> => {
-      if (!address) {
+      if (!address || !threshold.staking) {
         return []
       }
 
diff --git a/src/hooks/useFetchStakingRewards.ts b/src/hooks/useFetchStakingRewards.ts
index a54259031..da89f919f 100644
--- a/src/hooks/useFetchStakingRewards.ts
+++ b/src/hooks/useFetchStakingRewards.ts
@@ -2,7 +2,7 @@ import { useEffect } from "react"
 import { useSelector, useDispatch } from "react-redux"
 import {
   useMerkleDropContract,
-  DEPLOYMENT_BLOCK,
+  getMerkleDropDeploymentBlock,
 } from "../web3/hooks/useMerkleDropContract"
 import rewardsData from "../merkle-drop/rewards.json"
 import { getContractPastEvents, getAddress } from "../web3/utils"
@@ -12,12 +12,14 @@ import { setInterimRewards } from "../store/rewards"
 import { selectStakingProviders } from "../store/staking"
 import { BigNumber } from "ethers"
 import { Zero } from "@ethersproject/constants"
+import { useIsActive } from "./useIsActive"
 
 interface StakingRewards {
   [stakingProvider: string]: string
 }
 
 export const useFetchStakingRewards = () => {
+  const { chainId } = useIsActive()
   const merkleDropContract = useMerkleDropContract()
   const stakingProviders = useSelector(selectStakingProviders)
   const { hasFetched, isFetching } = useSelector(
@@ -37,7 +39,7 @@ export const useFetchStakingRewards = () => {
 
       const claimedEvents = await getContractPastEvents(merkleDropContract, {
         eventName: "Claimed",
-        fromBlock: DEPLOYMENT_BLOCK,
+        fromBlock: getMerkleDropDeploymentBlock(),
         filterParams: [stakingProviders],
       })
 
diff --git a/src/hooks/useFetchTvl.ts b/src/hooks/useFetchTvl.ts
index 6ed84f776..860dcaac0 100644
--- a/src/hooks/useFetchTvl.ts
+++ b/src/hooks/useFetchTvl.ts
@@ -12,6 +12,9 @@ import { useETHData } from "./useETHData"
 import { useToken } from "./useToken"
 import { Token } from "../enums"
 import { toUsdBalance } from "../utils/getUsdBalance"
+import { useIsActive } from "./useIsActive"
+import { isL1Network } from "../networks/utils"
+import { ContractCall } from "../threshold-ts/multicall"
 
 interface TvlRawData {
   ecdsaTvl: string
@@ -30,7 +33,7 @@ interface TvlData {
   total: string
 }
 
-const initialState = {
+const initialState: TvlRawData = {
   ecdsaTvl: "0",
   tbtcv1Tvl: "0",
   keepStakingTvl: "0",
@@ -43,6 +46,7 @@ export const useFetchTvl = (): [
   () => Promise<TvlRawData>,
   TvlRawData
 ] => {
+  const { chainId } = useIsActive()
   const [rawData, setRawData] = useState<TvlRawData>(initialState)
   const {
     ecdsaTvl,
@@ -51,7 +55,6 @@ export const useFetchTvl = (): [
     tStakingTvl,
     tBTC: tBTCTvl,
   } = rawData
-
   const eth = useETHData()
   const keep = useToken(Token.Keep)
   const tbtcv1 = useToken(Token.TBTC)
@@ -62,60 +65,75 @@ export const useFetchTvl = (): [
   const keepTokenStaking = useKeepTokenStakingContract()
   const tBTCToken = useToken(Token.TBTCV2)
 
-  const fetchOnChainData = useMulticall([
-    {
-      address: multicall?.address!,
-      interface: multicall?.interface!,
+  const calls: Array<ContractCall & { key: string }> = []
+
+  if (keepBonding && multicall) {
+    calls.push({
+      address: multicall.address,
+      interface: multicall.interface,
       method: "getEthBalance",
-      args: [keepBonding?.address],
-    },
-    {
-      address: tbtcv1.contract?.address!,
-      interface: tbtcv1.contract?.interface!,
+      args: [keepBonding.address],
+      key: "ecdsaTvl",
+    })
+  }
+
+  if (tbtcv1.contract) {
+    calls.push({
+      address: tbtcv1.contract.address,
+      interface: tbtcv1.contract.interface,
       method: "totalSupply",
-    },
-    {
-      address: keep.contract?.address!,
-      interface: keep.contract?.interface!,
+      args: [],
+      key: "tbtcv1Tvl",
+    })
+  }
+
+  if (keep.contract && keepTokenStaking) {
+    calls.push({
+      address: keep.contract.address,
+      interface: keep.contract.interface,
       method: "balanceOf",
-      args: [keepTokenStaking?.address],
-    },
-    {
-      address: t.contract?.address!,
-      interface: t.contract?.interface!,
+      args: [keepTokenStaking.address],
+      key: "keepStakingTvl",
+    })
+  }
+
+  if (t.contract && tTokenStaking) {
+    calls.push({
+      address: t.contract.address,
+      interface: t.contract.interface,
       method: "balanceOf",
-      args: [tTokenStaking?.address],
-    },
-    {
-      address: tBTCToken.contract?.address!,
-      interface: tBTCToken.contract?.interface!,
+      args: [tTokenStaking.address],
+      key: "tStakingTvl",
+    })
+  }
+
+  if (tBTCToken.contract) {
+    calls.push({
+      address: tBTCToken.contract.address,
+      interface: tBTCToken.contract.interface,
       method: "totalSupply",
-    },
-  ])
+      args: [],
+      key: "tBTC",
+    })
+  }
+
+  const fetchOnChainData = useMulticall(calls)
 
   const fetchTvlData = useCallback(async () => {
+    if (chainId && !isL1Network(chainId)) return initialState
     const chainData = await fetchOnChainData()
     if (chainData.length === 0) return initialState
 
-    const [
-      ethInKeepBonding,
-      tbtcv1TokenTotalSupply,
-      keepStaking,
-      tStaking,
-      tBTCTokenTotalSupply,
-    ] = chainData.map((amount: BigNumberish) => amount.toString())
-
-    const data: TvlRawData = {
-      ecdsaTvl: ethInKeepBonding,
-      tbtcv1Tvl: tbtcv1TokenTotalSupply,
-      keepStakingTvl: keepStaking,
-      tStakingTvl: tStaking,
-      tBTC: tBTCTokenTotalSupply,
-    }
-    setRawData(data)
+    const data: TvlRawData = { ...initialState }
+
+    chainData.forEach((result: BigNumberish, index: number) => {
+      const key = calls[index].key as keyof TvlRawData
+      data[key] = result ? result.toString() : "0"
+    })
 
+    setRawData(data)
     return data
-  }, [fetchOnChainData])
+  }, [fetchOnChainData, chainId])
 
   const data = useMemo(() => {
     const ecdsa = toUsdBalance(formatUnits(ecdsaTvl), eth.usdPrice)
@@ -123,25 +141,27 @@ export const useFetchTvl = (): [
     const tbtcv1USD = toUsdBalance(formatUnits(tbtcTvl), tbtcv1.usdConversion)
     const tBTCUSD = toUsdBalance(formatUnits(tBTCTvl), tBTCToken.usdConversion)
 
-    const keepStaking = toUsdBalance(
+    const keepStakingUSD = toUsdBalance(
       formatUnits(keepStakingTvl),
       keep.usdConversion
     )
 
-    const tStaking = toUsdBalance(formatUnits(tStakingTvl), t.usdConversion)
+    const tStakingUSD = toUsdBalance(formatUnits(tStakingTvl), t.usdConversion)
+
+    const total = ecdsa
+      .addUnsafe(tbtcv1USD)
+      .addUnsafe(keepStakingUSD)
+      .addUnsafe(tStakingUSD)
+      .addUnsafe(tBTCUSD)
+      .toString()
 
     return {
       ecdsa: ecdsa.toString(),
       tbtcv1: tbtcv1USD.toString(),
-      keepStaking: keepStaking.toString(),
-      tStaking: tStaking.toString(),
+      keepStaking: keepStakingUSD.toString(),
+      tStaking: tStakingUSD.toString(),
       tBTC: tBTCUSD.toString(),
-      total: ecdsa
-        .addUnsafe(tbtcv1USD)
-        .addUnsafe(keepStaking)
-        .addUnsafe(tStaking)
-        .addUnsafe(tBTCUSD)
-        .toString(),
+      total,
     } as TvlData
   }, [
     ecdsaTvl,
diff --git a/src/hooks/useTBTCBridgeContractAddress.ts b/src/hooks/useTBTCBridgeContractAddress.ts
index 3396e19d8..50a460bc6 100644
--- a/src/hooks/useTBTCBridgeContractAddress.ts
+++ b/src/hooks/useTBTCBridgeContractAddress.ts
@@ -3,5 +3,5 @@ import { useBridgeContract } from "./tbtc/useBridgeContract"
 export const useTBTCBridgeContractAddress = () => {
   const bridgeContract = useBridgeContract()
 
-  return bridgeContract.address
+  return bridgeContract?.address
 }
diff --git a/src/hooks/useTBTCTokenAddress.ts b/src/hooks/useTBTCTokenAddress.ts
index 0a166864d..21600e7ec 100644
--- a/src/hooks/useTBTCTokenAddress.ts
+++ b/src/hooks/useTBTCTokenAddress.ts
@@ -3,5 +3,5 @@ import { useTBTCv2TokenContract } from "../web3/hooks/useTBTCv2TokenContract"
 export const useTBTCTokenAddress = () => {
   const tbtcContract = useTBTCv2TokenContract()
 
-  return tbtcContract.address
+  return tbtcContract?.contract?.address
 }
diff --git a/src/hooks/useTokensBalanceCall.ts b/src/hooks/useTokensBalanceCall.ts
index 70a2be644..43fcf5c65 100644
--- a/src/hooks/useTokensBalanceCall.ts
+++ b/src/hooks/useTokensBalanceCall.ts
@@ -4,8 +4,8 @@ import { useMulticall } from "../web3/hooks/useMulticall"
 export const useTokensBalanceCall = (tokens: Contract[], address: string) => {
   return useMulticall(
     tokens.map((tokenContract) => ({
-      address: tokenContract.address,
-      interface: tokenContract.interface,
+      address: tokenContract?.address,
+      interface: tokenContract?.interface,
       method: "balanceOf",
       args: [address],
     }))
diff --git a/src/pages/Staking/HowItWorks/StakingOverview/LegacyStakesCard.tsx b/src/pages/Staking/HowItWorks/StakingOverview/LegacyStakesCard.tsx
index 8e64b13ab..7b91d5e5b 100644
--- a/src/pages/Staking/HowItWorks/StakingOverview/LegacyStakesCard.tsx
+++ b/src/pages/Staking/HowItWorks/StakingOverview/LegacyStakesCard.tsx
@@ -1,7 +1,7 @@
 import { ComponentProps, FC } from "react"
 import { BodyMd, BoxLabel, Card, LabelSm } from "@threshold-network/components"
 import ViewInBlockExplorer from "../../../../components/ViewInBlockExplorer"
-import { ExplorerDataType } from "../../../../utils/createEtherscanLink"
+import { ExplorerDataType } from "../../../../networks/enums/networks"
 import { LegacyStakesDepositSteps } from "../../../../components/StakingTimeline"
 
 export const LegacyStakesCard: FC<
diff --git a/src/pages/Staking/HowItWorks/StakingOverview/ThresholdStakesCard.tsx b/src/pages/Staking/HowItWorks/StakingOverview/ThresholdStakesCard.tsx
index 336b591b2..ff3322c7f 100644
--- a/src/pages/Staking/HowItWorks/StakingOverview/ThresholdStakesCard.tsx
+++ b/src/pages/Staking/HowItWorks/StakingOverview/ThresholdStakesCard.tsx
@@ -2,7 +2,7 @@ import { FC, ComponentProps } from "react"
 import { UnorderedList, ListItem, useColorModeValue } from "@chakra-ui/react"
 import { BodyMd, LabelSm, Card } from "@threshold-network/components"
 import ViewInBlockExplorer from "../../../../components/ViewInBlockExplorer"
-import { ExplorerDataType } from "../../../../utils/createEtherscanLink"
+import { ExplorerDataType } from "../../../../networks/enums/networks"
 
 export const ThresholdStakesCard: FC<
   ComponentProps<typeof Card> & { tStakingContractAddress: string }
diff --git a/src/store/account/effects.ts b/src/store/account/effects.ts
index 7aba3f6ba..83d730e12 100644
--- a/src/store/account/effects.ts
+++ b/src/store/account/effects.ts
@@ -26,6 +26,9 @@ export const getStakingProviderOperatorInfo = async (
     const { account } = listenerApi.getState()
     const { address } = account
     const stakes = action.payload
+    const threshold = listenerApi.extra.threshold
+
+    if (!account || !threshold.staking || !threshold.multiAppStaking) return
 
     const stake = stakes.find((_: StakeData) =>
       isSameETHAddress(_.stakingProvider, address)
@@ -37,7 +40,7 @@ export const getStakingProviderOperatorInfo = async (
       isStakingProvider = true
     } else {
       const { owner, authorizer, beneficiary } =
-        await listenerApi.extra.threshold.staking.rolesOf(address)
+        await threshold.staking.rolesOf(address)
 
       isStakingProvider =
         !isAddressZero(owner) &&
@@ -52,7 +55,7 @@ export const getStakingProviderOperatorInfo = async (
     listenerApi.dispatch(accountUsedAsStakingProvider())
 
     const mappedOperators =
-      await listenerApi.extra.threshold.multiAppStaking.getMappedOperatorsForStakingProvider(
+      await threshold.multiAppStaking.getMappedOperatorsForStakingProvider(
         address
       )
 
diff --git a/src/store/staking-applications/effects.ts b/src/store/staking-applications/effects.ts
index dcaf10726..086030e45 100644
--- a/src/store/staking-applications/effects.ts
+++ b/src/store/staking-applications/effects.ts
@@ -47,7 +47,7 @@ export const getSupportedAppsEffect = async (
       })
     )
     const data =
-      await listenerApi.extra.threshold.multiAppStaking.getSupportedAppsAuthParameters()
+      await listenerApi.extra.threshold.multiAppStaking!.getSupportedAppsAuthParameters()
     const payload = {
       tbtc: {
         minimumAuthorization: data.tbtc.minimumAuthorization.toString(),
@@ -126,7 +126,11 @@ export const getSupportedAppsStakingProvidersData = async (
 ) => {
   try {
     const stakingProviders = selectStakingProviders(listenerApi.getState())
-    if (stakingProviders.length === 0) return
+    if (
+      stakingProviders.length === 0 ||
+      !listenerApi.extra.threshold.multiAppStaking
+    )
+      return
     // one-off listener
     listenerApi.unsubscribe()
 
@@ -392,6 +396,7 @@ export const displayDeauthrizationInitiatedModalEffect = (
         stakingProvider,
         txHash,
         decreaseAmount,
+        stakingAppName: appName,
       },
     })
   )
diff --git a/src/store/staking/effects.ts b/src/store/staking/effects.ts
index 51368ea0f..732ca7664 100644
--- a/src/store/staking/effects.ts
+++ b/src/store/staking/effects.ts
@@ -11,6 +11,7 @@ export const fetchStakeByStakingProviderEffect = async (
   const { stakingProvider } = actionCreator.payload
 
   if (
+    !listenerApi.extra.threshold.staking ||
     !stakingProvider ||
     !isAddress(stakingProvider) ||
     isAddressZero(stakingProvider)
@@ -51,7 +52,7 @@ const fetchStake = async (
   listenerApi: AppListenerEffectAPI
 ) => {
   const stake =
-    await listenerApi.extra.threshold.staking.getStakeByStakingProvider(
+    await listenerApi.extra.threshold.staking!.getStakeByStakingProvider(
       stakingProvider
     )
 
diff --git a/src/threshold-ts/mas/dapp-development-sepolia-artifacts/TacoRegistry.json b/src/threshold-ts/mas/dapp-development-sepolia-artifacts/TacoRegistry.json
new file mode 100644
index 000000000..1e5bcbf03
--- /dev/null
+++ b/src/threshold-ts/mas/dapp-development-sepolia-artifacts/TacoRegistry.json
@@ -0,0 +1,1352 @@
+{
+  "address": "0xE9Eb81F72cDBE9fE82f61EA527e8a3A39f5B023a",
+  "abi": [
+    {
+      "type": "constructor",
+      "stateMutability": "nonpayable",
+      "inputs": [
+        {
+          "name": "_token",
+          "type": "address",
+          "internalType": "contract IERC20"
+        },
+        {
+          "name": "_tStaking",
+          "type": "address",
+          "internalType": "contract IStaking"
+        },
+        {
+          "name": "_minimumAuthorization",
+          "type": "uint96",
+          "internalType": "uint96"
+        },
+        {
+          "name": "_minOperatorSeconds",
+          "type": "uint256",
+          "internalType": "uint256"
+        },
+        {
+          "name": "_rewardDuration",
+          "type": "uint256",
+          "internalType": "uint256"
+        },
+        {
+          "name": "_deauthorizationDuration",
+          "type": "uint256",
+          "internalType": "uint256"
+        },
+        {
+          "name": "_commitmentDurationOptions",
+          "type": "uint64[]",
+          "internalType": "uint64[]"
+        },
+        {
+          "name": "_commitmentDeadline",
+          "type": "uint64",
+          "internalType": "uint64"
+        }
+      ]
+    },
+    {
+      "type": "error",
+      "name": "AddressEmptyCode",
+      "inputs": [
+        {
+          "name": "target",
+          "type": "address",
+          "internalType": "address"
+        }
+      ]
+    },
+    {
+      "type": "error",
+      "name": "AddressInsufficientBalance",
+      "inputs": [
+        {
+          "name": "account",
+          "type": "address",
+          "internalType": "address"
+        }
+      ]
+    },
+    {
+      "type": "error",
+      "name": "FailedInnerCall",
+      "inputs": []
+    },
+    {
+      "type": "error",
+      "name": "InvalidInitialization",
+      "inputs": []
+    },
+    {
+      "type": "error",
+      "name": "NotInitializing",
+      "inputs": []
+    },
+    {
+      "type": "error",
+      "name": "OwnableInvalidOwner",
+      "inputs": [
+        {
+          "name": "owner",
+          "type": "address",
+          "internalType": "address"
+        }
+      ]
+    },
+    {
+      "type": "error",
+      "name": "OwnableUnauthorizedAccount",
+      "inputs": [
+        {
+          "name": "account",
+          "type": "address",
+          "internalType": "address"
+        }
+      ]
+    },
+    {
+      "type": "error",
+      "name": "SafeCastOverflowedUintDowncast",
+      "inputs": [
+        {
+          "name": "bits",
+          "type": "uint8",
+          "internalType": "uint8"
+        },
+        {
+          "name": "value",
+          "type": "uint256",
+          "internalType": "uint256"
+        }
+      ]
+    },
+    {
+      "type": "error",
+      "name": "SafeERC20FailedOperation",
+      "inputs": [
+        {
+          "name": "token",
+          "type": "address",
+          "internalType": "address"
+        }
+      ]
+    },
+    {
+      "type": "event",
+      "name": "AuthorizationDecreaseApproved",
+      "inputs": [
+        {
+          "name": "stakingProvider",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        },
+        {
+          "name": "fromAmount",
+          "type": "uint96",
+          "internalType": "uint96",
+          "indexed": false
+        },
+        {
+          "name": "toAmount",
+          "type": "uint96",
+          "internalType": "uint96",
+          "indexed": false
+        }
+      ],
+      "anonymous": false
+    },
+    {
+      "type": "event",
+      "name": "AuthorizationDecreaseRequested",
+      "inputs": [
+        {
+          "name": "stakingProvider",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        },
+        {
+          "name": "fromAmount",
+          "type": "uint96",
+          "internalType": "uint96",
+          "indexed": false
+        },
+        {
+          "name": "toAmount",
+          "type": "uint96",
+          "internalType": "uint96",
+          "indexed": false
+        }
+      ],
+      "anonymous": false
+    },
+    {
+      "type": "event",
+      "name": "AuthorizationIncreased",
+      "inputs": [
+        {
+          "name": "stakingProvider",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        },
+        {
+          "name": "fromAmount",
+          "type": "uint96",
+          "internalType": "uint96",
+          "indexed": false
+        },
+        {
+          "name": "toAmount",
+          "type": "uint96",
+          "internalType": "uint96",
+          "indexed": false
+        }
+      ],
+      "anonymous": false
+    },
+    {
+      "type": "event",
+      "name": "AuthorizationInvoluntaryDecreased",
+      "inputs": [
+        {
+          "name": "stakingProvider",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        },
+        {
+          "name": "fromAmount",
+          "type": "uint96",
+          "internalType": "uint96",
+          "indexed": false
+        },
+        {
+          "name": "toAmount",
+          "type": "uint96",
+          "internalType": "uint96",
+          "indexed": false
+        }
+      ],
+      "anonymous": false
+    },
+    {
+      "type": "event",
+      "name": "AuthorizationReSynchronized",
+      "inputs": [
+        {
+          "name": "stakingProvider",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        },
+        {
+          "name": "fromAmount",
+          "type": "uint96",
+          "internalType": "uint96",
+          "indexed": false
+        },
+        {
+          "name": "toAmount",
+          "type": "uint96",
+          "internalType": "uint96",
+          "indexed": false
+        }
+      ],
+      "anonymous": false
+    },
+    {
+      "type": "event",
+      "name": "CommitmentMade",
+      "inputs": [
+        {
+          "name": "stakingProvider",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        },
+        {
+          "name": "endCommitment",
+          "type": "uint256",
+          "internalType": "uint256",
+          "indexed": false
+        }
+      ],
+      "anonymous": false
+    },
+    {
+      "type": "event",
+      "name": "Initialized",
+      "inputs": [
+        {
+          "name": "version",
+          "type": "uint64",
+          "internalType": "uint64",
+          "indexed": false
+        }
+      ],
+      "anonymous": false
+    },
+    {
+      "type": "event",
+      "name": "OperatorBonded",
+      "inputs": [
+        {
+          "name": "stakingProvider",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        },
+        {
+          "name": "operator",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        },
+        {
+          "name": "previousOperator",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        },
+        {
+          "name": "startTimestamp",
+          "type": "uint256",
+          "internalType": "uint256",
+          "indexed": false
+        }
+      ],
+      "anonymous": false
+    },
+    {
+      "type": "event",
+      "name": "OperatorConfirmed",
+      "inputs": [
+        {
+          "name": "stakingProvider",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        },
+        {
+          "name": "operator",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        }
+      ],
+      "anonymous": false
+    },
+    {
+      "type": "event",
+      "name": "OwnershipTransferred",
+      "inputs": [
+        {
+          "name": "previousOwner",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        },
+        {
+          "name": "newOwner",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        }
+      ],
+      "anonymous": false
+    },
+    {
+      "type": "event",
+      "name": "RewardAdded",
+      "inputs": [
+        {
+          "name": "reward",
+          "type": "uint256",
+          "internalType": "uint256",
+          "indexed": false
+        }
+      ],
+      "anonymous": false
+    },
+    {
+      "type": "event",
+      "name": "RewardDistributorSet",
+      "inputs": [
+        {
+          "name": "distributor",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        }
+      ],
+      "anonymous": false
+    },
+    {
+      "type": "event",
+      "name": "RewardPaid",
+      "inputs": [
+        {
+          "name": "stakingProvider",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        },
+        {
+          "name": "beneficiary",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        },
+        {
+          "name": "reward",
+          "type": "uint256",
+          "internalType": "uint256",
+          "indexed": false
+        }
+      ],
+      "anonymous": false
+    },
+    {
+      "type": "event",
+      "name": "RewardsWithdrawn",
+      "inputs": [
+        {
+          "name": "stakingProvider",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        },
+        {
+          "name": "amount",
+          "type": "uint96",
+          "internalType": "uint96",
+          "indexed": false
+        }
+      ],
+      "anonymous": false
+    },
+    {
+      "type": "event",
+      "name": "Slashed",
+      "inputs": [
+        {
+          "name": "stakingProvider",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        },
+        {
+          "name": "penalty",
+          "type": "uint256",
+          "internalType": "uint256",
+          "indexed": false
+        },
+        {
+          "name": "investigator",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        },
+        {
+          "name": "reward",
+          "type": "uint256",
+          "internalType": "uint256",
+          "indexed": false
+        }
+      ],
+      "anonymous": false
+    },
+    {
+      "type": "function",
+      "name": "REWARD_PER_TOKEN_MULTIPLIER",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint256",
+          "internalType": "uint256"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "adjudicator",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "address",
+          "internalType": "address"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "approveAuthorizationDecrease",
+      "stateMutability": "nonpayable",
+      "inputs": [
+        {
+          "name": "_stakingProvider",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": []
+    },
+    {
+      "type": "function",
+      "name": "authorizationDecreaseRequested",
+      "stateMutability": "nonpayable",
+      "inputs": [
+        {
+          "name": "_stakingProvider",
+          "type": "address",
+          "internalType": "address"
+        },
+        {
+          "name": "_fromAmount",
+          "type": "uint96",
+          "internalType": "uint96"
+        },
+        {
+          "name": "_toAmount",
+          "type": "uint96",
+          "internalType": "uint96"
+        }
+      ],
+      "outputs": []
+    },
+    {
+      "type": "function",
+      "name": "authorizationIncreased",
+      "stateMutability": "nonpayable",
+      "inputs": [
+        {
+          "name": "_stakingProvider",
+          "type": "address",
+          "internalType": "address"
+        },
+        {
+          "name": "_fromAmount",
+          "type": "uint96",
+          "internalType": "uint96"
+        },
+        {
+          "name": "_toAmount",
+          "type": "uint96",
+          "internalType": "uint96"
+        }
+      ],
+      "outputs": []
+    },
+    {
+      "type": "function",
+      "name": "authorizationParameters",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "_minimumAuthorization",
+          "type": "uint96",
+          "internalType": "uint96"
+        },
+        {
+          "name": "authorizationDecreaseDelay",
+          "type": "uint64",
+          "internalType": "uint64"
+        },
+        {
+          "name": "authorizationDecreaseChangePeriod",
+          "type": "uint64",
+          "internalType": "uint64"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "authorizedOverall",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint96",
+          "internalType": "uint96"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "authorizedStake",
+      "stateMutability": "view",
+      "inputs": [
+        {
+          "name": "_stakingProvider",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint96",
+          "internalType": "uint96"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "availableRewards",
+      "stateMutability": "view",
+      "inputs": [
+        {
+          "name": "_stakingProvider",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint96",
+          "internalType": "uint96"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "bondOperator",
+      "stateMutability": "nonpayable",
+      "inputs": [
+        {
+          "name": "_stakingProvider",
+          "type": "address",
+          "internalType": "address"
+        },
+        {
+          "name": "_operator",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": []
+    },
+    {
+      "type": "function",
+      "name": "childApplication",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "address",
+          "internalType": "contract ITACoRootToChild"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "commitmentDeadline",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint64",
+          "internalType": "uint64"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "commitmentDurationOption1",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint64",
+          "internalType": "uint64"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "commitmentDurationOption2",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint64",
+          "internalType": "uint64"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "commitmentDurationOption3",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint64",
+          "internalType": "uint64"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "commitmentDurationOption4",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint64",
+          "internalType": "uint64"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "confirmOperatorAddress",
+      "stateMutability": "nonpayable",
+      "inputs": [
+        {
+          "name": "_operator",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": []
+    },
+    {
+      "type": "function",
+      "name": "deauthorizationDuration",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint256",
+          "internalType": "uint256"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "getActiveStakingProviders",
+      "stateMutability": "view",
+      "inputs": [
+        {
+          "name": "_startIndex",
+          "type": "uint256",
+          "internalType": "uint256"
+        },
+        {
+          "name": "_maxStakingProviders",
+          "type": "uint256",
+          "internalType": "uint256"
+        }
+      ],
+      "outputs": [
+        {
+          "name": "allAuthorizedTokens",
+          "type": "uint256",
+          "internalType": "uint256"
+        },
+        {
+          "name": "activeStakingProviders",
+          "type": "bytes32[]",
+          "internalType": "bytes32[]"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "getBeneficiary",
+      "stateMutability": "view",
+      "inputs": [
+        {
+          "name": "_stakingProvider",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": [
+        {
+          "name": "beneficiary",
+          "type": "address",
+          "internalType": "address payable"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "getStakingProvidersLength",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint256",
+          "internalType": "uint256"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "initialize",
+      "stateMutability": "nonpayable",
+      "inputs": [],
+      "outputs": []
+    },
+    {
+      "type": "function",
+      "name": "involuntaryAuthorizationDecrease",
+      "stateMutability": "nonpayable",
+      "inputs": [
+        {
+          "name": "_stakingProvider",
+          "type": "address",
+          "internalType": "address"
+        },
+        {
+          "name": "_fromAmount",
+          "type": "uint96",
+          "internalType": "uint96"
+        },
+        {
+          "name": "_toAmount",
+          "type": "uint96",
+          "internalType": "uint96"
+        }
+      ],
+      "outputs": []
+    },
+    {
+      "type": "function",
+      "name": "isAuthorized",
+      "stateMutability": "view",
+      "inputs": [
+        {
+          "name": "_stakingProvider",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": [
+        {
+          "name": "",
+          "type": "bool",
+          "internalType": "bool"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "isOperatorConfirmed",
+      "stateMutability": "view",
+      "inputs": [
+        {
+          "name": "_operator",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": [
+        {
+          "name": "",
+          "type": "bool",
+          "internalType": "bool"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "lastTimeRewardApplicable",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint256",
+          "internalType": "uint256"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "lastUpdateTime",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint256",
+          "internalType": "uint256"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "makeCommitment",
+      "stateMutability": "nonpayable",
+      "inputs": [
+        {
+          "name": "_stakingProvider",
+          "type": "address",
+          "internalType": "address"
+        },
+        {
+          "name": "_commitmentDuration",
+          "type": "uint64",
+          "internalType": "uint64"
+        }
+      ],
+      "outputs": []
+    },
+    {
+      "type": "function",
+      "name": "minOperatorSeconds",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint256",
+          "internalType": "uint256"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "minimumAuthorization",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint96",
+          "internalType": "uint96"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "operatorToStakingProvider",
+      "stateMutability": "view",
+      "inputs": [
+        {
+          "name": "_operator",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": [
+        {
+          "name": "",
+          "type": "address",
+          "internalType": "address"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "owner",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "address",
+          "internalType": "address"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "pendingAuthorizationDecrease",
+      "stateMutability": "view",
+      "inputs": [
+        {
+          "name": "_stakingProvider",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint96",
+          "internalType": "uint96"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "periodFinish",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint256",
+          "internalType": "uint256"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "pushReward",
+      "stateMutability": "nonpayable",
+      "inputs": [
+        {
+          "name": "_reward",
+          "type": "uint96",
+          "internalType": "uint96"
+        }
+      ],
+      "outputs": []
+    },
+    {
+      "type": "function",
+      "name": "registerOperator",
+      "stateMutability": "nonpayable",
+      "inputs": [
+        {
+          "name": "_operator",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": []
+    },
+    {
+      "type": "function",
+      "name": "remainingAuthorizationDecreaseDelay",
+      "stateMutability": "view",
+      "inputs": [
+        {
+          "name": "_stakingProvider",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint64",
+          "internalType": "uint64"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "renounceOwnership",
+      "stateMutability": "nonpayable",
+      "inputs": [],
+      "outputs": []
+    },
+    {
+      "type": "function",
+      "name": "resynchronizeAuthorization",
+      "stateMutability": "nonpayable",
+      "inputs": [
+        {
+          "name": "_stakingProvider",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": []
+    },
+    {
+      "type": "function",
+      "name": "rewardDistributor",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "address",
+          "internalType": "address"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "rewardDuration",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint256",
+          "internalType": "uint256"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "rewardPerToken",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint160",
+          "internalType": "uint160"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "rewardPerTokenStored",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint160",
+          "internalType": "uint160"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "rewardRateDecimals",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint256",
+          "internalType": "uint256"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "setAdjudicator",
+      "stateMutability": "nonpayable",
+      "inputs": [
+        {
+          "name": "_adjudicator",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": []
+    },
+    {
+      "type": "function",
+      "name": "setChildApplication",
+      "stateMutability": "nonpayable",
+      "inputs": [
+        {
+          "name": "_childApplication",
+          "type": "address",
+          "internalType": "contract ITACoRootToChild"
+        }
+      ],
+      "outputs": []
+    },
+    {
+      "type": "function",
+      "name": "setRewardDistributor",
+      "stateMutability": "nonpayable",
+      "inputs": [
+        {
+          "name": "_rewardDistributor",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": []
+    },
+    {
+      "type": "function",
+      "name": "slash",
+      "stateMutability": "nonpayable",
+      "inputs": [
+        {
+          "name": "_stakingProvider",
+          "type": "address",
+          "internalType": "address"
+        },
+        {
+          "name": "_penalty",
+          "type": "uint96",
+          "internalType": "uint96"
+        },
+        {
+          "name": "_investigator",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": []
+    },
+    {
+      "type": "function",
+      "name": "stakingProviderInfo",
+      "stateMutability": "view",
+      "inputs": [
+        {
+          "name": "",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": [
+        {
+          "name": "operator",
+          "type": "address",
+          "internalType": "address"
+        },
+        {
+          "name": "operatorConfirmed",
+          "type": "bool",
+          "internalType": "bool"
+        },
+        {
+          "name": "operatorStartTimestamp",
+          "type": "uint64",
+          "internalType": "uint64"
+        },
+        {
+          "name": "authorized",
+          "type": "uint96",
+          "internalType": "uint96"
+        },
+        {
+          "name": "deauthorizing",
+          "type": "uint96",
+          "internalType": "uint96"
+        },
+        {
+          "name": "endDeauthorization",
+          "type": "uint64",
+          "internalType": "uint64"
+        },
+        {
+          "name": "tReward",
+          "type": "uint96",
+          "internalType": "uint96"
+        },
+        {
+          "name": "rewardPerTokenPaid",
+          "type": "uint160",
+          "internalType": "uint160"
+        },
+        {
+          "name": "endCommitment",
+          "type": "uint64",
+          "internalType": "uint64"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "stakingProviderToOperator",
+      "stateMutability": "view",
+      "inputs": [
+        {
+          "name": "_stakingProvider",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": [
+        {
+          "name": "",
+          "type": "address",
+          "internalType": "address"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "stakingProviders",
+      "stateMutability": "view",
+      "inputs": [
+        {
+          "name": "",
+          "type": "uint256",
+          "internalType": "uint256"
+        }
+      ],
+      "outputs": [
+        {
+          "name": "",
+          "type": "address",
+          "internalType": "address"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "tStaking",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "address",
+          "internalType": "contract IStaking"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "token",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "address",
+          "internalType": "contract IERC20"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "transferOwnership",
+      "stateMutability": "nonpayable",
+      "inputs": [
+        {
+          "name": "newOwner",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": []
+    },
+    {
+      "type": "function",
+      "name": "withdrawRewards",
+      "stateMutability": "nonpayable",
+      "inputs": [
+        {
+          "name": "_stakingProvider",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": []
+    }
+  ],
+  "tx_hash": "0xb9cd5deb857d4e74e45bcd9dd435f3fccf08cdb8c91ac0ca9da36c47210eb149",
+  "block_number": 4776043,
+  "deployer": "0x24dbb0BEE134C3773D2C1791d65d99e307Fe86CF"
+}
diff --git a/src/threshold-ts/mas/index.ts b/src/threshold-ts/mas/index.ts
index 42700c642..7dffb2ed1 100644
--- a/src/threshold-ts/mas/index.ts
+++ b/src/threshold-ts/mas/index.ts
@@ -1,9 +1,3 @@
-import RandomBeacon from "@keep-network/random-beacon/artifacts/RandomBeacon.json"
-import WalletRegistry from "@keep-network/ecdsa/artifacts/WalletRegistry.json"
-
-const chainName = process.env.REACT_APP_TACO_DOMAIN || "" // Ensure it's a string
-const TacoRegistryFile: any = require(`@nucypher/nucypher-contracts/deployment/artifacts/${chainName}.json`)
-
 import {
   Application,
   AuthorizationParameters,
@@ -14,20 +8,6 @@ import { IStaking } from "../staking"
 import { EthereumConfig } from "../types"
 import { getArtifact } from "../utils"
 
-interface TacoChains {
-  [key: string]: string
-}
-
-const tacoChains: TacoChains = {
-  lynx: "5",
-  mainnet: "1",
-  tapir: "11155111",
-  dashboard: "11155111",
-}
-
-const key = tacoChains[chainName] || ""
-const TacoRegistry = TacoRegistryFile[key]["TACoApplication"]
-
 export interface SupportedAppAuthorizationParameters {
   tbtc: AuthorizationParameters
   randomBeacon: AuthorizationParameters
@@ -54,9 +34,14 @@ export class MultiAppStaking {
   ) {
     this._staking = staking
     this._multicall = multicall
+    const randomBeaconArtifact = getArtifact(
+      "RandomBeacon",
+      config.chainId,
+      config.shouldUseTestnetDevelopmentContracts
+    )
     this.randomBeacon = new Application(this._staking, this._multicall, {
-      address: RandomBeacon.address,
-      abi: RandomBeacon.abi,
+      address: randomBeaconArtifact.address,
+      abi: randomBeaconArtifact.abi,
       ...config,
     })
     const walletRegistryArtifacts = getArtifact(
@@ -69,9 +54,14 @@ export class MultiAppStaking {
       abi: walletRegistryArtifacts.abi,
       ...config,
     })
+    const tacoRegistryArtifacts = getArtifact(
+      "TacoRegistry",
+      config.chainId,
+      config.shouldUseTestnetDevelopmentContracts
+    )
     this.taco = new Application(this._staking, this._multicall, {
-      address: TacoRegistry.address,
-      abi: TacoRegistry.abi,
+      address: tacoRegistryArtifacts.address,
+      abi: tacoRegistryArtifacts.abi,
       ...config,
     })
   }
diff --git a/src/threshold-ts/mas/mainnet-artifacts/TacoRegistry.json b/src/threshold-ts/mas/mainnet-artifacts/TacoRegistry.json
new file mode 100644
index 000000000..681f5b44a
--- /dev/null
+++ b/src/threshold-ts/mas/mainnet-artifacts/TacoRegistry.json
@@ -0,0 +1,1646 @@
+{
+  "address": "0x347CC7ede7e5517bD47D20620B2CF1b406edcF07",
+  "abi": [
+    {
+      "type": "constructor",
+      "stateMutability": "nonpayable",
+      "inputs": [
+        {
+          "name": "_token",
+          "type": "address",
+          "internalType": "contract IERC20"
+        },
+        {
+          "name": "_tStaking",
+          "type": "address",
+          "internalType": "contract IStaking"
+        },
+        {
+          "name": "_minimumAuthorization",
+          "type": "uint96",
+          "internalType": "uint96"
+        },
+        {
+          "name": "_minOperatorSeconds",
+          "type": "uint256",
+          "internalType": "uint256"
+        },
+        {
+          "name": "_rewardDuration",
+          "type": "uint256",
+          "internalType": "uint256"
+        },
+        {
+          "name": "_deauthorizationDuration",
+          "type": "uint256",
+          "internalType": "uint256"
+        },
+        {
+          "name": "_commitmentDurationOptions",
+          "type": "uint64[]",
+          "internalType": "uint64[]"
+        },
+        {
+          "name": "_commitmentDeadline",
+          "type": "uint64",
+          "internalType": "uint64"
+        },
+        {
+          "name": "_penaltyDefault",
+          "type": "uint192",
+          "internalType": "uint192"
+        },
+        {
+          "name": "_penaltyDuration",
+          "type": "uint256",
+          "internalType": "uint256"
+        },
+        {
+          "name": "_penaltyIncrement",
+          "type": "uint192",
+          "internalType": "uint192"
+        }
+      ]
+    },
+    {
+      "type": "error",
+      "name": "AddressEmptyCode",
+      "inputs": [
+        {
+          "name": "target",
+          "type": "address",
+          "internalType": "address"
+        }
+      ]
+    },
+    {
+      "type": "error",
+      "name": "AddressInsufficientBalance",
+      "inputs": [
+        {
+          "name": "account",
+          "type": "address",
+          "internalType": "address"
+        }
+      ]
+    },
+    {
+      "type": "error",
+      "name": "FailedInnerCall",
+      "inputs": []
+    },
+    {
+      "type": "error",
+      "name": "InvalidInitialization",
+      "inputs": []
+    },
+    {
+      "type": "error",
+      "name": "NotInitializing",
+      "inputs": []
+    },
+    {
+      "type": "error",
+      "name": "OwnableInvalidOwner",
+      "inputs": [
+        {
+          "name": "owner",
+          "type": "address",
+          "internalType": "address"
+        }
+      ]
+    },
+    {
+      "type": "error",
+      "name": "OwnableUnauthorizedAccount",
+      "inputs": [
+        {
+          "name": "account",
+          "type": "address",
+          "internalType": "address"
+        }
+      ]
+    },
+    {
+      "type": "error",
+      "name": "SafeCastOverflowedUintDowncast",
+      "inputs": [
+        {
+          "name": "bits",
+          "type": "uint8",
+          "internalType": "uint8"
+        },
+        {
+          "name": "value",
+          "type": "uint256",
+          "internalType": "uint256"
+        }
+      ]
+    },
+    {
+      "type": "error",
+      "name": "SafeERC20FailedOperation",
+      "inputs": [
+        {
+          "name": "token",
+          "type": "address",
+          "internalType": "address"
+        }
+      ]
+    },
+    {
+      "type": "event",
+      "name": "AuthorizationDecreaseApproved",
+      "inputs": [
+        {
+          "name": "stakingProvider",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        },
+        {
+          "name": "fromAmount",
+          "type": "uint96",
+          "internalType": "uint96",
+          "indexed": false
+        },
+        {
+          "name": "toAmount",
+          "type": "uint96",
+          "internalType": "uint96",
+          "indexed": false
+        }
+      ],
+      "anonymous": false
+    },
+    {
+      "type": "event",
+      "name": "AuthorizationDecreaseRequested",
+      "inputs": [
+        {
+          "name": "stakingProvider",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        },
+        {
+          "name": "fromAmount",
+          "type": "uint96",
+          "internalType": "uint96",
+          "indexed": false
+        },
+        {
+          "name": "toAmount",
+          "type": "uint96",
+          "internalType": "uint96",
+          "indexed": false
+        }
+      ],
+      "anonymous": false
+    },
+    {
+      "type": "event",
+      "name": "AuthorizationIncreased",
+      "inputs": [
+        {
+          "name": "stakingProvider",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        },
+        {
+          "name": "fromAmount",
+          "type": "uint96",
+          "internalType": "uint96",
+          "indexed": false
+        },
+        {
+          "name": "toAmount",
+          "type": "uint96",
+          "internalType": "uint96",
+          "indexed": false
+        }
+      ],
+      "anonymous": false
+    },
+    {
+      "type": "event",
+      "name": "AuthorizationInvoluntaryDecreased",
+      "inputs": [
+        {
+          "name": "stakingProvider",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        },
+        {
+          "name": "fromAmount",
+          "type": "uint96",
+          "internalType": "uint96",
+          "indexed": false
+        },
+        {
+          "name": "toAmount",
+          "type": "uint96",
+          "internalType": "uint96",
+          "indexed": false
+        }
+      ],
+      "anonymous": false
+    },
+    {
+      "type": "event",
+      "name": "AuthorizationReSynchronized",
+      "inputs": [
+        {
+          "name": "stakingProvider",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        },
+        {
+          "name": "fromAmount",
+          "type": "uint96",
+          "internalType": "uint96",
+          "indexed": false
+        },
+        {
+          "name": "toAmount",
+          "type": "uint96",
+          "internalType": "uint96",
+          "indexed": false
+        }
+      ],
+      "anonymous": false
+    },
+    {
+      "type": "event",
+      "name": "CommitmentMade",
+      "inputs": [
+        {
+          "name": "stakingProvider",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        },
+        {
+          "name": "endCommitment",
+          "type": "uint256",
+          "internalType": "uint256",
+          "indexed": false
+        }
+      ],
+      "anonymous": false
+    },
+    {
+      "type": "event",
+      "name": "Initialized",
+      "inputs": [
+        {
+          "name": "version",
+          "type": "uint64",
+          "internalType": "uint64",
+          "indexed": false
+        }
+      ],
+      "anonymous": false
+    },
+    {
+      "type": "event",
+      "name": "ManualChildSynchronizationSent",
+      "inputs": [
+        {
+          "name": "stakingProvider",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        },
+        {
+          "name": "authorized",
+          "type": "uint96",
+          "internalType": "uint96",
+          "indexed": false
+        },
+        {
+          "name": "deauthorizing",
+          "type": "uint96",
+          "internalType": "uint96",
+          "indexed": false
+        },
+        {
+          "name": "endDeauthorization",
+          "type": "uint64",
+          "internalType": "uint64",
+          "indexed": false
+        },
+        {
+          "name": "operator",
+          "type": "address",
+          "internalType": "address",
+          "indexed": false
+        }
+      ],
+      "anonymous": false
+    },
+    {
+      "type": "event",
+      "name": "OperatorBonded",
+      "inputs": [
+        {
+          "name": "stakingProvider",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        },
+        {
+          "name": "operator",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        },
+        {
+          "name": "previousOperator",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        },
+        {
+          "name": "startTimestamp",
+          "type": "uint256",
+          "internalType": "uint256",
+          "indexed": false
+        }
+      ],
+      "anonymous": false
+    },
+    {
+      "type": "event",
+      "name": "OperatorConfirmed",
+      "inputs": [
+        {
+          "name": "stakingProvider",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        },
+        {
+          "name": "operator",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        }
+      ],
+      "anonymous": false
+    },
+    {
+      "type": "event",
+      "name": "OwnershipTransferred",
+      "inputs": [
+        {
+          "name": "previousOwner",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        },
+        {
+          "name": "newOwner",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        }
+      ],
+      "anonymous": false
+    },
+    {
+      "type": "event",
+      "name": "Penalized",
+      "inputs": [
+        {
+          "name": "stakingProvider",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        },
+        {
+          "name": "penaltyPercent",
+          "type": "uint256",
+          "internalType": "uint256",
+          "indexed": false
+        },
+        {
+          "name": "endPenalty",
+          "type": "uint64",
+          "internalType": "uint64",
+          "indexed": false
+        }
+      ],
+      "anonymous": false
+    },
+    {
+      "type": "event",
+      "name": "RewardAdded",
+      "inputs": [
+        {
+          "name": "reward",
+          "type": "uint256",
+          "internalType": "uint256",
+          "indexed": false
+        }
+      ],
+      "anonymous": false
+    },
+    {
+      "type": "event",
+      "name": "RewardContractSet",
+      "inputs": [
+        {
+          "name": "rewardContract",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        }
+      ],
+      "anonymous": false
+    },
+    {
+      "type": "event",
+      "name": "RewardDistributorSet",
+      "inputs": [
+        {
+          "name": "distributor",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        }
+      ],
+      "anonymous": false
+    },
+    {
+      "type": "event",
+      "name": "RewardPaid",
+      "inputs": [
+        {
+          "name": "sender",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        },
+        {
+          "name": "stakingProvider",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        },
+        {
+          "name": "beneficiary",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        },
+        {
+          "name": "reward",
+          "type": "uint256",
+          "internalType": "uint256",
+          "indexed": false
+        }
+      ],
+      "anonymous": false
+    },
+    {
+      "type": "event",
+      "name": "RewardReset",
+      "inputs": [
+        {
+          "name": "stakingProvider",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        }
+      ],
+      "anonymous": false
+    },
+    {
+      "type": "event",
+      "name": "RewardsWithdrawn",
+      "inputs": [
+        {
+          "name": "stakingProvider",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        },
+        {
+          "name": "amount",
+          "type": "uint96",
+          "internalType": "uint96",
+          "indexed": false
+        }
+      ],
+      "anonymous": false
+    },
+    {
+      "type": "event",
+      "name": "Slashed",
+      "inputs": [
+        {
+          "name": "stakingProvider",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        },
+        {
+          "name": "penalty",
+          "type": "uint256",
+          "internalType": "uint256",
+          "indexed": false
+        },
+        {
+          "name": "investigator",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        },
+        {
+          "name": "reward",
+          "type": "uint256",
+          "internalType": "uint256",
+          "indexed": false
+        }
+      ],
+      "anonymous": false
+    },
+    {
+      "type": "function",
+      "name": "PENALTY_BASE",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint192",
+          "internalType": "uint192"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "REWARD_PER_TOKEN_MULTIPLIER",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint256",
+          "internalType": "uint256"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "adjudicator",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "address",
+          "internalType": "address"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "approveAuthorizationDecrease",
+      "stateMutability": "nonpayable",
+      "inputs": [
+        {
+          "name": "_stakingProvider",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": []
+    },
+    {
+      "type": "function",
+      "name": "authorizationDecreaseRequested",
+      "stateMutability": "nonpayable",
+      "inputs": [
+        {
+          "name": "_stakingProvider",
+          "type": "address",
+          "internalType": "address"
+        },
+        {
+          "name": "_fromAmount",
+          "type": "uint96",
+          "internalType": "uint96"
+        },
+        {
+          "name": "_toAmount",
+          "type": "uint96",
+          "internalType": "uint96"
+        }
+      ],
+      "outputs": []
+    },
+    {
+      "type": "function",
+      "name": "authorizationIncreased",
+      "stateMutability": "nonpayable",
+      "inputs": [
+        {
+          "name": "_stakingProvider",
+          "type": "address",
+          "internalType": "address"
+        },
+        {
+          "name": "_fromAmount",
+          "type": "uint96",
+          "internalType": "uint96"
+        },
+        {
+          "name": "_toAmount",
+          "type": "uint96",
+          "internalType": "uint96"
+        }
+      ],
+      "outputs": []
+    },
+    {
+      "type": "function",
+      "name": "authorizationParameters",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "_minimumAuthorization",
+          "type": "uint96",
+          "internalType": "uint96"
+        },
+        {
+          "name": "authorizationDecreaseDelay",
+          "type": "uint64",
+          "internalType": "uint64"
+        },
+        {
+          "name": "authorizationDecreaseChangePeriod",
+          "type": "uint64",
+          "internalType": "uint64"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "authorizedOverall",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint96",
+          "internalType": "uint96"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "authorizedStake",
+      "stateMutability": "view",
+      "inputs": [
+        {
+          "name": "_stakingProvider",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint96",
+          "internalType": "uint96"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "availableRewards",
+      "stateMutability": "view",
+      "inputs": [
+        {
+          "name": "_stakingProvider",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint96",
+          "internalType": "uint96"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "bondOperator",
+      "stateMutability": "nonpayable",
+      "inputs": [
+        {
+          "name": "_stakingProvider",
+          "type": "address",
+          "internalType": "address"
+        },
+        {
+          "name": "_operator",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": []
+    },
+    {
+      "type": "function",
+      "name": "childApplication",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "address",
+          "internalType": "contract ITACoRootToChild"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "commitmentDeadline",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint64",
+          "internalType": "uint64"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "commitmentDurationOption1",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint64",
+          "internalType": "uint64"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "commitmentDurationOption2",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint64",
+          "internalType": "uint64"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "commitmentDurationOption3",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint64",
+          "internalType": "uint64"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "commitmentDurationOption4",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint64",
+          "internalType": "uint64"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "confirmOperatorAddress",
+      "stateMutability": "nonpayable",
+      "inputs": [
+        {
+          "name": "_operator",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": []
+    },
+    {
+      "type": "function",
+      "name": "deauthorizationDuration",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint256",
+          "internalType": "uint256"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "eligibleStake",
+      "stateMutability": "view",
+      "inputs": [
+        {
+          "name": "_stakingProvider",
+          "type": "address",
+          "internalType": "address"
+        },
+        {
+          "name": "_endDate",
+          "type": "uint256",
+          "internalType": "uint256"
+        }
+      ],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint96",
+          "internalType": "uint96"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "getActiveStakingProviders",
+      "stateMutability": "view",
+      "inputs": [
+        {
+          "name": "_startIndex",
+          "type": "uint256",
+          "internalType": "uint256"
+        },
+        {
+          "name": "_maxStakingProviders",
+          "type": "uint256",
+          "internalType": "uint256"
+        },
+        {
+          "name": "_cohortDuration",
+          "type": "uint32",
+          "internalType": "uint32"
+        }
+      ],
+      "outputs": [
+        {
+          "name": "allAuthorizedTokens",
+          "type": "uint256",
+          "internalType": "uint256"
+        },
+        {
+          "name": "activeStakingProviders",
+          "type": "bytes32[]",
+          "internalType": "bytes32[]"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "getBeneficiary",
+      "stateMutability": "view",
+      "inputs": [
+        {
+          "name": "_stakingProvider",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": [
+        {
+          "name": "beneficiary",
+          "type": "address",
+          "internalType": "address payable"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "getPenalty",
+      "stateMutability": "view",
+      "inputs": [
+        {
+          "name": "_stakingProvider",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": [
+        {
+          "name": "penalty",
+          "type": "uint192",
+          "internalType": "uint192"
+        },
+        {
+          "name": "endPenalty",
+          "type": "uint64",
+          "internalType": "uint64"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "getStakingProvidersLength",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint256",
+          "internalType": "uint256"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "initialize",
+      "stateMutability": "nonpayable",
+      "inputs": [],
+      "outputs": []
+    },
+    {
+      "type": "function",
+      "name": "involuntaryAuthorizationDecrease",
+      "stateMutability": "nonpayable",
+      "inputs": [
+        {
+          "name": "_stakingProvider",
+          "type": "address",
+          "internalType": "address"
+        },
+        {
+          "name": "_fromAmount",
+          "type": "uint96",
+          "internalType": "uint96"
+        },
+        {
+          "name": "_toAmount",
+          "type": "uint96",
+          "internalType": "uint96"
+        }
+      ],
+      "outputs": []
+    },
+    {
+      "type": "function",
+      "name": "isAuthorized",
+      "stateMutability": "view",
+      "inputs": [
+        {
+          "name": "_stakingProvider",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": [
+        {
+          "name": "",
+          "type": "bool",
+          "internalType": "bool"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "isOperatorConfirmed",
+      "stateMutability": "view",
+      "inputs": [
+        {
+          "name": "_operator",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": [
+        {
+          "name": "",
+          "type": "bool",
+          "internalType": "bool"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "lastTimeRewardApplicable",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint256",
+          "internalType": "uint256"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "lastUpdateTime",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint256",
+          "internalType": "uint256"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "makeCommitment",
+      "stateMutability": "nonpayable",
+      "inputs": [
+        {
+          "name": "_stakingProvider",
+          "type": "address",
+          "internalType": "address"
+        },
+        {
+          "name": "_commitmentDuration",
+          "type": "uint64",
+          "internalType": "uint64"
+        }
+      ],
+      "outputs": []
+    },
+    {
+      "type": "function",
+      "name": "manualChildSynchronization",
+      "stateMutability": "nonpayable",
+      "inputs": [
+        {
+          "name": "_stakingProvider",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": []
+    },
+    {
+      "type": "function",
+      "name": "minOperatorSeconds",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint256",
+          "internalType": "uint256"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "minimumAuthorization",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint96",
+          "internalType": "uint96"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "operatorToStakingProvider",
+      "stateMutability": "view",
+      "inputs": [
+        {
+          "name": "_operator",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": [
+        {
+          "name": "",
+          "type": "address",
+          "internalType": "address"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "owner",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "address",
+          "internalType": "address"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "penalize",
+      "stateMutability": "nonpayable",
+      "inputs": [
+        {
+          "name": "_stakingProvider",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": []
+    },
+    {
+      "type": "function",
+      "name": "penaltyDefault",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint192",
+          "internalType": "uint192"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "penaltyDuration",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint256",
+          "internalType": "uint256"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "penaltyIncrement",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint192",
+          "internalType": "uint192"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "pendingAuthorizationDecrease",
+      "stateMutability": "view",
+      "inputs": [
+        {
+          "name": "_stakingProvider",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint96",
+          "internalType": "uint96"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "periodFinish",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint256",
+          "internalType": "uint256"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "pushReward",
+      "stateMutability": "nonpayable",
+      "inputs": [
+        {
+          "name": "_reward",
+          "type": "uint96",
+          "internalType": "uint96"
+        }
+      ],
+      "outputs": []
+    },
+    {
+      "type": "function",
+      "name": "registerOperator",
+      "stateMutability": "nonpayable",
+      "inputs": [
+        {
+          "name": "_operator",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": []
+    },
+    {
+      "type": "function",
+      "name": "remainingAuthorizationDecreaseDelay",
+      "stateMutability": "view",
+      "inputs": [
+        {
+          "name": "_stakingProvider",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint64",
+          "internalType": "uint64"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "renounceOwnership",
+      "stateMutability": "nonpayable",
+      "inputs": [],
+      "outputs": []
+    },
+    {
+      "type": "function",
+      "name": "resetReward",
+      "stateMutability": "nonpayable",
+      "inputs": [
+        {
+          "name": "_stakingProvider",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": []
+    },
+    {
+      "type": "function",
+      "name": "resynchronizeAuthorization",
+      "stateMutability": "nonpayable",
+      "inputs": [
+        {
+          "name": "_stakingProvider",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": []
+    },
+    {
+      "type": "function",
+      "name": "rewardContract",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "address",
+          "internalType": "address"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "rewardDistributor",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "address",
+          "internalType": "address"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "rewardDuration",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint256",
+          "internalType": "uint256"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "rewardPerToken",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint160",
+          "internalType": "uint160"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "rewardPerTokenStored",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint160",
+          "internalType": "uint160"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "rewardRateDecimals",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint256",
+          "internalType": "uint256"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "setAdjudicator",
+      "stateMutability": "nonpayable",
+      "inputs": [
+        {
+          "name": "_adjudicator",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": []
+    },
+    {
+      "type": "function",
+      "name": "setChildApplication",
+      "stateMutability": "nonpayable",
+      "inputs": [
+        {
+          "name": "_childApplication",
+          "type": "address",
+          "internalType": "contract ITACoRootToChild"
+        }
+      ],
+      "outputs": []
+    },
+    {
+      "type": "function",
+      "name": "setRewardContract",
+      "stateMutability": "nonpayable",
+      "inputs": [
+        {
+          "name": "_rewardContract",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": []
+    },
+    {
+      "type": "function",
+      "name": "setRewardDistributor",
+      "stateMutability": "nonpayable",
+      "inputs": [
+        {
+          "name": "_rewardDistributor",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": []
+    },
+    {
+      "type": "function",
+      "name": "slash",
+      "stateMutability": "nonpayable",
+      "inputs": [
+        {
+          "name": "_stakingProvider",
+          "type": "address",
+          "internalType": "address"
+        },
+        {
+          "name": "_penalty",
+          "type": "uint96",
+          "internalType": "uint96"
+        },
+        {
+          "name": "_investigator",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": []
+    },
+    {
+      "type": "function",
+      "name": "stakingProviderInfo",
+      "stateMutability": "view",
+      "inputs": [
+        {
+          "name": "",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": [
+        {
+          "name": "operator",
+          "type": "address",
+          "internalType": "address"
+        },
+        {
+          "name": "operatorConfirmed",
+          "type": "bool",
+          "internalType": "bool"
+        },
+        {
+          "name": "operatorStartTimestamp",
+          "type": "uint64",
+          "internalType": "uint64"
+        },
+        {
+          "name": "authorized",
+          "type": "uint96",
+          "internalType": "uint96"
+        },
+        {
+          "name": "deauthorizing",
+          "type": "uint96",
+          "internalType": "uint96"
+        },
+        {
+          "name": "endDeauthorization",
+          "type": "uint64",
+          "internalType": "uint64"
+        },
+        {
+          "name": "tReward",
+          "type": "uint96",
+          "internalType": "uint96"
+        },
+        {
+          "name": "rewardPerTokenPaid",
+          "type": "uint160",
+          "internalType": "uint160"
+        },
+        {
+          "name": "endCommitment",
+          "type": "uint64",
+          "internalType": "uint64"
+        },
+        {
+          "name": "stub",
+          "type": "uint256",
+          "internalType": "uint256"
+        },
+        {
+          "name": "penaltyPercent",
+          "type": "uint192",
+          "internalType": "uint192"
+        },
+        {
+          "name": "endPenalty",
+          "type": "uint64",
+          "internalType": "uint64"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "stakingProviderToOperator",
+      "stateMutability": "view",
+      "inputs": [
+        {
+          "name": "_stakingProvider",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": [
+        {
+          "name": "",
+          "type": "address",
+          "internalType": "address"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "stakingProviders",
+      "stateMutability": "view",
+      "inputs": [
+        {
+          "name": "",
+          "type": "uint256",
+          "internalType": "uint256"
+        }
+      ],
+      "outputs": [
+        {
+          "name": "",
+          "type": "address",
+          "internalType": "address"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "tStaking",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "address",
+          "internalType": "contract IStaking"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "token",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "address",
+          "internalType": "contract IERC20"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "transferOwnership",
+      "stateMutability": "nonpayable",
+      "inputs": [
+        {
+          "name": "newOwner",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": []
+    },
+    {
+      "type": "function",
+      "name": "withdrawRewards",
+      "stateMutability": "nonpayable",
+      "inputs": [
+        {
+          "name": "_stakingProvider",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": []
+    }
+  ],
+  "tx_hash": "0x178f50155caea7bb32dab5cd79280c66d19a52aa2d303174fa9f5d843ba2ea91",
+  "block_number": 20410589,
+  "deployer": "0xFfFd7092685bDeeBD121D1A0FEA3c349114Cce50"
+}
diff --git a/src/threshold-ts/mas/sepolia-artifacts/TacoRegistry.json b/src/threshold-ts/mas/sepolia-artifacts/TacoRegistry.json
new file mode 100644
index 000000000..968c9536e
--- /dev/null
+++ b/src/threshold-ts/mas/sepolia-artifacts/TacoRegistry.json
@@ -0,0 +1,1431 @@
+{
+  "address": "0xCcFf527698E78a536d80695D9Af4F4f3265ADA05",
+  "abi": [
+    {
+      "type": "constructor",
+      "stateMutability": "nonpayable",
+      "inputs": [
+        {
+          "name": "_token",
+          "type": "address",
+          "internalType": "contract IERC20"
+        },
+        {
+          "name": "_tStaking",
+          "type": "address",
+          "internalType": "contract IStaking"
+        },
+        {
+          "name": "_minimumAuthorization",
+          "type": "uint96",
+          "internalType": "uint96"
+        },
+        {
+          "name": "_minOperatorSeconds",
+          "type": "uint256",
+          "internalType": "uint256"
+        },
+        {
+          "name": "_rewardDuration",
+          "type": "uint256",
+          "internalType": "uint256"
+        },
+        {
+          "name": "_deauthorizationDuration",
+          "type": "uint256",
+          "internalType": "uint256"
+        },
+        {
+          "name": "_commitmentDurationOptions",
+          "type": "uint64[]",
+          "internalType": "uint64[]"
+        },
+        {
+          "name": "_commitmentDeadline",
+          "type": "uint64",
+          "internalType": "uint64"
+        }
+      ]
+    },
+    {
+      "type": "error",
+      "name": "AddressEmptyCode",
+      "inputs": [
+        {
+          "name": "target",
+          "type": "address",
+          "internalType": "address"
+        }
+      ]
+    },
+    {
+      "type": "error",
+      "name": "AddressInsufficientBalance",
+      "inputs": [
+        {
+          "name": "account",
+          "type": "address",
+          "internalType": "address"
+        }
+      ]
+    },
+    {
+      "type": "error",
+      "name": "FailedInnerCall",
+      "inputs": []
+    },
+    {
+      "type": "error",
+      "name": "InvalidInitialization",
+      "inputs": []
+    },
+    {
+      "type": "error",
+      "name": "NotInitializing",
+      "inputs": []
+    },
+    {
+      "type": "error",
+      "name": "OwnableInvalidOwner",
+      "inputs": [
+        {
+          "name": "owner",
+          "type": "address",
+          "internalType": "address"
+        }
+      ]
+    },
+    {
+      "type": "error",
+      "name": "OwnableUnauthorizedAccount",
+      "inputs": [
+        {
+          "name": "account",
+          "type": "address",
+          "internalType": "address"
+        }
+      ]
+    },
+    {
+      "type": "error",
+      "name": "SafeCastOverflowedUintDowncast",
+      "inputs": [
+        {
+          "name": "bits",
+          "type": "uint8",
+          "internalType": "uint8"
+        },
+        {
+          "name": "value",
+          "type": "uint256",
+          "internalType": "uint256"
+        }
+      ]
+    },
+    {
+      "type": "error",
+      "name": "SafeERC20FailedOperation",
+      "inputs": [
+        {
+          "name": "token",
+          "type": "address",
+          "internalType": "address"
+        }
+      ]
+    },
+    {
+      "type": "event",
+      "name": "AuthorizationDecreaseApproved",
+      "inputs": [
+        {
+          "name": "stakingProvider",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        },
+        {
+          "name": "fromAmount",
+          "type": "uint96",
+          "internalType": "uint96",
+          "indexed": false
+        },
+        {
+          "name": "toAmount",
+          "type": "uint96",
+          "internalType": "uint96",
+          "indexed": false
+        }
+      ],
+      "anonymous": false
+    },
+    {
+      "type": "event",
+      "name": "AuthorizationDecreaseRequested",
+      "inputs": [
+        {
+          "name": "stakingProvider",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        },
+        {
+          "name": "fromAmount",
+          "type": "uint96",
+          "internalType": "uint96",
+          "indexed": false
+        },
+        {
+          "name": "toAmount",
+          "type": "uint96",
+          "internalType": "uint96",
+          "indexed": false
+        }
+      ],
+      "anonymous": false
+    },
+    {
+      "type": "event",
+      "name": "AuthorizationIncreased",
+      "inputs": [
+        {
+          "name": "stakingProvider",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        },
+        {
+          "name": "fromAmount",
+          "type": "uint96",
+          "internalType": "uint96",
+          "indexed": false
+        },
+        {
+          "name": "toAmount",
+          "type": "uint96",
+          "internalType": "uint96",
+          "indexed": false
+        }
+      ],
+      "anonymous": false
+    },
+    {
+      "type": "event",
+      "name": "AuthorizationInvoluntaryDecreased",
+      "inputs": [
+        {
+          "name": "stakingProvider",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        },
+        {
+          "name": "fromAmount",
+          "type": "uint96",
+          "internalType": "uint96",
+          "indexed": false
+        },
+        {
+          "name": "toAmount",
+          "type": "uint96",
+          "internalType": "uint96",
+          "indexed": false
+        }
+      ],
+      "anonymous": false
+    },
+    {
+      "type": "event",
+      "name": "AuthorizationReSynchronized",
+      "inputs": [
+        {
+          "name": "stakingProvider",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        },
+        {
+          "name": "fromAmount",
+          "type": "uint96",
+          "internalType": "uint96",
+          "indexed": false
+        },
+        {
+          "name": "toAmount",
+          "type": "uint96",
+          "internalType": "uint96",
+          "indexed": false
+        }
+      ],
+      "anonymous": false
+    },
+    {
+      "type": "event",
+      "name": "CommitmentMade",
+      "inputs": [
+        {
+          "name": "stakingProvider",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        },
+        {
+          "name": "endCommitment",
+          "type": "uint256",
+          "internalType": "uint256",
+          "indexed": false
+        }
+      ],
+      "anonymous": false
+    },
+    {
+      "type": "event",
+      "name": "Initialized",
+      "inputs": [
+        {
+          "name": "version",
+          "type": "uint64",
+          "internalType": "uint64",
+          "indexed": false
+        }
+      ],
+      "anonymous": false
+    },
+    {
+      "type": "event",
+      "name": "ManualChildSynchronizationSent",
+      "inputs": [
+        {
+          "name": "stakingProvider",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        },
+        {
+          "name": "authorized",
+          "type": "uint96",
+          "internalType": "uint96",
+          "indexed": false
+        },
+        {
+          "name": "deauthorizing",
+          "type": "uint96",
+          "internalType": "uint96",
+          "indexed": false
+        },
+        {
+          "name": "endDeauthorization",
+          "type": "uint64",
+          "internalType": "uint64",
+          "indexed": false
+        },
+        {
+          "name": "operator",
+          "type": "address",
+          "internalType": "address",
+          "indexed": false
+        }
+      ],
+      "anonymous": false
+    },
+    {
+      "type": "event",
+      "name": "OperatorBonded",
+      "inputs": [
+        {
+          "name": "stakingProvider",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        },
+        {
+          "name": "operator",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        },
+        {
+          "name": "previousOperator",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        },
+        {
+          "name": "startTimestamp",
+          "type": "uint256",
+          "internalType": "uint256",
+          "indexed": false
+        }
+      ],
+      "anonymous": false
+    },
+    {
+      "type": "event",
+      "name": "OperatorConfirmed",
+      "inputs": [
+        {
+          "name": "stakingProvider",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        },
+        {
+          "name": "operator",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        }
+      ],
+      "anonymous": false
+    },
+    {
+      "type": "event",
+      "name": "OwnershipTransferred",
+      "inputs": [
+        {
+          "name": "previousOwner",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        },
+        {
+          "name": "newOwner",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        }
+      ],
+      "anonymous": false
+    },
+    {
+      "type": "event",
+      "name": "RewardAdded",
+      "inputs": [
+        {
+          "name": "reward",
+          "type": "uint256",
+          "internalType": "uint256",
+          "indexed": false
+        }
+      ],
+      "anonymous": false
+    },
+    {
+      "type": "event",
+      "name": "RewardDistributorSet",
+      "inputs": [
+        {
+          "name": "distributor",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        }
+      ],
+      "anonymous": false
+    },
+    {
+      "type": "event",
+      "name": "RewardPaid",
+      "inputs": [
+        {
+          "name": "stakingProvider",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        },
+        {
+          "name": "beneficiary",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        },
+        {
+          "name": "reward",
+          "type": "uint256",
+          "internalType": "uint256",
+          "indexed": false
+        }
+      ],
+      "anonymous": false
+    },
+    {
+      "type": "event",
+      "name": "RewardsWithdrawn",
+      "inputs": [
+        {
+          "name": "stakingProvider",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        },
+        {
+          "name": "amount",
+          "type": "uint96",
+          "internalType": "uint96",
+          "indexed": false
+        }
+      ],
+      "anonymous": false
+    },
+    {
+      "type": "event",
+      "name": "Slashed",
+      "inputs": [
+        {
+          "name": "stakingProvider",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        },
+        {
+          "name": "penalty",
+          "type": "uint256",
+          "internalType": "uint256",
+          "indexed": false
+        },
+        {
+          "name": "investigator",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        },
+        {
+          "name": "reward",
+          "type": "uint256",
+          "internalType": "uint256",
+          "indexed": false
+        }
+      ],
+      "anonymous": false
+    },
+    {
+      "type": "function",
+      "name": "REWARD_PER_TOKEN_MULTIPLIER",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint256",
+          "internalType": "uint256"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "adjudicator",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "address",
+          "internalType": "address"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "approveAuthorizationDecrease",
+      "stateMutability": "nonpayable",
+      "inputs": [
+        {
+          "name": "_stakingProvider",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": []
+    },
+    {
+      "type": "function",
+      "name": "authorizationDecreaseRequested",
+      "stateMutability": "nonpayable",
+      "inputs": [
+        {
+          "name": "_stakingProvider",
+          "type": "address",
+          "internalType": "address"
+        },
+        {
+          "name": "_fromAmount",
+          "type": "uint96",
+          "internalType": "uint96"
+        },
+        {
+          "name": "_toAmount",
+          "type": "uint96",
+          "internalType": "uint96"
+        }
+      ],
+      "outputs": []
+    },
+    {
+      "type": "function",
+      "name": "authorizationIncreased",
+      "stateMutability": "nonpayable",
+      "inputs": [
+        {
+          "name": "_stakingProvider",
+          "type": "address",
+          "internalType": "address"
+        },
+        {
+          "name": "_fromAmount",
+          "type": "uint96",
+          "internalType": "uint96"
+        },
+        {
+          "name": "_toAmount",
+          "type": "uint96",
+          "internalType": "uint96"
+        }
+      ],
+      "outputs": []
+    },
+    {
+      "type": "function",
+      "name": "authorizationParameters",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "_minimumAuthorization",
+          "type": "uint96",
+          "internalType": "uint96"
+        },
+        {
+          "name": "authorizationDecreaseDelay",
+          "type": "uint64",
+          "internalType": "uint64"
+        },
+        {
+          "name": "authorizationDecreaseChangePeriod",
+          "type": "uint64",
+          "internalType": "uint64"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "authorizedOverall",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint96",
+          "internalType": "uint96"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "authorizedStake",
+      "stateMutability": "view",
+      "inputs": [
+        {
+          "name": "_stakingProvider",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint96",
+          "internalType": "uint96"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "availableRewards",
+      "stateMutability": "view",
+      "inputs": [
+        {
+          "name": "_stakingProvider",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint96",
+          "internalType": "uint96"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "bondOperator",
+      "stateMutability": "nonpayable",
+      "inputs": [
+        {
+          "name": "_stakingProvider",
+          "type": "address",
+          "internalType": "address"
+        },
+        {
+          "name": "_operator",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": []
+    },
+    {
+      "type": "function",
+      "name": "childApplication",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "address",
+          "internalType": "contract ITACoRootToChild"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "commitmentDeadline",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint64",
+          "internalType": "uint64"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "commitmentDurationOption1",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint64",
+          "internalType": "uint64"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "commitmentDurationOption2",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint64",
+          "internalType": "uint64"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "commitmentDurationOption3",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint64",
+          "internalType": "uint64"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "commitmentDurationOption4",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint64",
+          "internalType": "uint64"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "confirmOperatorAddress",
+      "stateMutability": "nonpayable",
+      "inputs": [
+        {
+          "name": "_operator",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": []
+    },
+    {
+      "type": "function",
+      "name": "deauthorizationDuration",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint256",
+          "internalType": "uint256"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "eligibleStake",
+      "stateMutability": "view",
+      "inputs": [
+        {
+          "name": "_stakingProvider",
+          "type": "address",
+          "internalType": "address"
+        },
+        {
+          "name": "_endDate",
+          "type": "uint256",
+          "internalType": "uint256"
+        }
+      ],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint96",
+          "internalType": "uint96"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "getActiveStakingProviders",
+      "stateMutability": "view",
+      "inputs": [
+        {
+          "name": "_startIndex",
+          "type": "uint256",
+          "internalType": "uint256"
+        },
+        {
+          "name": "_maxStakingProviders",
+          "type": "uint256",
+          "internalType": "uint256"
+        },
+        {
+          "name": "_cohortDuration",
+          "type": "uint32",
+          "internalType": "uint32"
+        }
+      ],
+      "outputs": [
+        {
+          "name": "allAuthorizedTokens",
+          "type": "uint256",
+          "internalType": "uint256"
+        },
+        {
+          "name": "activeStakingProviders",
+          "type": "bytes32[]",
+          "internalType": "bytes32[]"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "getBeneficiary",
+      "stateMutability": "view",
+      "inputs": [
+        {
+          "name": "_stakingProvider",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": [
+        {
+          "name": "beneficiary",
+          "type": "address",
+          "internalType": "address payable"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "getStakingProvidersLength",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint256",
+          "internalType": "uint256"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "initialize",
+      "stateMutability": "nonpayable",
+      "inputs": [],
+      "outputs": []
+    },
+    {
+      "type": "function",
+      "name": "involuntaryAuthorizationDecrease",
+      "stateMutability": "nonpayable",
+      "inputs": [
+        {
+          "name": "_stakingProvider",
+          "type": "address",
+          "internalType": "address"
+        },
+        {
+          "name": "_fromAmount",
+          "type": "uint96",
+          "internalType": "uint96"
+        },
+        {
+          "name": "_toAmount",
+          "type": "uint96",
+          "internalType": "uint96"
+        }
+      ],
+      "outputs": []
+    },
+    {
+      "type": "function",
+      "name": "isAuthorized",
+      "stateMutability": "view",
+      "inputs": [
+        {
+          "name": "_stakingProvider",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": [
+        {
+          "name": "",
+          "type": "bool",
+          "internalType": "bool"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "isOperatorConfirmed",
+      "stateMutability": "view",
+      "inputs": [
+        {
+          "name": "_operator",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": [
+        {
+          "name": "",
+          "type": "bool",
+          "internalType": "bool"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "lastTimeRewardApplicable",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint256",
+          "internalType": "uint256"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "lastUpdateTime",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint256",
+          "internalType": "uint256"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "makeCommitment",
+      "stateMutability": "nonpayable",
+      "inputs": [
+        {
+          "name": "_stakingProvider",
+          "type": "address",
+          "internalType": "address"
+        },
+        {
+          "name": "_commitmentDuration",
+          "type": "uint64",
+          "internalType": "uint64"
+        }
+      ],
+      "outputs": []
+    },
+    {
+      "type": "function",
+      "name": "manualChildSynchronization",
+      "stateMutability": "nonpayable",
+      "inputs": [
+        {
+          "name": "_stakingProvider",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": []
+    },
+    {
+      "type": "function",
+      "name": "minOperatorSeconds",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint256",
+          "internalType": "uint256"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "minimumAuthorization",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint96",
+          "internalType": "uint96"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "operatorToStakingProvider",
+      "stateMutability": "view",
+      "inputs": [
+        {
+          "name": "_operator",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": [
+        {
+          "name": "",
+          "type": "address",
+          "internalType": "address"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "owner",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "address",
+          "internalType": "address"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "pendingAuthorizationDecrease",
+      "stateMutability": "view",
+      "inputs": [
+        {
+          "name": "_stakingProvider",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint96",
+          "internalType": "uint96"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "periodFinish",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint256",
+          "internalType": "uint256"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "pushReward",
+      "stateMutability": "nonpayable",
+      "inputs": [
+        {
+          "name": "_reward",
+          "type": "uint96",
+          "internalType": "uint96"
+        }
+      ],
+      "outputs": []
+    },
+    {
+      "type": "function",
+      "name": "registerOperator",
+      "stateMutability": "nonpayable",
+      "inputs": [
+        {
+          "name": "_operator",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": []
+    },
+    {
+      "type": "function",
+      "name": "remainingAuthorizationDecreaseDelay",
+      "stateMutability": "view",
+      "inputs": [
+        {
+          "name": "_stakingProvider",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint64",
+          "internalType": "uint64"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "renounceOwnership",
+      "stateMutability": "nonpayable",
+      "inputs": [],
+      "outputs": []
+    },
+    {
+      "type": "function",
+      "name": "resynchronizeAuthorization",
+      "stateMutability": "nonpayable",
+      "inputs": [
+        {
+          "name": "_stakingProvider",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": []
+    },
+    {
+      "type": "function",
+      "name": "rewardDistributor",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "address",
+          "internalType": "address"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "rewardDuration",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint256",
+          "internalType": "uint256"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "rewardPerToken",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint160",
+          "internalType": "uint160"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "rewardPerTokenStored",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint160",
+          "internalType": "uint160"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "rewardRateDecimals",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint256",
+          "internalType": "uint256"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "setAdjudicator",
+      "stateMutability": "nonpayable",
+      "inputs": [
+        {
+          "name": "_adjudicator",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": []
+    },
+    {
+      "type": "function",
+      "name": "setChildApplication",
+      "stateMutability": "nonpayable",
+      "inputs": [
+        {
+          "name": "_childApplication",
+          "type": "address",
+          "internalType": "contract ITACoRootToChild"
+        }
+      ],
+      "outputs": []
+    },
+    {
+      "type": "function",
+      "name": "setRewardDistributor",
+      "stateMutability": "nonpayable",
+      "inputs": [
+        {
+          "name": "_rewardDistributor",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": []
+    },
+    {
+      "type": "function",
+      "name": "slash",
+      "stateMutability": "nonpayable",
+      "inputs": [
+        {
+          "name": "_stakingProvider",
+          "type": "address",
+          "internalType": "address"
+        },
+        {
+          "name": "_penalty",
+          "type": "uint96",
+          "internalType": "uint96"
+        },
+        {
+          "name": "_investigator",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": []
+    },
+    {
+      "type": "function",
+      "name": "stakingProviderInfo",
+      "stateMutability": "view",
+      "inputs": [
+        {
+          "name": "",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": [
+        {
+          "name": "operator",
+          "type": "address",
+          "internalType": "address"
+        },
+        {
+          "name": "operatorConfirmed",
+          "type": "bool",
+          "internalType": "bool"
+        },
+        {
+          "name": "operatorStartTimestamp",
+          "type": "uint64",
+          "internalType": "uint64"
+        },
+        {
+          "name": "authorized",
+          "type": "uint96",
+          "internalType": "uint96"
+        },
+        {
+          "name": "deauthorizing",
+          "type": "uint96",
+          "internalType": "uint96"
+        },
+        {
+          "name": "endDeauthorization",
+          "type": "uint64",
+          "internalType": "uint64"
+        },
+        {
+          "name": "tReward",
+          "type": "uint96",
+          "internalType": "uint96"
+        },
+        {
+          "name": "rewardPerTokenPaid",
+          "type": "uint160",
+          "internalType": "uint160"
+        },
+        {
+          "name": "endCommitment",
+          "type": "uint64",
+          "internalType": "uint64"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "stakingProviderToOperator",
+      "stateMutability": "view",
+      "inputs": [
+        {
+          "name": "_stakingProvider",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": [
+        {
+          "name": "",
+          "type": "address",
+          "internalType": "address"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "stakingProviders",
+      "stateMutability": "view",
+      "inputs": [
+        {
+          "name": "",
+          "type": "uint256",
+          "internalType": "uint256"
+        }
+      ],
+      "outputs": [
+        {
+          "name": "",
+          "type": "address",
+          "internalType": "address"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "tStaking",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "address",
+          "internalType": "contract IStaking"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "token",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "address",
+          "internalType": "contract IERC20"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "transferOwnership",
+      "stateMutability": "nonpayable",
+      "inputs": [
+        {
+          "name": "newOwner",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": []
+    },
+    {
+      "type": "function",
+      "name": "withdrawRewards",
+      "stateMutability": "nonpayable",
+      "inputs": [
+        {
+          "name": "_stakingProvider",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": []
+    }
+  ],
+  "tx_hash": "0x4824e7d3b6dae9ec69b79b9f0578853c51fd92a49b0edce45d892d6cdf7901bd",
+  "block_number": 5048617,
+  "deployer": "0x3B42d26E19FF860bC4dEbB920DD8caA53F93c600"
+}
diff --git a/src/threshold-ts/multicall/__test__/multicall.test.ts b/src/threshold-ts/multicall/__test__/multicall.test.ts
index c55736470..f73fa12e5 100644
--- a/src/threshold-ts/multicall/__test__/multicall.test.ts
+++ b/src/threshold-ts/multicall/__test__/multicall.test.ts
@@ -5,7 +5,7 @@ import {
   IMulticall,
   Multicall,
   MULTICALL_ABI,
-  MULTICALL_ADDRESSESS,
+  MULTICALL_ADDRESSES,
 } from ".."
 import { getContract } from "../../utils"
 
@@ -35,7 +35,7 @@ describe("Multicall test", () => {
 
   test("should create the instance correctly", () => {
     expect(getContract).toHaveBeenCalledWith(
-      MULTICALL_ADDRESSESS[config.chainId],
+      MULTICALL_ADDRESSES[config.chainId],
       MULTICALL_ABI,
       config.providerOrSigner,
       config.account
diff --git a/src/threshold-ts/multicall/index.ts b/src/threshold-ts/multicall/index.ts
index adb48749d..c5528393c 100644
--- a/src/threshold-ts/multicall/index.ts
+++ b/src/threshold-ts/multicall/index.ts
@@ -1,7 +1,8 @@
 import { Contract } from "ethers"
 import { Interface } from "@ethersproject/abi"
 import { EthereumConfig } from "../types"
-import { AddressZero, getContract } from "../utils"
+import { getContract } from "../utils"
+import { SupportedChainIds } from "../../networks/enums/networks"
 
 export interface ContractCall {
   address: string
@@ -38,17 +39,18 @@ export const MULTICALL_ABI = [
   "function getEthBalance(address addr) view returns (uint256 balance)",
   "function getCurrentBlockTimestamp() view returns (uint256 timestamp)",
 ]
-export const MULTICALL_ADDRESSESS = {
-  1: "0xeefba1e63905ef1d7acba5a8513c70307c1ce441",
-  11155111: "0xcA11bde05977b3631167028862bE2a173976CA11",
-  1337: process.env.REACT_APP_MULTICALL_ADDRESS || AddressZero,
+
+export const MULTICALL_ADDRESSES = {
+  [SupportedChainIds.Ethereum]: "0xeefba1e63905ef1d7acba5a8513c70307c1ce441",
+  [SupportedChainIds.Sepolia]: "0xcA11bde05977b3631167028862bE2a173976CA11",
+  [SupportedChainIds.Localhost]: process.env.REACT_APP_MULTICALL_ADDRESS,
 } as Record<number | string, string>
 
 export class Multicall implements IMulticall {
   private _multicall: Contract
 
   constructor(config: EthereumConfig) {
-    const address = MULTICALL_ADDRESSESS[config.chainId]
+    const address = MULTICALL_ADDRESSES[config.chainId]
     if (!address) {
       throw new Error("Unsupported chain id")
     }
diff --git a/src/threshold-ts/staking/dapp-development-sepolia-artifacts/LegacyKeepStaking.json b/src/threshold-ts/staking/dapp-development-sepolia-artifacts/LegacyKeepStaking.json
new file mode 100644
index 000000000..7ed91c483
--- /dev/null
+++ b/src/threshold-ts/staking/dapp-development-sepolia-artifacts/LegacyKeepStaking.json
@@ -0,0 +1,915 @@
+{
+  "address": "0xa07f4E37C2E7089Ea3AFffbe51A6A281833a4D14",
+  "abi": [
+    {
+      "inputs": [
+        {
+          "internalType": "contract ERC20Burnable",
+          "name": "_token",
+          "type": "address"
+        },
+        {
+          "internalType": "contract TokenGrant",
+          "name": "_tokenGrant",
+          "type": "address"
+        },
+        {
+          "internalType": "contract TokenStakingEscrow",
+          "name": "_escrow",
+          "type": "address"
+        },
+        {
+          "internalType": "contract KeepRegistry",
+          "name": "_registry",
+          "type": "address"
+        },
+        {
+          "internalType": "uint256",
+          "name": "_initializationPeriod",
+          "type": "uint256"
+        }
+      ],
+      "payable": false,
+      "stateMutability": "nonpayable",
+      "type": "constructor"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "operator",
+          "type": "address"
+        },
+        {
+          "indexed": false,
+          "internalType": "address",
+          "name": "lockCreator",
+          "type": "address"
+        }
+      ],
+      "name": "ExpiredLockReleased",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "operator",
+          "type": "address"
+        },
+        {
+          "indexed": false,
+          "internalType": "address",
+          "name": "lockCreator",
+          "type": "address"
+        }
+      ],
+      "name": "LockReleased",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "operator",
+          "type": "address"
+        },
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "beneficiary",
+          "type": "address"
+        },
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "authorizer",
+          "type": "address"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "value",
+          "type": "uint256"
+        }
+      ],
+      "name": "OperatorStaked",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": false,
+          "internalType": "address",
+          "name": "operator",
+          "type": "address"
+        }
+      ],
+      "name": "RecoveredStake",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "owner",
+          "type": "address"
+        },
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "operator",
+          "type": "address"
+        }
+      ],
+      "name": "StakeDelegated",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "operator",
+          "type": "address"
+        },
+        {
+          "indexed": false,
+          "internalType": "address",
+          "name": "lockCreator",
+          "type": "address"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "until",
+          "type": "uint256"
+        }
+      ],
+      "name": "StakeLocked",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "operator",
+          "type": "address"
+        },
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "newOwner",
+          "type": "address"
+        }
+      ],
+      "name": "StakeOwnershipTransferred",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "operator",
+          "type": "address"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "amount",
+          "type": "uint256"
+        }
+      ],
+      "name": "TokensSeized",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "operator",
+          "type": "address"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "amount",
+          "type": "uint256"
+        }
+      ],
+      "name": "TokensSlashed",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "operator",
+          "type": "address"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "newAmount",
+          "type": "uint256"
+        }
+      ],
+      "name": "TopUpCompleted",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "operator",
+          "type": "address"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "topUp",
+          "type": "uint256"
+        }
+      ],
+      "name": "TopUpInitiated",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "operator",
+          "type": "address"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "undelegatedAt",
+          "type": "uint256"
+        }
+      ],
+      "name": "Undelegated",
+      "type": "event"
+    },
+    {
+      "constant": true,
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "_operator",
+          "type": "address"
+        },
+        {
+          "internalType": "address",
+          "name": "_operatorContract",
+          "type": "address"
+        }
+      ],
+      "name": "activeStake",
+      "outputs": [
+        {
+          "internalType": "uint256",
+          "name": "balance",
+          "type": "uint256"
+        }
+      ],
+      "payable": false,
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "constant": false,
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "_operator",
+          "type": "address"
+        },
+        {
+          "internalType": "address",
+          "name": "_operatorContract",
+          "type": "address"
+        }
+      ],
+      "name": "authorizeOperatorContract",
+      "outputs": [],
+      "payable": false,
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "constant": true,
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "_operator",
+          "type": "address"
+        }
+      ],
+      "name": "authorizerOf",
+      "outputs": [
+        {
+          "internalType": "address",
+          "name": "",
+          "type": "address"
+        }
+      ],
+      "payable": false,
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "constant": true,
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "_address",
+          "type": "address"
+        }
+      ],
+      "name": "balanceOf",
+      "outputs": [
+        {
+          "internalType": "uint256",
+          "name": "balance",
+          "type": "uint256"
+        }
+      ],
+      "payable": false,
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "constant": true,
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "_operator",
+          "type": "address"
+        }
+      ],
+      "name": "beneficiaryOf",
+      "outputs": [
+        {
+          "internalType": "address payable",
+          "name": "",
+          "type": "address"
+        }
+      ],
+      "payable": false,
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "constant": false,
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "_operator",
+          "type": "address"
+        }
+      ],
+      "name": "cancelStake",
+      "outputs": [],
+      "payable": false,
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "constant": false,
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "delegatedAuthoritySource",
+          "type": "address"
+        }
+      ],
+      "name": "claimDelegatedAuthority",
+      "outputs": [],
+      "payable": false,
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "constant": false,
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "_operator",
+          "type": "address"
+        }
+      ],
+      "name": "commitTopUp",
+      "outputs": [],
+      "payable": false,
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "constant": true,
+      "inputs": [],
+      "name": "deployedAt",
+      "outputs": [
+        {
+          "internalType": "uint256",
+          "name": "",
+          "type": "uint256"
+        }
+      ],
+      "payable": false,
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "constant": true,
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "_operator",
+          "type": "address"
+        },
+        {
+          "internalType": "address",
+          "name": "_operatorContract",
+          "type": "address"
+        }
+      ],
+      "name": "eligibleStake",
+      "outputs": [
+        {
+          "internalType": "uint256",
+          "name": "balance",
+          "type": "uint256"
+        }
+      ],
+      "payable": false,
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "constant": true,
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "operatorContract",
+          "type": "address"
+        }
+      ],
+      "name": "getAuthoritySource",
+      "outputs": [
+        {
+          "internalType": "address",
+          "name": "",
+          "type": "address"
+        }
+      ],
+      "payable": false,
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "constant": true,
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "_operator",
+          "type": "address"
+        }
+      ],
+      "name": "getDelegationInfo",
+      "outputs": [
+        {
+          "internalType": "uint256",
+          "name": "amount",
+          "type": "uint256"
+        },
+        {
+          "internalType": "uint256",
+          "name": "createdAt",
+          "type": "uint256"
+        },
+        {
+          "internalType": "uint256",
+          "name": "undelegatedAt",
+          "type": "uint256"
+        }
+      ],
+      "payable": false,
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "constant": true,
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "operator",
+          "type": "address"
+        }
+      ],
+      "name": "getLocks",
+      "outputs": [
+        {
+          "internalType": "address[]",
+          "name": "creators",
+          "type": "address[]"
+        },
+        {
+          "internalType": "uint256[]",
+          "name": "expirations",
+          "type": "uint256[]"
+        }
+      ],
+      "payable": false,
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "constant": true,
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "staker",
+          "type": "address"
+        },
+        {
+          "internalType": "address",
+          "name": "operatorContract",
+          "type": "address"
+        }
+      ],
+      "name": "hasMinimumStake",
+      "outputs": [
+        {
+          "internalType": "bool",
+          "name": "",
+          "type": "bool"
+        }
+      ],
+      "payable": false,
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "constant": true,
+      "inputs": [],
+      "name": "initializationPeriod",
+      "outputs": [
+        {
+          "internalType": "uint256",
+          "name": "",
+          "type": "uint256"
+        }
+      ],
+      "payable": false,
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "constant": true,
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "_operatorContract",
+          "type": "address"
+        }
+      ],
+      "name": "isApprovedOperatorContract",
+      "outputs": [
+        {
+          "internalType": "bool",
+          "name": "",
+          "type": "bool"
+        }
+      ],
+      "payable": false,
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "constant": true,
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "_operator",
+          "type": "address"
+        },
+        {
+          "internalType": "address",
+          "name": "_operatorContract",
+          "type": "address"
+        }
+      ],
+      "name": "isAuthorizedForOperator",
+      "outputs": [
+        {
+          "internalType": "bool",
+          "name": "",
+          "type": "bool"
+        }
+      ],
+      "payable": false,
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "constant": true,
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "operator",
+          "type": "address"
+        }
+      ],
+      "name": "isStakeLocked",
+      "outputs": [
+        {
+          "internalType": "bool",
+          "name": "",
+          "type": "bool"
+        }
+      ],
+      "payable": false,
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "constant": false,
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "operator",
+          "type": "address"
+        },
+        {
+          "internalType": "uint256",
+          "name": "duration",
+          "type": "uint256"
+        }
+      ],
+      "name": "lockStake",
+      "outputs": [],
+      "payable": false,
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "constant": true,
+      "inputs": [],
+      "name": "minimumStake",
+      "outputs": [
+        {
+          "internalType": "uint256",
+          "name": "",
+          "type": "uint256"
+        }
+      ],
+      "payable": false,
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "constant": true,
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "_operator",
+          "type": "address"
+        }
+      ],
+      "name": "ownerOf",
+      "outputs": [
+        {
+          "internalType": "address",
+          "name": "",
+          "type": "address"
+        }
+      ],
+      "payable": false,
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "constant": false,
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "_from",
+          "type": "address"
+        },
+        {
+          "internalType": "uint256",
+          "name": "_value",
+          "type": "uint256"
+        },
+        {
+          "internalType": "address",
+          "name": "_token",
+          "type": "address"
+        },
+        {
+          "internalType": "bytes",
+          "name": "_extraData",
+          "type": "bytes"
+        }
+      ],
+      "name": "receiveApproval",
+      "outputs": [],
+      "payable": false,
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "constant": false,
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "_operator",
+          "type": "address"
+        }
+      ],
+      "name": "recoverStake",
+      "outputs": [],
+      "payable": false,
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "constant": false,
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "operator",
+          "type": "address"
+        },
+        {
+          "internalType": "address",
+          "name": "operatorContract",
+          "type": "address"
+        }
+      ],
+      "name": "releaseExpiredLock",
+      "outputs": [],
+      "payable": false,
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "constant": false,
+      "inputs": [
+        {
+          "internalType": "uint256",
+          "name": "amountToSeize",
+          "type": "uint256"
+        },
+        {
+          "internalType": "uint256",
+          "name": "rewardMultiplier",
+          "type": "uint256"
+        },
+        {
+          "internalType": "address",
+          "name": "tattletale",
+          "type": "address"
+        },
+        {
+          "internalType": "address[]",
+          "name": "misbehavedOperators",
+          "type": "address[]"
+        }
+      ],
+      "name": "seize",
+      "outputs": [],
+      "payable": false,
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "constant": false,
+      "inputs": [
+        {
+          "internalType": "uint256",
+          "name": "amountToSlash",
+          "type": "uint256"
+        },
+        {
+          "internalType": "address[]",
+          "name": "misbehavedOperators",
+          "type": "address[]"
+        }
+      ],
+      "name": "slash",
+      "outputs": [],
+      "payable": false,
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "constant": false,
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "operator",
+          "type": "address"
+        },
+        {
+          "internalType": "address",
+          "name": "newOwner",
+          "type": "address"
+        }
+      ],
+      "name": "transferStakeOwnership",
+      "outputs": [],
+      "payable": false,
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "constant": false,
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "_operator",
+          "type": "address"
+        }
+      ],
+      "name": "undelegate",
+      "outputs": [],
+      "payable": false,
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "constant": false,
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "_operator",
+          "type": "address"
+        },
+        {
+          "internalType": "uint256",
+          "name": "_undelegationTimestamp",
+          "type": "uint256"
+        }
+      ],
+      "name": "undelegateAt",
+      "outputs": [],
+      "payable": false,
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "constant": true,
+      "inputs": [],
+      "name": "undelegationPeriod",
+      "outputs": [
+        {
+          "internalType": "uint256",
+          "name": "",
+          "type": "uint256"
+        }
+      ],
+      "payable": false,
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "constant": false,
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "operator",
+          "type": "address"
+        }
+      ],
+      "name": "unlockStake",
+      "outputs": [],
+      "payable": false,
+      "stateMutability": "nonpayable",
+      "type": "function"
+    }
+  ]
+}
diff --git a/src/threshold-ts/staking/dapp-development-sepolia-artifacts/TokenStaking.json b/src/threshold-ts/staking/dapp-development-sepolia-artifacts/TokenStaking.json
new file mode 100644
index 000000000..f2b8ef5fa
--- /dev/null
+++ b/src/threshold-ts/staking/dapp-development-sepolia-artifacts/TokenStaking.json
@@ -0,0 +1,1591 @@
+{
+  "address": "0x3d4cb85c0e3c5bd1667B7E30f3E86B3FAB878Ff8",
+  "abi": [
+    {
+      "inputs": [
+        {
+          "internalType": "contract T",
+          "name": "_token",
+          "type": "address"
+        },
+        {
+          "internalType": "contract IKeepTokenStaking",
+          "name": "_keepStakingContract",
+          "type": "address"
+        },
+        {
+          "internalType": "contract INuCypherStakingEscrow",
+          "name": "_nucypherStakingContract",
+          "type": "address"
+        },
+        {
+          "internalType": "contract VendingMachine",
+          "name": "_keepVendingMachine",
+          "type": "address"
+        },
+        {
+          "internalType": "contract VendingMachine",
+          "name": "_nucypherVendingMachine",
+          "type": "address"
+        },
+        {
+          "internalType": "contract KeepStake",
+          "name": "_keepStake",
+          "type": "address"
+        }
+      ],
+      "stateMutability": "nonpayable",
+      "type": "constructor"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "application",
+          "type": "address"
+        },
+        {
+          "indexed": true,
+          "internalType": "enum TokenStaking.ApplicationStatus",
+          "name": "newStatus",
+          "type": "uint8"
+        }
+      ],
+      "name": "ApplicationStatusChanged",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "ceiling",
+          "type": "uint256"
+        }
+      ],
+      "name": "AuthorizationCeilingSet",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        },
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "application",
+          "type": "address"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint96",
+          "name": "fromAmount",
+          "type": "uint96"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint96",
+          "name": "toAmount",
+          "type": "uint96"
+        }
+      ],
+      "name": "AuthorizationDecreaseApproved",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        },
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "application",
+          "type": "address"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint96",
+          "name": "fromAmount",
+          "type": "uint96"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint96",
+          "name": "toAmount",
+          "type": "uint96"
+        }
+      ],
+      "name": "AuthorizationDecreaseRequested",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        },
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "application",
+          "type": "address"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint96",
+          "name": "fromAmount",
+          "type": "uint96"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint96",
+          "name": "toAmount",
+          "type": "uint96"
+        }
+      ],
+      "name": "AuthorizationIncreased",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        },
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "application",
+          "type": "address"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint96",
+          "name": "fromAmount",
+          "type": "uint96"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint96",
+          "name": "toAmount",
+          "type": "uint96"
+        },
+        {
+          "indexed": true,
+          "internalType": "bool",
+          "name": "successfulCall",
+          "type": "bool"
+        }
+      ],
+      "name": "AuthorizationInvoluntaryDecreased",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "delegator",
+          "type": "address"
+        },
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "fromDelegate",
+          "type": "address"
+        },
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "toDelegate",
+          "type": "address"
+        }
+      ],
+      "name": "DelegateChanged",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "delegate",
+          "type": "address"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "previousBalance",
+          "type": "uint256"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "newBalance",
+          "type": "uint256"
+        }
+      ],
+      "name": "DelegateVotesChanged",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": false,
+          "internalType": "address",
+          "name": "oldGovernance",
+          "type": "address"
+        },
+        {
+          "indexed": false,
+          "internalType": "address",
+          "name": "newGovernance",
+          "type": "address"
+        }
+      ],
+      "name": "GovernanceTransferred",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": false,
+          "internalType": "uint96",
+          "name": "amount",
+          "type": "uint96"
+        }
+      ],
+      "name": "MinimumStakeAmountSet",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": false,
+          "internalType": "uint96",
+          "name": "reward",
+          "type": "uint96"
+        }
+      ],
+      "name": "NotificationRewardPushed",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": false,
+          "internalType": "uint96",
+          "name": "reward",
+          "type": "uint96"
+        }
+      ],
+      "name": "NotificationRewardSet",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": false,
+          "internalType": "address",
+          "name": "recipient",
+          "type": "address"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint96",
+          "name": "amount",
+          "type": "uint96"
+        }
+      ],
+      "name": "NotificationRewardWithdrawn",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "notifier",
+          "type": "address"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "amount",
+          "type": "uint256"
+        }
+      ],
+      "name": "NotifierRewarded",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        },
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "oldOwner",
+          "type": "address"
+        },
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "newOwner",
+          "type": "address"
+        }
+      ],
+      "name": "OwnerRefreshed",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "application",
+          "type": "address"
+        },
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "panicButton",
+          "type": "address"
+        }
+      ],
+      "name": "PanicButtonSet",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "caller",
+          "type": "address"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "count",
+          "type": "uint256"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "tAmount",
+          "type": "uint256"
+        }
+      ],
+      "name": "SlashingProcessed",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": false,
+          "internalType": "uint96",
+          "name": "penalty",
+          "type": "uint96"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "rewardMultiplier",
+          "type": "uint256"
+        }
+      ],
+      "name": "StakeDiscrepancyPenaltySet",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "enum IStaking.StakeType",
+          "name": "stakeType",
+          "type": "uint8"
+        },
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "owner",
+          "type": "address"
+        },
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        },
+        {
+          "indexed": false,
+          "internalType": "address",
+          "name": "beneficiary",
+          "type": "address"
+        },
+        {
+          "indexed": false,
+          "internalType": "address",
+          "name": "authorizer",
+          "type": "address"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint96",
+          "name": "amount",
+          "type": "uint96"
+        }
+      ],
+      "name": "Staked",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint96",
+          "name": "amount",
+          "type": "uint96"
+        },
+        {
+          "indexed": true,
+          "internalType": "bool",
+          "name": "discrepancy",
+          "type": "bool"
+        }
+      ],
+      "name": "TokensSeized",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint96",
+          "name": "amount",
+          "type": "uint96"
+        }
+      ],
+      "name": "ToppedUp",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint96",
+          "name": "amount",
+          "type": "uint96"
+        }
+      ],
+      "name": "Unstaked",
+      "type": "event"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "",
+          "type": "address"
+        }
+      ],
+      "name": "applicationInfo",
+      "outputs": [
+        {
+          "internalType": "enum TokenStaking.ApplicationStatus",
+          "name": "status",
+          "type": "uint8"
+        },
+        {
+          "internalType": "address",
+          "name": "panicButton",
+          "type": "address"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "uint256",
+          "name": "",
+          "type": "uint256"
+        }
+      ],
+      "name": "applications",
+      "outputs": [
+        {
+          "internalType": "address",
+          "name": "",
+          "type": "address"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "application",
+          "type": "address"
+        }
+      ],
+      "name": "approveApplication",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        }
+      ],
+      "name": "approveAuthorizationDecrease",
+      "outputs": [
+        {
+          "internalType": "uint96",
+          "name": "",
+          "type": "uint96"
+        }
+      ],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "authorizationCeiling",
+      "outputs": [
+        {
+          "internalType": "uint256",
+          "name": "",
+          "type": "uint256"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        },
+        {
+          "internalType": "address",
+          "name": "application",
+          "type": "address"
+        }
+      ],
+      "name": "authorizedStake",
+      "outputs": [
+        {
+          "internalType": "uint96",
+          "name": "",
+          "type": "uint96"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "account",
+          "type": "address"
+        },
+        {
+          "internalType": "uint32",
+          "name": "pos",
+          "type": "uint32"
+        }
+      ],
+      "name": "checkpoints",
+      "outputs": [
+        {
+          "components": [
+            {
+              "internalType": "uint32",
+              "name": "fromBlock",
+              "type": "uint32"
+            },
+            {
+              "internalType": "uint96",
+              "name": "votes",
+              "type": "uint96"
+            }
+          ],
+          "internalType": "struct Checkpoints.Checkpoint",
+          "name": "checkpoint",
+          "type": "tuple"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        },
+        {
+          "internalType": "address",
+          "name": "delegatee",
+          "type": "address"
+        }
+      ],
+      "name": "delegateVoting",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "account",
+          "type": "address"
+        }
+      ],
+      "name": "delegates",
+      "outputs": [
+        {
+          "internalType": "address",
+          "name": "",
+          "type": "address"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "application",
+          "type": "address"
+        }
+      ],
+      "name": "disableApplication",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        },
+        {
+          "internalType": "address",
+          "name": "application",
+          "type": "address"
+        }
+      ],
+      "name": "forceDecreaseAuthorization",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "getApplicationsLength",
+      "outputs": [
+        {
+          "internalType": "uint256",
+          "name": "",
+          "type": "uint256"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        },
+        {
+          "internalType": "address",
+          "name": "application",
+          "type": "address"
+        }
+      ],
+      "name": "getAvailableToAuthorize",
+      "outputs": [
+        {
+          "internalType": "uint96",
+          "name": "availableTValue",
+          "type": "uint96"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        },
+        {
+          "internalType": "enum IStaking.StakeType",
+          "name": "stakeTypes",
+          "type": "uint8"
+        }
+      ],
+      "name": "getMinStaked",
+      "outputs": [
+        {
+          "internalType": "uint96",
+          "name": "",
+          "type": "uint96"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "uint256",
+          "name": "blockNumber",
+          "type": "uint256"
+        }
+      ],
+      "name": "getPastTotalSupply",
+      "outputs": [
+        {
+          "internalType": "uint96",
+          "name": "",
+          "type": "uint96"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "account",
+          "type": "address"
+        },
+        {
+          "internalType": "uint256",
+          "name": "blockNumber",
+          "type": "uint256"
+        }
+      ],
+      "name": "getPastVotes",
+      "outputs": [
+        {
+          "internalType": "uint96",
+          "name": "",
+          "type": "uint96"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "getSlashingQueueLength",
+      "outputs": [
+        {
+          "internalType": "uint256",
+          "name": "",
+          "type": "uint256"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        }
+      ],
+      "name": "getStartStakingTimestamp",
+      "outputs": [
+        {
+          "internalType": "uint256",
+          "name": "",
+          "type": "uint256"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "account",
+          "type": "address"
+        }
+      ],
+      "name": "getVotes",
+      "outputs": [
+        {
+          "internalType": "uint96",
+          "name": "",
+          "type": "uint96"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "governance",
+      "outputs": [
+        {
+          "internalType": "address",
+          "name": "",
+          "type": "address"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        },
+        {
+          "internalType": "address",
+          "name": "application",
+          "type": "address"
+        },
+        {
+          "internalType": "uint96",
+          "name": "amount",
+          "type": "uint96"
+        }
+      ],
+      "name": "increaseAuthorization",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "initialize",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "minTStakeAmount",
+      "outputs": [
+        {
+          "internalType": "uint96",
+          "name": "",
+          "type": "uint96"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "notificationReward",
+      "outputs": [
+        {
+          "internalType": "uint256",
+          "name": "",
+          "type": "uint256"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "notifiersTreasury",
+      "outputs": [
+        {
+          "internalType": "uint256",
+          "name": "",
+          "type": "uint256"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        }
+      ],
+      "name": "notifyKeepStakeDiscrepancy",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        }
+      ],
+      "name": "notifyNuStakeDiscrepancy",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "account",
+          "type": "address"
+        }
+      ],
+      "name": "numCheckpoints",
+      "outputs": [
+        {
+          "internalType": "uint32",
+          "name": "",
+          "type": "uint32"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "application",
+          "type": "address"
+        }
+      ],
+      "name": "pauseApplication",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "uint256",
+          "name": "count",
+          "type": "uint256"
+        }
+      ],
+      "name": "processSlashing",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "uint96",
+          "name": "reward",
+          "type": "uint96"
+        }
+      ],
+      "name": "pushNotificationReward",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        }
+      ],
+      "name": "refreshKeepStakeOwner",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        },
+        {
+          "internalType": "address",
+          "name": "application",
+          "type": "address"
+        },
+        {
+          "internalType": "uint96",
+          "name": "amount",
+          "type": "uint96"
+        }
+      ],
+      "name": "requestAuthorizationDecrease",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        }
+      ],
+      "name": "requestAuthorizationDecrease",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        }
+      ],
+      "name": "rolesOf",
+      "outputs": [
+        {
+          "internalType": "address",
+          "name": "owner",
+          "type": "address"
+        },
+        {
+          "internalType": "address payable",
+          "name": "beneficiary",
+          "type": "address"
+        },
+        {
+          "internalType": "address",
+          "name": "authorizer",
+          "type": "address"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "uint96",
+          "name": "amount",
+          "type": "uint96"
+        },
+        {
+          "internalType": "uint256",
+          "name": "rewardMultiplier",
+          "type": "uint256"
+        },
+        {
+          "internalType": "address",
+          "name": "notifier",
+          "type": "address"
+        },
+        {
+          "internalType": "address[]",
+          "name": "_stakingProviders",
+          "type": "address[]"
+        }
+      ],
+      "name": "seize",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "uint256",
+          "name": "ceiling",
+          "type": "uint256"
+        }
+      ],
+      "name": "setAuthorizationCeiling",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "uint96",
+          "name": "amount",
+          "type": "uint96"
+        }
+      ],
+      "name": "setMinimumStakeAmount",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "uint96",
+          "name": "reward",
+          "type": "uint96"
+        }
+      ],
+      "name": "setNotificationReward",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "application",
+          "type": "address"
+        },
+        {
+          "internalType": "address",
+          "name": "panicButton",
+          "type": "address"
+        }
+      ],
+      "name": "setPanicButton",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "uint96",
+          "name": "penalty",
+          "type": "uint96"
+        },
+        {
+          "internalType": "uint256",
+          "name": "rewardMultiplier",
+          "type": "uint256"
+        }
+      ],
+      "name": "setStakeDiscrepancyPenalty",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "uint96",
+          "name": "amount",
+          "type": "uint96"
+        },
+        {
+          "internalType": "address[]",
+          "name": "_stakingProviders",
+          "type": "address[]"
+        }
+      ],
+      "name": "slash",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "uint256",
+          "name": "",
+          "type": "uint256"
+        }
+      ],
+      "name": "slashingQueue",
+      "outputs": [
+        {
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        },
+        {
+          "internalType": "uint96",
+          "name": "amount",
+          "type": "uint96"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "slashingQueueIndex",
+      "outputs": [
+        {
+          "internalType": "uint256",
+          "name": "",
+          "type": "uint256"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        },
+        {
+          "internalType": "address payable",
+          "name": "beneficiary",
+          "type": "address"
+        },
+        {
+          "internalType": "address",
+          "name": "authorizer",
+          "type": "address"
+        },
+        {
+          "internalType": "uint96",
+          "name": "amount",
+          "type": "uint96"
+        }
+      ],
+      "name": "stake",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "stakeDiscrepancyPenalty",
+      "outputs": [
+        {
+          "internalType": "uint96",
+          "name": "",
+          "type": "uint96"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "stakeDiscrepancyRewardMultiplier",
+      "outputs": [
+        {
+          "internalType": "uint256",
+          "name": "",
+          "type": "uint256"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        }
+      ],
+      "name": "stakeKeep",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        },
+        {
+          "internalType": "address payable",
+          "name": "beneficiary",
+          "type": "address"
+        },
+        {
+          "internalType": "address",
+          "name": "authorizer",
+          "type": "address"
+        }
+      ],
+      "name": "stakeNu",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        }
+      ],
+      "name": "stakedNu",
+      "outputs": [
+        {
+          "internalType": "uint256",
+          "name": "nuAmount",
+          "type": "uint256"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        }
+      ],
+      "name": "stakes",
+      "outputs": [
+        {
+          "internalType": "uint96",
+          "name": "tStake",
+          "type": "uint96"
+        },
+        {
+          "internalType": "uint96",
+          "name": "keepInTStake",
+          "type": "uint96"
+        },
+        {
+          "internalType": "uint96",
+          "name": "nuInTStake",
+          "type": "uint96"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        },
+        {
+          "internalType": "uint96",
+          "name": "amount",
+          "type": "uint96"
+        }
+      ],
+      "name": "topUp",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        }
+      ],
+      "name": "topUpKeep",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        }
+      ],
+      "name": "topUpNu",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "newGuvnor",
+          "type": "address"
+        }
+      ],
+      "name": "transferGovernance",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        }
+      ],
+      "name": "unstakeAll",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        }
+      ],
+      "name": "unstakeKeep",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        },
+        {
+          "internalType": "uint96",
+          "name": "amount",
+          "type": "uint96"
+        }
+      ],
+      "name": "unstakeNu",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        },
+        {
+          "internalType": "uint96",
+          "name": "amount",
+          "type": "uint96"
+        }
+      ],
+      "name": "unstakeT",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "recipient",
+          "type": "address"
+        },
+        {
+          "internalType": "uint96",
+          "name": "amount",
+          "type": "uint96"
+        }
+      ],
+      "name": "withdrawNotificationReward",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    }
+  ]
+}
diff --git a/src/threshold-ts/staking/index.ts b/src/threshold-ts/staking/index.ts
index 7988ccbd1..7f8c50487 100644
--- a/src/threshold-ts/staking/index.ts
+++ b/src/threshold-ts/staking/index.ts
@@ -1,12 +1,9 @@
-import TokenStaking from "@threshold-network/solidity-contracts/artifacts/TokenStaking.json"
-import KeepTokenStaking from "@keep-network/keep-core/artifacts/TokenStaking.json"
 import { BigNumber, BigNumberish, Contract, ContractTransaction } from "ethers"
 import { ContractCall, IMulticall } from "../multicall"
 import { EthereumConfig } from "../types"
 import {
   getArtifact,
   getContract,
-  getContractAddressFromTruffleArtifact,
   getContractPastEvents,
   isAddress,
   isSameETHAddress,
@@ -132,27 +129,39 @@ export class Staking implements IStaking {
     multicall: IMulticall,
     vendingMachines: IVendingMachines
   ) {
-    this.STAKING_CONTRACT_DEPLOYMENT_BLOCK = config.chainId === 1 ? 14113768 : 0
+    this.STAKING_CONTRACT_DEPLOYMENT_BLOCK =
+      config.chainId === 1 ? 14113768 : 4320502
+
+    const stakingArtifact = getArtifact(
+      "TokenStaking",
+      config.chainId,
+      config.shouldUseTestnetDevelopmentContracts
+    )
     this._staking = getContract(
-      TokenStaking.address,
-      TokenStaking.abi,
+      stakingArtifact.address,
+      stakingArtifact.abi,
       config.providerOrSigner,
       config.account
     )
+    const legacyKeepStakingArtifact = getArtifact(
+      "LegacyKeepStaking",
+      config.chainId,
+      config.shouldUseTestnetDevelopmentContracts
+    )
     this._legacyKeepStaking = getContract(
-      getContractAddressFromTruffleArtifact(KeepTokenStaking),
-      KeepTokenStaking.abi,
+      legacyKeepStakingArtifact.address,
+      legacyKeepStakingArtifact.abi,
       config.providerOrSigner,
       config.account
     )
-    const NuCypherStakingEscrowArtifact = getArtifact(
+    const nuCypherStakingEscrowArtifact = getArtifact(
       "NuCypherStakingEscrow",
       config.chainId,
       config.shouldUseTestnetDevelopmentContracts
     )
     this._legacyNuStaking = getContract(
-      NuCypherStakingEscrowArtifact.address,
-      NuCypherStakingEscrowArtifact.abi,
+      nuCypherStakingEscrowArtifact.address,
+      nuCypherStakingEscrowArtifact.abi,
       config.providerOrSigner,
       config.account
     )
diff --git a/src/threshold-ts/staking/mainnet-artifacts/LegacyKeepStaking.json b/src/threshold-ts/staking/mainnet-artifacts/LegacyKeepStaking.json
new file mode 100644
index 000000000..82ffbbe24
--- /dev/null
+++ b/src/threshold-ts/staking/mainnet-artifacts/LegacyKeepStaking.json
@@ -0,0 +1,915 @@
+{
+  "address": "0x1293a54e160D1cd7075487898d65266081A15458",
+  "abi": [
+    {
+      "inputs": [
+        {
+          "internalType": "contract ERC20Burnable",
+          "name": "_token",
+          "type": "address"
+        },
+        {
+          "internalType": "contract TokenGrant",
+          "name": "_tokenGrant",
+          "type": "address"
+        },
+        {
+          "internalType": "contract TokenStakingEscrow",
+          "name": "_escrow",
+          "type": "address"
+        },
+        {
+          "internalType": "contract KeepRegistry",
+          "name": "_registry",
+          "type": "address"
+        },
+        {
+          "internalType": "uint256",
+          "name": "_initializationPeriod",
+          "type": "uint256"
+        }
+      ],
+      "payable": false,
+      "stateMutability": "nonpayable",
+      "type": "constructor"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "operator",
+          "type": "address"
+        },
+        {
+          "indexed": false,
+          "internalType": "address",
+          "name": "lockCreator",
+          "type": "address"
+        }
+      ],
+      "name": "ExpiredLockReleased",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "operator",
+          "type": "address"
+        },
+        {
+          "indexed": false,
+          "internalType": "address",
+          "name": "lockCreator",
+          "type": "address"
+        }
+      ],
+      "name": "LockReleased",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "operator",
+          "type": "address"
+        },
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "beneficiary",
+          "type": "address"
+        },
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "authorizer",
+          "type": "address"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "value",
+          "type": "uint256"
+        }
+      ],
+      "name": "OperatorStaked",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": false,
+          "internalType": "address",
+          "name": "operator",
+          "type": "address"
+        }
+      ],
+      "name": "RecoveredStake",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "owner",
+          "type": "address"
+        },
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "operator",
+          "type": "address"
+        }
+      ],
+      "name": "StakeDelegated",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "operator",
+          "type": "address"
+        },
+        {
+          "indexed": false,
+          "internalType": "address",
+          "name": "lockCreator",
+          "type": "address"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "until",
+          "type": "uint256"
+        }
+      ],
+      "name": "StakeLocked",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "operator",
+          "type": "address"
+        },
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "newOwner",
+          "type": "address"
+        }
+      ],
+      "name": "StakeOwnershipTransferred",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "operator",
+          "type": "address"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "amount",
+          "type": "uint256"
+        }
+      ],
+      "name": "TokensSeized",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "operator",
+          "type": "address"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "amount",
+          "type": "uint256"
+        }
+      ],
+      "name": "TokensSlashed",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "operator",
+          "type": "address"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "newAmount",
+          "type": "uint256"
+        }
+      ],
+      "name": "TopUpCompleted",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "operator",
+          "type": "address"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "topUp",
+          "type": "uint256"
+        }
+      ],
+      "name": "TopUpInitiated",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "operator",
+          "type": "address"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "undelegatedAt",
+          "type": "uint256"
+        }
+      ],
+      "name": "Undelegated",
+      "type": "event"
+    },
+    {
+      "constant": true,
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "_operator",
+          "type": "address"
+        },
+        {
+          "internalType": "address",
+          "name": "_operatorContract",
+          "type": "address"
+        }
+      ],
+      "name": "activeStake",
+      "outputs": [
+        {
+          "internalType": "uint256",
+          "name": "balance",
+          "type": "uint256"
+        }
+      ],
+      "payable": false,
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "constant": false,
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "_operator",
+          "type": "address"
+        },
+        {
+          "internalType": "address",
+          "name": "_operatorContract",
+          "type": "address"
+        }
+      ],
+      "name": "authorizeOperatorContract",
+      "outputs": [],
+      "payable": false,
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "constant": true,
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "_operator",
+          "type": "address"
+        }
+      ],
+      "name": "authorizerOf",
+      "outputs": [
+        {
+          "internalType": "address",
+          "name": "",
+          "type": "address"
+        }
+      ],
+      "payable": false,
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "constant": true,
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "_address",
+          "type": "address"
+        }
+      ],
+      "name": "balanceOf",
+      "outputs": [
+        {
+          "internalType": "uint256",
+          "name": "balance",
+          "type": "uint256"
+        }
+      ],
+      "payable": false,
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "constant": true,
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "_operator",
+          "type": "address"
+        }
+      ],
+      "name": "beneficiaryOf",
+      "outputs": [
+        {
+          "internalType": "address payable",
+          "name": "",
+          "type": "address"
+        }
+      ],
+      "payable": false,
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "constant": false,
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "_operator",
+          "type": "address"
+        }
+      ],
+      "name": "cancelStake",
+      "outputs": [],
+      "payable": false,
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "constant": false,
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "delegatedAuthoritySource",
+          "type": "address"
+        }
+      ],
+      "name": "claimDelegatedAuthority",
+      "outputs": [],
+      "payable": false,
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "constant": false,
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "_operator",
+          "type": "address"
+        }
+      ],
+      "name": "commitTopUp",
+      "outputs": [],
+      "payable": false,
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "constant": true,
+      "inputs": [],
+      "name": "deployedAt",
+      "outputs": [
+        {
+          "internalType": "uint256",
+          "name": "",
+          "type": "uint256"
+        }
+      ],
+      "payable": false,
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "constant": true,
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "_operator",
+          "type": "address"
+        },
+        {
+          "internalType": "address",
+          "name": "_operatorContract",
+          "type": "address"
+        }
+      ],
+      "name": "eligibleStake",
+      "outputs": [
+        {
+          "internalType": "uint256",
+          "name": "balance",
+          "type": "uint256"
+        }
+      ],
+      "payable": false,
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "constant": true,
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "operatorContract",
+          "type": "address"
+        }
+      ],
+      "name": "getAuthoritySource",
+      "outputs": [
+        {
+          "internalType": "address",
+          "name": "",
+          "type": "address"
+        }
+      ],
+      "payable": false,
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "constant": true,
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "_operator",
+          "type": "address"
+        }
+      ],
+      "name": "getDelegationInfo",
+      "outputs": [
+        {
+          "internalType": "uint256",
+          "name": "amount",
+          "type": "uint256"
+        },
+        {
+          "internalType": "uint256",
+          "name": "createdAt",
+          "type": "uint256"
+        },
+        {
+          "internalType": "uint256",
+          "name": "undelegatedAt",
+          "type": "uint256"
+        }
+      ],
+      "payable": false,
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "constant": true,
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "operator",
+          "type": "address"
+        }
+      ],
+      "name": "getLocks",
+      "outputs": [
+        {
+          "internalType": "address[]",
+          "name": "creators",
+          "type": "address[]"
+        },
+        {
+          "internalType": "uint256[]",
+          "name": "expirations",
+          "type": "uint256[]"
+        }
+      ],
+      "payable": false,
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "constant": true,
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "staker",
+          "type": "address"
+        },
+        {
+          "internalType": "address",
+          "name": "operatorContract",
+          "type": "address"
+        }
+      ],
+      "name": "hasMinimumStake",
+      "outputs": [
+        {
+          "internalType": "bool",
+          "name": "",
+          "type": "bool"
+        }
+      ],
+      "payable": false,
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "constant": true,
+      "inputs": [],
+      "name": "initializationPeriod",
+      "outputs": [
+        {
+          "internalType": "uint256",
+          "name": "",
+          "type": "uint256"
+        }
+      ],
+      "payable": false,
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "constant": true,
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "_operatorContract",
+          "type": "address"
+        }
+      ],
+      "name": "isApprovedOperatorContract",
+      "outputs": [
+        {
+          "internalType": "bool",
+          "name": "",
+          "type": "bool"
+        }
+      ],
+      "payable": false,
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "constant": true,
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "_operator",
+          "type": "address"
+        },
+        {
+          "internalType": "address",
+          "name": "_operatorContract",
+          "type": "address"
+        }
+      ],
+      "name": "isAuthorizedForOperator",
+      "outputs": [
+        {
+          "internalType": "bool",
+          "name": "",
+          "type": "bool"
+        }
+      ],
+      "payable": false,
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "constant": true,
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "operator",
+          "type": "address"
+        }
+      ],
+      "name": "isStakeLocked",
+      "outputs": [
+        {
+          "internalType": "bool",
+          "name": "",
+          "type": "bool"
+        }
+      ],
+      "payable": false,
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "constant": false,
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "operator",
+          "type": "address"
+        },
+        {
+          "internalType": "uint256",
+          "name": "duration",
+          "type": "uint256"
+        }
+      ],
+      "name": "lockStake",
+      "outputs": [],
+      "payable": false,
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "constant": true,
+      "inputs": [],
+      "name": "minimumStake",
+      "outputs": [
+        {
+          "internalType": "uint256",
+          "name": "",
+          "type": "uint256"
+        }
+      ],
+      "payable": false,
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "constant": true,
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "_operator",
+          "type": "address"
+        }
+      ],
+      "name": "ownerOf",
+      "outputs": [
+        {
+          "internalType": "address",
+          "name": "",
+          "type": "address"
+        }
+      ],
+      "payable": false,
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "constant": false,
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "_from",
+          "type": "address"
+        },
+        {
+          "internalType": "uint256",
+          "name": "_value",
+          "type": "uint256"
+        },
+        {
+          "internalType": "address",
+          "name": "_token",
+          "type": "address"
+        },
+        {
+          "internalType": "bytes",
+          "name": "_extraData",
+          "type": "bytes"
+        }
+      ],
+      "name": "receiveApproval",
+      "outputs": [],
+      "payable": false,
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "constant": false,
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "_operator",
+          "type": "address"
+        }
+      ],
+      "name": "recoverStake",
+      "outputs": [],
+      "payable": false,
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "constant": false,
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "operator",
+          "type": "address"
+        },
+        {
+          "internalType": "address",
+          "name": "operatorContract",
+          "type": "address"
+        }
+      ],
+      "name": "releaseExpiredLock",
+      "outputs": [],
+      "payable": false,
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "constant": false,
+      "inputs": [
+        {
+          "internalType": "uint256",
+          "name": "amountToSeize",
+          "type": "uint256"
+        },
+        {
+          "internalType": "uint256",
+          "name": "rewardMultiplier",
+          "type": "uint256"
+        },
+        {
+          "internalType": "address",
+          "name": "tattletale",
+          "type": "address"
+        },
+        {
+          "internalType": "address[]",
+          "name": "misbehavedOperators",
+          "type": "address[]"
+        }
+      ],
+      "name": "seize",
+      "outputs": [],
+      "payable": false,
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "constant": false,
+      "inputs": [
+        {
+          "internalType": "uint256",
+          "name": "amountToSlash",
+          "type": "uint256"
+        },
+        {
+          "internalType": "address[]",
+          "name": "misbehavedOperators",
+          "type": "address[]"
+        }
+      ],
+      "name": "slash",
+      "outputs": [],
+      "payable": false,
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "constant": false,
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "operator",
+          "type": "address"
+        },
+        {
+          "internalType": "address",
+          "name": "newOwner",
+          "type": "address"
+        }
+      ],
+      "name": "transferStakeOwnership",
+      "outputs": [],
+      "payable": false,
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "constant": false,
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "_operator",
+          "type": "address"
+        }
+      ],
+      "name": "undelegate",
+      "outputs": [],
+      "payable": false,
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "constant": false,
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "_operator",
+          "type": "address"
+        },
+        {
+          "internalType": "uint256",
+          "name": "_undelegationTimestamp",
+          "type": "uint256"
+        }
+      ],
+      "name": "undelegateAt",
+      "outputs": [],
+      "payable": false,
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "constant": true,
+      "inputs": [],
+      "name": "undelegationPeriod",
+      "outputs": [
+        {
+          "internalType": "uint256",
+          "name": "",
+          "type": "uint256"
+        }
+      ],
+      "payable": false,
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "constant": false,
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "operator",
+          "type": "address"
+        }
+      ],
+      "name": "unlockStake",
+      "outputs": [],
+      "payable": false,
+      "stateMutability": "nonpayable",
+      "type": "function"
+    }
+  ]
+}
diff --git a/src/threshold-ts/staking/mainnet-artifacts/TokenStaking.json b/src/threshold-ts/staking/mainnet-artifacts/TokenStaking.json
new file mode 100644
index 000000000..43e3664c3
--- /dev/null
+++ b/src/threshold-ts/staking/mainnet-artifacts/TokenStaking.json
@@ -0,0 +1,1591 @@
+{
+  "address": "0x01B67b1194C75264d06F808A921228a95C765dd7",
+  "abi": [
+    {
+      "inputs": [
+        {
+          "internalType": "contract T",
+          "name": "_token",
+          "type": "address"
+        },
+        {
+          "internalType": "contract IKeepTokenStaking",
+          "name": "_keepStakingContract",
+          "type": "address"
+        },
+        {
+          "internalType": "contract INuCypherStakingEscrow",
+          "name": "_nucypherStakingContract",
+          "type": "address"
+        },
+        {
+          "internalType": "contract VendingMachine",
+          "name": "_keepVendingMachine",
+          "type": "address"
+        },
+        {
+          "internalType": "contract VendingMachine",
+          "name": "_nucypherVendingMachine",
+          "type": "address"
+        },
+        {
+          "internalType": "contract KeepStake",
+          "name": "_keepStake",
+          "type": "address"
+        }
+      ],
+      "stateMutability": "nonpayable",
+      "type": "constructor"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "application",
+          "type": "address"
+        },
+        {
+          "indexed": true,
+          "internalType": "enum TokenStaking.ApplicationStatus",
+          "name": "newStatus",
+          "type": "uint8"
+        }
+      ],
+      "name": "ApplicationStatusChanged",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "ceiling",
+          "type": "uint256"
+        }
+      ],
+      "name": "AuthorizationCeilingSet",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        },
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "application",
+          "type": "address"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint96",
+          "name": "fromAmount",
+          "type": "uint96"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint96",
+          "name": "toAmount",
+          "type": "uint96"
+        }
+      ],
+      "name": "AuthorizationDecreaseApproved",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        },
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "application",
+          "type": "address"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint96",
+          "name": "fromAmount",
+          "type": "uint96"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint96",
+          "name": "toAmount",
+          "type": "uint96"
+        }
+      ],
+      "name": "AuthorizationDecreaseRequested",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        },
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "application",
+          "type": "address"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint96",
+          "name": "fromAmount",
+          "type": "uint96"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint96",
+          "name": "toAmount",
+          "type": "uint96"
+        }
+      ],
+      "name": "AuthorizationIncreased",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        },
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "application",
+          "type": "address"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint96",
+          "name": "fromAmount",
+          "type": "uint96"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint96",
+          "name": "toAmount",
+          "type": "uint96"
+        },
+        {
+          "indexed": true,
+          "internalType": "bool",
+          "name": "successfulCall",
+          "type": "bool"
+        }
+      ],
+      "name": "AuthorizationInvoluntaryDecreased",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "delegator",
+          "type": "address"
+        },
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "fromDelegate",
+          "type": "address"
+        },
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "toDelegate",
+          "type": "address"
+        }
+      ],
+      "name": "DelegateChanged",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "delegate",
+          "type": "address"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "previousBalance",
+          "type": "uint256"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "newBalance",
+          "type": "uint256"
+        }
+      ],
+      "name": "DelegateVotesChanged",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": false,
+          "internalType": "address",
+          "name": "oldGovernance",
+          "type": "address"
+        },
+        {
+          "indexed": false,
+          "internalType": "address",
+          "name": "newGovernance",
+          "type": "address"
+        }
+      ],
+      "name": "GovernanceTransferred",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": false,
+          "internalType": "uint96",
+          "name": "amount",
+          "type": "uint96"
+        }
+      ],
+      "name": "MinimumStakeAmountSet",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": false,
+          "internalType": "uint96",
+          "name": "reward",
+          "type": "uint96"
+        }
+      ],
+      "name": "NotificationRewardPushed",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": false,
+          "internalType": "uint96",
+          "name": "reward",
+          "type": "uint96"
+        }
+      ],
+      "name": "NotificationRewardSet",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": false,
+          "internalType": "address",
+          "name": "recipient",
+          "type": "address"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint96",
+          "name": "amount",
+          "type": "uint96"
+        }
+      ],
+      "name": "NotificationRewardWithdrawn",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "notifier",
+          "type": "address"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "amount",
+          "type": "uint256"
+        }
+      ],
+      "name": "NotifierRewarded",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        },
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "oldOwner",
+          "type": "address"
+        },
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "newOwner",
+          "type": "address"
+        }
+      ],
+      "name": "OwnerRefreshed",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "application",
+          "type": "address"
+        },
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "panicButton",
+          "type": "address"
+        }
+      ],
+      "name": "PanicButtonSet",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "caller",
+          "type": "address"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "count",
+          "type": "uint256"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "tAmount",
+          "type": "uint256"
+        }
+      ],
+      "name": "SlashingProcessed",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": false,
+          "internalType": "uint96",
+          "name": "penalty",
+          "type": "uint96"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "rewardMultiplier",
+          "type": "uint256"
+        }
+      ],
+      "name": "StakeDiscrepancyPenaltySet",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "enum IStaking.StakeType",
+          "name": "stakeType",
+          "type": "uint8"
+        },
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "owner",
+          "type": "address"
+        },
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        },
+        {
+          "indexed": false,
+          "internalType": "address",
+          "name": "beneficiary",
+          "type": "address"
+        },
+        {
+          "indexed": false,
+          "internalType": "address",
+          "name": "authorizer",
+          "type": "address"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint96",
+          "name": "amount",
+          "type": "uint96"
+        }
+      ],
+      "name": "Staked",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint96",
+          "name": "amount",
+          "type": "uint96"
+        },
+        {
+          "indexed": true,
+          "internalType": "bool",
+          "name": "discrepancy",
+          "type": "bool"
+        }
+      ],
+      "name": "TokensSeized",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint96",
+          "name": "amount",
+          "type": "uint96"
+        }
+      ],
+      "name": "ToppedUp",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint96",
+          "name": "amount",
+          "type": "uint96"
+        }
+      ],
+      "name": "Unstaked",
+      "type": "event"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "",
+          "type": "address"
+        }
+      ],
+      "name": "applicationInfo",
+      "outputs": [
+        {
+          "internalType": "enum TokenStaking.ApplicationStatus",
+          "name": "status",
+          "type": "uint8"
+        },
+        {
+          "internalType": "address",
+          "name": "panicButton",
+          "type": "address"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "uint256",
+          "name": "",
+          "type": "uint256"
+        }
+      ],
+      "name": "applications",
+      "outputs": [
+        {
+          "internalType": "address",
+          "name": "",
+          "type": "address"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "application",
+          "type": "address"
+        }
+      ],
+      "name": "approveApplication",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        }
+      ],
+      "name": "approveAuthorizationDecrease",
+      "outputs": [
+        {
+          "internalType": "uint96",
+          "name": "",
+          "type": "uint96"
+        }
+      ],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "authorizationCeiling",
+      "outputs": [
+        {
+          "internalType": "uint256",
+          "name": "",
+          "type": "uint256"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        },
+        {
+          "internalType": "address",
+          "name": "application",
+          "type": "address"
+        }
+      ],
+      "name": "authorizedStake",
+      "outputs": [
+        {
+          "internalType": "uint96",
+          "name": "",
+          "type": "uint96"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "account",
+          "type": "address"
+        },
+        {
+          "internalType": "uint32",
+          "name": "pos",
+          "type": "uint32"
+        }
+      ],
+      "name": "checkpoints",
+      "outputs": [
+        {
+          "components": [
+            {
+              "internalType": "uint32",
+              "name": "fromBlock",
+              "type": "uint32"
+            },
+            {
+              "internalType": "uint96",
+              "name": "votes",
+              "type": "uint96"
+            }
+          ],
+          "internalType": "struct Checkpoints.Checkpoint",
+          "name": "checkpoint",
+          "type": "tuple"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        },
+        {
+          "internalType": "address",
+          "name": "delegatee",
+          "type": "address"
+        }
+      ],
+      "name": "delegateVoting",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "account",
+          "type": "address"
+        }
+      ],
+      "name": "delegates",
+      "outputs": [
+        {
+          "internalType": "address",
+          "name": "",
+          "type": "address"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "application",
+          "type": "address"
+        }
+      ],
+      "name": "disableApplication",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        },
+        {
+          "internalType": "address",
+          "name": "application",
+          "type": "address"
+        }
+      ],
+      "name": "forceDecreaseAuthorization",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "getApplicationsLength",
+      "outputs": [
+        {
+          "internalType": "uint256",
+          "name": "",
+          "type": "uint256"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        },
+        {
+          "internalType": "address",
+          "name": "application",
+          "type": "address"
+        }
+      ],
+      "name": "getAvailableToAuthorize",
+      "outputs": [
+        {
+          "internalType": "uint96",
+          "name": "availableTValue",
+          "type": "uint96"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        },
+        {
+          "internalType": "enum IStaking.StakeType",
+          "name": "stakeTypes",
+          "type": "uint8"
+        }
+      ],
+      "name": "getMinStaked",
+      "outputs": [
+        {
+          "internalType": "uint96",
+          "name": "",
+          "type": "uint96"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "uint256",
+          "name": "blockNumber",
+          "type": "uint256"
+        }
+      ],
+      "name": "getPastTotalSupply",
+      "outputs": [
+        {
+          "internalType": "uint96",
+          "name": "",
+          "type": "uint96"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "account",
+          "type": "address"
+        },
+        {
+          "internalType": "uint256",
+          "name": "blockNumber",
+          "type": "uint256"
+        }
+      ],
+      "name": "getPastVotes",
+      "outputs": [
+        {
+          "internalType": "uint96",
+          "name": "",
+          "type": "uint96"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "getSlashingQueueLength",
+      "outputs": [
+        {
+          "internalType": "uint256",
+          "name": "",
+          "type": "uint256"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        }
+      ],
+      "name": "getStartStakingTimestamp",
+      "outputs": [
+        {
+          "internalType": "uint256",
+          "name": "",
+          "type": "uint256"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "account",
+          "type": "address"
+        }
+      ],
+      "name": "getVotes",
+      "outputs": [
+        {
+          "internalType": "uint96",
+          "name": "",
+          "type": "uint96"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "governance",
+      "outputs": [
+        {
+          "internalType": "address",
+          "name": "",
+          "type": "address"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        },
+        {
+          "internalType": "address",
+          "name": "application",
+          "type": "address"
+        },
+        {
+          "internalType": "uint96",
+          "name": "amount",
+          "type": "uint96"
+        }
+      ],
+      "name": "increaseAuthorization",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "initialize",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "minTStakeAmount",
+      "outputs": [
+        {
+          "internalType": "uint96",
+          "name": "",
+          "type": "uint96"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "notificationReward",
+      "outputs": [
+        {
+          "internalType": "uint256",
+          "name": "",
+          "type": "uint256"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "notifiersTreasury",
+      "outputs": [
+        {
+          "internalType": "uint256",
+          "name": "",
+          "type": "uint256"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        }
+      ],
+      "name": "notifyKeepStakeDiscrepancy",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        }
+      ],
+      "name": "notifyNuStakeDiscrepancy",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "account",
+          "type": "address"
+        }
+      ],
+      "name": "numCheckpoints",
+      "outputs": [
+        {
+          "internalType": "uint32",
+          "name": "",
+          "type": "uint32"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "application",
+          "type": "address"
+        }
+      ],
+      "name": "pauseApplication",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "uint256",
+          "name": "count",
+          "type": "uint256"
+        }
+      ],
+      "name": "processSlashing",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "uint96",
+          "name": "reward",
+          "type": "uint96"
+        }
+      ],
+      "name": "pushNotificationReward",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        }
+      ],
+      "name": "refreshKeepStakeOwner",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        },
+        {
+          "internalType": "address",
+          "name": "application",
+          "type": "address"
+        },
+        {
+          "internalType": "uint96",
+          "name": "amount",
+          "type": "uint96"
+        }
+      ],
+      "name": "requestAuthorizationDecrease",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        }
+      ],
+      "name": "requestAuthorizationDecrease",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        }
+      ],
+      "name": "rolesOf",
+      "outputs": [
+        {
+          "internalType": "address",
+          "name": "owner",
+          "type": "address"
+        },
+        {
+          "internalType": "address payable",
+          "name": "beneficiary",
+          "type": "address"
+        },
+        {
+          "internalType": "address",
+          "name": "authorizer",
+          "type": "address"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "uint96",
+          "name": "amount",
+          "type": "uint96"
+        },
+        {
+          "internalType": "uint256",
+          "name": "rewardMultiplier",
+          "type": "uint256"
+        },
+        {
+          "internalType": "address",
+          "name": "notifier",
+          "type": "address"
+        },
+        {
+          "internalType": "address[]",
+          "name": "_stakingProviders",
+          "type": "address[]"
+        }
+      ],
+      "name": "seize",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "uint256",
+          "name": "ceiling",
+          "type": "uint256"
+        }
+      ],
+      "name": "setAuthorizationCeiling",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "uint96",
+          "name": "amount",
+          "type": "uint96"
+        }
+      ],
+      "name": "setMinimumStakeAmount",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "uint96",
+          "name": "reward",
+          "type": "uint96"
+        }
+      ],
+      "name": "setNotificationReward",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "application",
+          "type": "address"
+        },
+        {
+          "internalType": "address",
+          "name": "panicButton",
+          "type": "address"
+        }
+      ],
+      "name": "setPanicButton",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "uint96",
+          "name": "penalty",
+          "type": "uint96"
+        },
+        {
+          "internalType": "uint256",
+          "name": "rewardMultiplier",
+          "type": "uint256"
+        }
+      ],
+      "name": "setStakeDiscrepancyPenalty",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "uint96",
+          "name": "amount",
+          "type": "uint96"
+        },
+        {
+          "internalType": "address[]",
+          "name": "_stakingProviders",
+          "type": "address[]"
+        }
+      ],
+      "name": "slash",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "uint256",
+          "name": "",
+          "type": "uint256"
+        }
+      ],
+      "name": "slashingQueue",
+      "outputs": [
+        {
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        },
+        {
+          "internalType": "uint96",
+          "name": "amount",
+          "type": "uint96"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "slashingQueueIndex",
+      "outputs": [
+        {
+          "internalType": "uint256",
+          "name": "",
+          "type": "uint256"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        },
+        {
+          "internalType": "address payable",
+          "name": "beneficiary",
+          "type": "address"
+        },
+        {
+          "internalType": "address",
+          "name": "authorizer",
+          "type": "address"
+        },
+        {
+          "internalType": "uint96",
+          "name": "amount",
+          "type": "uint96"
+        }
+      ],
+      "name": "stake",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "stakeDiscrepancyPenalty",
+      "outputs": [
+        {
+          "internalType": "uint96",
+          "name": "",
+          "type": "uint96"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "stakeDiscrepancyRewardMultiplier",
+      "outputs": [
+        {
+          "internalType": "uint256",
+          "name": "",
+          "type": "uint256"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        }
+      ],
+      "name": "stakeKeep",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        },
+        {
+          "internalType": "address payable",
+          "name": "beneficiary",
+          "type": "address"
+        },
+        {
+          "internalType": "address",
+          "name": "authorizer",
+          "type": "address"
+        }
+      ],
+      "name": "stakeNu",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        }
+      ],
+      "name": "stakedNu",
+      "outputs": [
+        {
+          "internalType": "uint256",
+          "name": "nuAmount",
+          "type": "uint256"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        }
+      ],
+      "name": "stakes",
+      "outputs": [
+        {
+          "internalType": "uint96",
+          "name": "tStake",
+          "type": "uint96"
+        },
+        {
+          "internalType": "uint96",
+          "name": "keepInTStake",
+          "type": "uint96"
+        },
+        {
+          "internalType": "uint96",
+          "name": "nuInTStake",
+          "type": "uint96"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        },
+        {
+          "internalType": "uint96",
+          "name": "amount",
+          "type": "uint96"
+        }
+      ],
+      "name": "topUp",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        }
+      ],
+      "name": "topUpKeep",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        }
+      ],
+      "name": "topUpNu",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "newGuvnor",
+          "type": "address"
+        }
+      ],
+      "name": "transferGovernance",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        }
+      ],
+      "name": "unstakeAll",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        }
+      ],
+      "name": "unstakeKeep",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        },
+        {
+          "internalType": "uint96",
+          "name": "amount",
+          "type": "uint96"
+        }
+      ],
+      "name": "unstakeNu",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        },
+        {
+          "internalType": "uint96",
+          "name": "amount",
+          "type": "uint96"
+        }
+      ],
+      "name": "unstakeT",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "recipient",
+          "type": "address"
+        },
+        {
+          "internalType": "uint96",
+          "name": "amount",
+          "type": "uint96"
+        }
+      ],
+      "name": "withdrawNotificationReward",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    }
+  ]
+}
diff --git a/src/threshold-ts/staking/sepolia-artifacts/LegacyKeepStaking.json b/src/threshold-ts/staking/sepolia-artifacts/LegacyKeepStaking.json
new file mode 100644
index 000000000..7ed91c483
--- /dev/null
+++ b/src/threshold-ts/staking/sepolia-artifacts/LegacyKeepStaking.json
@@ -0,0 +1,915 @@
+{
+  "address": "0xa07f4E37C2E7089Ea3AFffbe51A6A281833a4D14",
+  "abi": [
+    {
+      "inputs": [
+        {
+          "internalType": "contract ERC20Burnable",
+          "name": "_token",
+          "type": "address"
+        },
+        {
+          "internalType": "contract TokenGrant",
+          "name": "_tokenGrant",
+          "type": "address"
+        },
+        {
+          "internalType": "contract TokenStakingEscrow",
+          "name": "_escrow",
+          "type": "address"
+        },
+        {
+          "internalType": "contract KeepRegistry",
+          "name": "_registry",
+          "type": "address"
+        },
+        {
+          "internalType": "uint256",
+          "name": "_initializationPeriod",
+          "type": "uint256"
+        }
+      ],
+      "payable": false,
+      "stateMutability": "nonpayable",
+      "type": "constructor"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "operator",
+          "type": "address"
+        },
+        {
+          "indexed": false,
+          "internalType": "address",
+          "name": "lockCreator",
+          "type": "address"
+        }
+      ],
+      "name": "ExpiredLockReleased",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "operator",
+          "type": "address"
+        },
+        {
+          "indexed": false,
+          "internalType": "address",
+          "name": "lockCreator",
+          "type": "address"
+        }
+      ],
+      "name": "LockReleased",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "operator",
+          "type": "address"
+        },
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "beneficiary",
+          "type": "address"
+        },
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "authorizer",
+          "type": "address"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "value",
+          "type": "uint256"
+        }
+      ],
+      "name": "OperatorStaked",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": false,
+          "internalType": "address",
+          "name": "operator",
+          "type": "address"
+        }
+      ],
+      "name": "RecoveredStake",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "owner",
+          "type": "address"
+        },
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "operator",
+          "type": "address"
+        }
+      ],
+      "name": "StakeDelegated",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "operator",
+          "type": "address"
+        },
+        {
+          "indexed": false,
+          "internalType": "address",
+          "name": "lockCreator",
+          "type": "address"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "until",
+          "type": "uint256"
+        }
+      ],
+      "name": "StakeLocked",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "operator",
+          "type": "address"
+        },
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "newOwner",
+          "type": "address"
+        }
+      ],
+      "name": "StakeOwnershipTransferred",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "operator",
+          "type": "address"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "amount",
+          "type": "uint256"
+        }
+      ],
+      "name": "TokensSeized",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "operator",
+          "type": "address"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "amount",
+          "type": "uint256"
+        }
+      ],
+      "name": "TokensSlashed",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "operator",
+          "type": "address"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "newAmount",
+          "type": "uint256"
+        }
+      ],
+      "name": "TopUpCompleted",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "operator",
+          "type": "address"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "topUp",
+          "type": "uint256"
+        }
+      ],
+      "name": "TopUpInitiated",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "operator",
+          "type": "address"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "undelegatedAt",
+          "type": "uint256"
+        }
+      ],
+      "name": "Undelegated",
+      "type": "event"
+    },
+    {
+      "constant": true,
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "_operator",
+          "type": "address"
+        },
+        {
+          "internalType": "address",
+          "name": "_operatorContract",
+          "type": "address"
+        }
+      ],
+      "name": "activeStake",
+      "outputs": [
+        {
+          "internalType": "uint256",
+          "name": "balance",
+          "type": "uint256"
+        }
+      ],
+      "payable": false,
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "constant": false,
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "_operator",
+          "type": "address"
+        },
+        {
+          "internalType": "address",
+          "name": "_operatorContract",
+          "type": "address"
+        }
+      ],
+      "name": "authorizeOperatorContract",
+      "outputs": [],
+      "payable": false,
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "constant": true,
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "_operator",
+          "type": "address"
+        }
+      ],
+      "name": "authorizerOf",
+      "outputs": [
+        {
+          "internalType": "address",
+          "name": "",
+          "type": "address"
+        }
+      ],
+      "payable": false,
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "constant": true,
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "_address",
+          "type": "address"
+        }
+      ],
+      "name": "balanceOf",
+      "outputs": [
+        {
+          "internalType": "uint256",
+          "name": "balance",
+          "type": "uint256"
+        }
+      ],
+      "payable": false,
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "constant": true,
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "_operator",
+          "type": "address"
+        }
+      ],
+      "name": "beneficiaryOf",
+      "outputs": [
+        {
+          "internalType": "address payable",
+          "name": "",
+          "type": "address"
+        }
+      ],
+      "payable": false,
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "constant": false,
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "_operator",
+          "type": "address"
+        }
+      ],
+      "name": "cancelStake",
+      "outputs": [],
+      "payable": false,
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "constant": false,
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "delegatedAuthoritySource",
+          "type": "address"
+        }
+      ],
+      "name": "claimDelegatedAuthority",
+      "outputs": [],
+      "payable": false,
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "constant": false,
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "_operator",
+          "type": "address"
+        }
+      ],
+      "name": "commitTopUp",
+      "outputs": [],
+      "payable": false,
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "constant": true,
+      "inputs": [],
+      "name": "deployedAt",
+      "outputs": [
+        {
+          "internalType": "uint256",
+          "name": "",
+          "type": "uint256"
+        }
+      ],
+      "payable": false,
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "constant": true,
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "_operator",
+          "type": "address"
+        },
+        {
+          "internalType": "address",
+          "name": "_operatorContract",
+          "type": "address"
+        }
+      ],
+      "name": "eligibleStake",
+      "outputs": [
+        {
+          "internalType": "uint256",
+          "name": "balance",
+          "type": "uint256"
+        }
+      ],
+      "payable": false,
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "constant": true,
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "operatorContract",
+          "type": "address"
+        }
+      ],
+      "name": "getAuthoritySource",
+      "outputs": [
+        {
+          "internalType": "address",
+          "name": "",
+          "type": "address"
+        }
+      ],
+      "payable": false,
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "constant": true,
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "_operator",
+          "type": "address"
+        }
+      ],
+      "name": "getDelegationInfo",
+      "outputs": [
+        {
+          "internalType": "uint256",
+          "name": "amount",
+          "type": "uint256"
+        },
+        {
+          "internalType": "uint256",
+          "name": "createdAt",
+          "type": "uint256"
+        },
+        {
+          "internalType": "uint256",
+          "name": "undelegatedAt",
+          "type": "uint256"
+        }
+      ],
+      "payable": false,
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "constant": true,
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "operator",
+          "type": "address"
+        }
+      ],
+      "name": "getLocks",
+      "outputs": [
+        {
+          "internalType": "address[]",
+          "name": "creators",
+          "type": "address[]"
+        },
+        {
+          "internalType": "uint256[]",
+          "name": "expirations",
+          "type": "uint256[]"
+        }
+      ],
+      "payable": false,
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "constant": true,
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "staker",
+          "type": "address"
+        },
+        {
+          "internalType": "address",
+          "name": "operatorContract",
+          "type": "address"
+        }
+      ],
+      "name": "hasMinimumStake",
+      "outputs": [
+        {
+          "internalType": "bool",
+          "name": "",
+          "type": "bool"
+        }
+      ],
+      "payable": false,
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "constant": true,
+      "inputs": [],
+      "name": "initializationPeriod",
+      "outputs": [
+        {
+          "internalType": "uint256",
+          "name": "",
+          "type": "uint256"
+        }
+      ],
+      "payable": false,
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "constant": true,
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "_operatorContract",
+          "type": "address"
+        }
+      ],
+      "name": "isApprovedOperatorContract",
+      "outputs": [
+        {
+          "internalType": "bool",
+          "name": "",
+          "type": "bool"
+        }
+      ],
+      "payable": false,
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "constant": true,
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "_operator",
+          "type": "address"
+        },
+        {
+          "internalType": "address",
+          "name": "_operatorContract",
+          "type": "address"
+        }
+      ],
+      "name": "isAuthorizedForOperator",
+      "outputs": [
+        {
+          "internalType": "bool",
+          "name": "",
+          "type": "bool"
+        }
+      ],
+      "payable": false,
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "constant": true,
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "operator",
+          "type": "address"
+        }
+      ],
+      "name": "isStakeLocked",
+      "outputs": [
+        {
+          "internalType": "bool",
+          "name": "",
+          "type": "bool"
+        }
+      ],
+      "payable": false,
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "constant": false,
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "operator",
+          "type": "address"
+        },
+        {
+          "internalType": "uint256",
+          "name": "duration",
+          "type": "uint256"
+        }
+      ],
+      "name": "lockStake",
+      "outputs": [],
+      "payable": false,
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "constant": true,
+      "inputs": [],
+      "name": "minimumStake",
+      "outputs": [
+        {
+          "internalType": "uint256",
+          "name": "",
+          "type": "uint256"
+        }
+      ],
+      "payable": false,
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "constant": true,
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "_operator",
+          "type": "address"
+        }
+      ],
+      "name": "ownerOf",
+      "outputs": [
+        {
+          "internalType": "address",
+          "name": "",
+          "type": "address"
+        }
+      ],
+      "payable": false,
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "constant": false,
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "_from",
+          "type": "address"
+        },
+        {
+          "internalType": "uint256",
+          "name": "_value",
+          "type": "uint256"
+        },
+        {
+          "internalType": "address",
+          "name": "_token",
+          "type": "address"
+        },
+        {
+          "internalType": "bytes",
+          "name": "_extraData",
+          "type": "bytes"
+        }
+      ],
+      "name": "receiveApproval",
+      "outputs": [],
+      "payable": false,
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "constant": false,
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "_operator",
+          "type": "address"
+        }
+      ],
+      "name": "recoverStake",
+      "outputs": [],
+      "payable": false,
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "constant": false,
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "operator",
+          "type": "address"
+        },
+        {
+          "internalType": "address",
+          "name": "operatorContract",
+          "type": "address"
+        }
+      ],
+      "name": "releaseExpiredLock",
+      "outputs": [],
+      "payable": false,
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "constant": false,
+      "inputs": [
+        {
+          "internalType": "uint256",
+          "name": "amountToSeize",
+          "type": "uint256"
+        },
+        {
+          "internalType": "uint256",
+          "name": "rewardMultiplier",
+          "type": "uint256"
+        },
+        {
+          "internalType": "address",
+          "name": "tattletale",
+          "type": "address"
+        },
+        {
+          "internalType": "address[]",
+          "name": "misbehavedOperators",
+          "type": "address[]"
+        }
+      ],
+      "name": "seize",
+      "outputs": [],
+      "payable": false,
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "constant": false,
+      "inputs": [
+        {
+          "internalType": "uint256",
+          "name": "amountToSlash",
+          "type": "uint256"
+        },
+        {
+          "internalType": "address[]",
+          "name": "misbehavedOperators",
+          "type": "address[]"
+        }
+      ],
+      "name": "slash",
+      "outputs": [],
+      "payable": false,
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "constant": false,
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "operator",
+          "type": "address"
+        },
+        {
+          "internalType": "address",
+          "name": "newOwner",
+          "type": "address"
+        }
+      ],
+      "name": "transferStakeOwnership",
+      "outputs": [],
+      "payable": false,
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "constant": false,
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "_operator",
+          "type": "address"
+        }
+      ],
+      "name": "undelegate",
+      "outputs": [],
+      "payable": false,
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "constant": false,
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "_operator",
+          "type": "address"
+        },
+        {
+          "internalType": "uint256",
+          "name": "_undelegationTimestamp",
+          "type": "uint256"
+        }
+      ],
+      "name": "undelegateAt",
+      "outputs": [],
+      "payable": false,
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "constant": true,
+      "inputs": [],
+      "name": "undelegationPeriod",
+      "outputs": [
+        {
+          "internalType": "uint256",
+          "name": "",
+          "type": "uint256"
+        }
+      ],
+      "payable": false,
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "constant": false,
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "operator",
+          "type": "address"
+        }
+      ],
+      "name": "unlockStake",
+      "outputs": [],
+      "payable": false,
+      "stateMutability": "nonpayable",
+      "type": "function"
+    }
+  ]
+}
diff --git a/src/threshold-ts/staking/sepolia-artifacts/TokenStaking.json b/src/threshold-ts/staking/sepolia-artifacts/TokenStaking.json
new file mode 100644
index 000000000..f2b8ef5fa
--- /dev/null
+++ b/src/threshold-ts/staking/sepolia-artifacts/TokenStaking.json
@@ -0,0 +1,1591 @@
+{
+  "address": "0x3d4cb85c0e3c5bd1667B7E30f3E86B3FAB878Ff8",
+  "abi": [
+    {
+      "inputs": [
+        {
+          "internalType": "contract T",
+          "name": "_token",
+          "type": "address"
+        },
+        {
+          "internalType": "contract IKeepTokenStaking",
+          "name": "_keepStakingContract",
+          "type": "address"
+        },
+        {
+          "internalType": "contract INuCypherStakingEscrow",
+          "name": "_nucypherStakingContract",
+          "type": "address"
+        },
+        {
+          "internalType": "contract VendingMachine",
+          "name": "_keepVendingMachine",
+          "type": "address"
+        },
+        {
+          "internalType": "contract VendingMachine",
+          "name": "_nucypherVendingMachine",
+          "type": "address"
+        },
+        {
+          "internalType": "contract KeepStake",
+          "name": "_keepStake",
+          "type": "address"
+        }
+      ],
+      "stateMutability": "nonpayable",
+      "type": "constructor"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "application",
+          "type": "address"
+        },
+        {
+          "indexed": true,
+          "internalType": "enum TokenStaking.ApplicationStatus",
+          "name": "newStatus",
+          "type": "uint8"
+        }
+      ],
+      "name": "ApplicationStatusChanged",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "ceiling",
+          "type": "uint256"
+        }
+      ],
+      "name": "AuthorizationCeilingSet",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        },
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "application",
+          "type": "address"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint96",
+          "name": "fromAmount",
+          "type": "uint96"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint96",
+          "name": "toAmount",
+          "type": "uint96"
+        }
+      ],
+      "name": "AuthorizationDecreaseApproved",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        },
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "application",
+          "type": "address"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint96",
+          "name": "fromAmount",
+          "type": "uint96"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint96",
+          "name": "toAmount",
+          "type": "uint96"
+        }
+      ],
+      "name": "AuthorizationDecreaseRequested",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        },
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "application",
+          "type": "address"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint96",
+          "name": "fromAmount",
+          "type": "uint96"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint96",
+          "name": "toAmount",
+          "type": "uint96"
+        }
+      ],
+      "name": "AuthorizationIncreased",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        },
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "application",
+          "type": "address"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint96",
+          "name": "fromAmount",
+          "type": "uint96"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint96",
+          "name": "toAmount",
+          "type": "uint96"
+        },
+        {
+          "indexed": true,
+          "internalType": "bool",
+          "name": "successfulCall",
+          "type": "bool"
+        }
+      ],
+      "name": "AuthorizationInvoluntaryDecreased",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "delegator",
+          "type": "address"
+        },
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "fromDelegate",
+          "type": "address"
+        },
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "toDelegate",
+          "type": "address"
+        }
+      ],
+      "name": "DelegateChanged",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "delegate",
+          "type": "address"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "previousBalance",
+          "type": "uint256"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "newBalance",
+          "type": "uint256"
+        }
+      ],
+      "name": "DelegateVotesChanged",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": false,
+          "internalType": "address",
+          "name": "oldGovernance",
+          "type": "address"
+        },
+        {
+          "indexed": false,
+          "internalType": "address",
+          "name": "newGovernance",
+          "type": "address"
+        }
+      ],
+      "name": "GovernanceTransferred",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": false,
+          "internalType": "uint96",
+          "name": "amount",
+          "type": "uint96"
+        }
+      ],
+      "name": "MinimumStakeAmountSet",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": false,
+          "internalType": "uint96",
+          "name": "reward",
+          "type": "uint96"
+        }
+      ],
+      "name": "NotificationRewardPushed",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": false,
+          "internalType": "uint96",
+          "name": "reward",
+          "type": "uint96"
+        }
+      ],
+      "name": "NotificationRewardSet",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": false,
+          "internalType": "address",
+          "name": "recipient",
+          "type": "address"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint96",
+          "name": "amount",
+          "type": "uint96"
+        }
+      ],
+      "name": "NotificationRewardWithdrawn",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "notifier",
+          "type": "address"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "amount",
+          "type": "uint256"
+        }
+      ],
+      "name": "NotifierRewarded",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        },
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "oldOwner",
+          "type": "address"
+        },
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "newOwner",
+          "type": "address"
+        }
+      ],
+      "name": "OwnerRefreshed",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "application",
+          "type": "address"
+        },
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "panicButton",
+          "type": "address"
+        }
+      ],
+      "name": "PanicButtonSet",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "caller",
+          "type": "address"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "count",
+          "type": "uint256"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "tAmount",
+          "type": "uint256"
+        }
+      ],
+      "name": "SlashingProcessed",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": false,
+          "internalType": "uint96",
+          "name": "penalty",
+          "type": "uint96"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "rewardMultiplier",
+          "type": "uint256"
+        }
+      ],
+      "name": "StakeDiscrepancyPenaltySet",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "enum IStaking.StakeType",
+          "name": "stakeType",
+          "type": "uint8"
+        },
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "owner",
+          "type": "address"
+        },
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        },
+        {
+          "indexed": false,
+          "internalType": "address",
+          "name": "beneficiary",
+          "type": "address"
+        },
+        {
+          "indexed": false,
+          "internalType": "address",
+          "name": "authorizer",
+          "type": "address"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint96",
+          "name": "amount",
+          "type": "uint96"
+        }
+      ],
+      "name": "Staked",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint96",
+          "name": "amount",
+          "type": "uint96"
+        },
+        {
+          "indexed": true,
+          "internalType": "bool",
+          "name": "discrepancy",
+          "type": "bool"
+        }
+      ],
+      "name": "TokensSeized",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint96",
+          "name": "amount",
+          "type": "uint96"
+        }
+      ],
+      "name": "ToppedUp",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint96",
+          "name": "amount",
+          "type": "uint96"
+        }
+      ],
+      "name": "Unstaked",
+      "type": "event"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "",
+          "type": "address"
+        }
+      ],
+      "name": "applicationInfo",
+      "outputs": [
+        {
+          "internalType": "enum TokenStaking.ApplicationStatus",
+          "name": "status",
+          "type": "uint8"
+        },
+        {
+          "internalType": "address",
+          "name": "panicButton",
+          "type": "address"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "uint256",
+          "name": "",
+          "type": "uint256"
+        }
+      ],
+      "name": "applications",
+      "outputs": [
+        {
+          "internalType": "address",
+          "name": "",
+          "type": "address"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "application",
+          "type": "address"
+        }
+      ],
+      "name": "approveApplication",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        }
+      ],
+      "name": "approveAuthorizationDecrease",
+      "outputs": [
+        {
+          "internalType": "uint96",
+          "name": "",
+          "type": "uint96"
+        }
+      ],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "authorizationCeiling",
+      "outputs": [
+        {
+          "internalType": "uint256",
+          "name": "",
+          "type": "uint256"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        },
+        {
+          "internalType": "address",
+          "name": "application",
+          "type": "address"
+        }
+      ],
+      "name": "authorizedStake",
+      "outputs": [
+        {
+          "internalType": "uint96",
+          "name": "",
+          "type": "uint96"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "account",
+          "type": "address"
+        },
+        {
+          "internalType": "uint32",
+          "name": "pos",
+          "type": "uint32"
+        }
+      ],
+      "name": "checkpoints",
+      "outputs": [
+        {
+          "components": [
+            {
+              "internalType": "uint32",
+              "name": "fromBlock",
+              "type": "uint32"
+            },
+            {
+              "internalType": "uint96",
+              "name": "votes",
+              "type": "uint96"
+            }
+          ],
+          "internalType": "struct Checkpoints.Checkpoint",
+          "name": "checkpoint",
+          "type": "tuple"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        },
+        {
+          "internalType": "address",
+          "name": "delegatee",
+          "type": "address"
+        }
+      ],
+      "name": "delegateVoting",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "account",
+          "type": "address"
+        }
+      ],
+      "name": "delegates",
+      "outputs": [
+        {
+          "internalType": "address",
+          "name": "",
+          "type": "address"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "application",
+          "type": "address"
+        }
+      ],
+      "name": "disableApplication",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        },
+        {
+          "internalType": "address",
+          "name": "application",
+          "type": "address"
+        }
+      ],
+      "name": "forceDecreaseAuthorization",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "getApplicationsLength",
+      "outputs": [
+        {
+          "internalType": "uint256",
+          "name": "",
+          "type": "uint256"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        },
+        {
+          "internalType": "address",
+          "name": "application",
+          "type": "address"
+        }
+      ],
+      "name": "getAvailableToAuthorize",
+      "outputs": [
+        {
+          "internalType": "uint96",
+          "name": "availableTValue",
+          "type": "uint96"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        },
+        {
+          "internalType": "enum IStaking.StakeType",
+          "name": "stakeTypes",
+          "type": "uint8"
+        }
+      ],
+      "name": "getMinStaked",
+      "outputs": [
+        {
+          "internalType": "uint96",
+          "name": "",
+          "type": "uint96"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "uint256",
+          "name": "blockNumber",
+          "type": "uint256"
+        }
+      ],
+      "name": "getPastTotalSupply",
+      "outputs": [
+        {
+          "internalType": "uint96",
+          "name": "",
+          "type": "uint96"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "account",
+          "type": "address"
+        },
+        {
+          "internalType": "uint256",
+          "name": "blockNumber",
+          "type": "uint256"
+        }
+      ],
+      "name": "getPastVotes",
+      "outputs": [
+        {
+          "internalType": "uint96",
+          "name": "",
+          "type": "uint96"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "getSlashingQueueLength",
+      "outputs": [
+        {
+          "internalType": "uint256",
+          "name": "",
+          "type": "uint256"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        }
+      ],
+      "name": "getStartStakingTimestamp",
+      "outputs": [
+        {
+          "internalType": "uint256",
+          "name": "",
+          "type": "uint256"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "account",
+          "type": "address"
+        }
+      ],
+      "name": "getVotes",
+      "outputs": [
+        {
+          "internalType": "uint96",
+          "name": "",
+          "type": "uint96"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "governance",
+      "outputs": [
+        {
+          "internalType": "address",
+          "name": "",
+          "type": "address"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        },
+        {
+          "internalType": "address",
+          "name": "application",
+          "type": "address"
+        },
+        {
+          "internalType": "uint96",
+          "name": "amount",
+          "type": "uint96"
+        }
+      ],
+      "name": "increaseAuthorization",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "initialize",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "minTStakeAmount",
+      "outputs": [
+        {
+          "internalType": "uint96",
+          "name": "",
+          "type": "uint96"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "notificationReward",
+      "outputs": [
+        {
+          "internalType": "uint256",
+          "name": "",
+          "type": "uint256"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "notifiersTreasury",
+      "outputs": [
+        {
+          "internalType": "uint256",
+          "name": "",
+          "type": "uint256"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        }
+      ],
+      "name": "notifyKeepStakeDiscrepancy",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        }
+      ],
+      "name": "notifyNuStakeDiscrepancy",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "account",
+          "type": "address"
+        }
+      ],
+      "name": "numCheckpoints",
+      "outputs": [
+        {
+          "internalType": "uint32",
+          "name": "",
+          "type": "uint32"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "application",
+          "type": "address"
+        }
+      ],
+      "name": "pauseApplication",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "uint256",
+          "name": "count",
+          "type": "uint256"
+        }
+      ],
+      "name": "processSlashing",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "uint96",
+          "name": "reward",
+          "type": "uint96"
+        }
+      ],
+      "name": "pushNotificationReward",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        }
+      ],
+      "name": "refreshKeepStakeOwner",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        },
+        {
+          "internalType": "address",
+          "name": "application",
+          "type": "address"
+        },
+        {
+          "internalType": "uint96",
+          "name": "amount",
+          "type": "uint96"
+        }
+      ],
+      "name": "requestAuthorizationDecrease",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        }
+      ],
+      "name": "requestAuthorizationDecrease",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        }
+      ],
+      "name": "rolesOf",
+      "outputs": [
+        {
+          "internalType": "address",
+          "name": "owner",
+          "type": "address"
+        },
+        {
+          "internalType": "address payable",
+          "name": "beneficiary",
+          "type": "address"
+        },
+        {
+          "internalType": "address",
+          "name": "authorizer",
+          "type": "address"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "uint96",
+          "name": "amount",
+          "type": "uint96"
+        },
+        {
+          "internalType": "uint256",
+          "name": "rewardMultiplier",
+          "type": "uint256"
+        },
+        {
+          "internalType": "address",
+          "name": "notifier",
+          "type": "address"
+        },
+        {
+          "internalType": "address[]",
+          "name": "_stakingProviders",
+          "type": "address[]"
+        }
+      ],
+      "name": "seize",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "uint256",
+          "name": "ceiling",
+          "type": "uint256"
+        }
+      ],
+      "name": "setAuthorizationCeiling",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "uint96",
+          "name": "amount",
+          "type": "uint96"
+        }
+      ],
+      "name": "setMinimumStakeAmount",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "uint96",
+          "name": "reward",
+          "type": "uint96"
+        }
+      ],
+      "name": "setNotificationReward",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "application",
+          "type": "address"
+        },
+        {
+          "internalType": "address",
+          "name": "panicButton",
+          "type": "address"
+        }
+      ],
+      "name": "setPanicButton",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "uint96",
+          "name": "penalty",
+          "type": "uint96"
+        },
+        {
+          "internalType": "uint256",
+          "name": "rewardMultiplier",
+          "type": "uint256"
+        }
+      ],
+      "name": "setStakeDiscrepancyPenalty",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "uint96",
+          "name": "amount",
+          "type": "uint96"
+        },
+        {
+          "internalType": "address[]",
+          "name": "_stakingProviders",
+          "type": "address[]"
+        }
+      ],
+      "name": "slash",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "uint256",
+          "name": "",
+          "type": "uint256"
+        }
+      ],
+      "name": "slashingQueue",
+      "outputs": [
+        {
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        },
+        {
+          "internalType": "uint96",
+          "name": "amount",
+          "type": "uint96"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "slashingQueueIndex",
+      "outputs": [
+        {
+          "internalType": "uint256",
+          "name": "",
+          "type": "uint256"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        },
+        {
+          "internalType": "address payable",
+          "name": "beneficiary",
+          "type": "address"
+        },
+        {
+          "internalType": "address",
+          "name": "authorizer",
+          "type": "address"
+        },
+        {
+          "internalType": "uint96",
+          "name": "amount",
+          "type": "uint96"
+        }
+      ],
+      "name": "stake",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "stakeDiscrepancyPenalty",
+      "outputs": [
+        {
+          "internalType": "uint96",
+          "name": "",
+          "type": "uint96"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "stakeDiscrepancyRewardMultiplier",
+      "outputs": [
+        {
+          "internalType": "uint256",
+          "name": "",
+          "type": "uint256"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        }
+      ],
+      "name": "stakeKeep",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        },
+        {
+          "internalType": "address payable",
+          "name": "beneficiary",
+          "type": "address"
+        },
+        {
+          "internalType": "address",
+          "name": "authorizer",
+          "type": "address"
+        }
+      ],
+      "name": "stakeNu",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        }
+      ],
+      "name": "stakedNu",
+      "outputs": [
+        {
+          "internalType": "uint256",
+          "name": "nuAmount",
+          "type": "uint256"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        }
+      ],
+      "name": "stakes",
+      "outputs": [
+        {
+          "internalType": "uint96",
+          "name": "tStake",
+          "type": "uint96"
+        },
+        {
+          "internalType": "uint96",
+          "name": "keepInTStake",
+          "type": "uint96"
+        },
+        {
+          "internalType": "uint96",
+          "name": "nuInTStake",
+          "type": "uint96"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        },
+        {
+          "internalType": "uint96",
+          "name": "amount",
+          "type": "uint96"
+        }
+      ],
+      "name": "topUp",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        }
+      ],
+      "name": "topUpKeep",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        }
+      ],
+      "name": "topUpNu",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "newGuvnor",
+          "type": "address"
+        }
+      ],
+      "name": "transferGovernance",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        }
+      ],
+      "name": "unstakeAll",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        }
+      ],
+      "name": "unstakeKeep",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        },
+        {
+          "internalType": "uint96",
+          "name": "amount",
+          "type": "uint96"
+        }
+      ],
+      "name": "unstakeNu",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        },
+        {
+          "internalType": "uint96",
+          "name": "amount",
+          "type": "uint96"
+        }
+      ],
+      "name": "unstakeT",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "recipient",
+          "type": "address"
+        },
+        {
+          "internalType": "uint96",
+          "name": "amount",
+          "type": "uint96"
+        }
+      ],
+      "name": "withdrawNotificationReward",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    }
+  ]
+}
diff --git a/src/threshold-ts/tbtc/dapp-development-sepolia-artifacts/RandomBeacon.json b/src/threshold-ts/tbtc/dapp-development-sepolia-artifacts/RandomBeacon.json
new file mode 100644
index 000000000..6ca0e0e63
--- /dev/null
+++ b/src/threshold-ts/tbtc/dapp-development-sepolia-artifacts/RandomBeacon.json
@@ -0,0 +1,3269 @@
+{
+  "address": "0x02CBA6D77CF9fB019e322c55b34c9d42f2eF4D74",
+  "abi": [
+    {
+      "inputs": [
+        {
+          "internalType": "contract SortitionPool",
+          "name": "_sortitionPool",
+          "type": "address"
+        },
+        {
+          "internalType": "contract IERC20",
+          "name": "_tToken",
+          "type": "address"
+        },
+        {
+          "internalType": "contract IStaking",
+          "name": "_staking",
+          "type": "address"
+        },
+        {
+          "internalType": "contract BeaconDkgValidator",
+          "name": "_dkgValidator",
+          "type": "address"
+        },
+        {
+          "internalType": "contract ReimbursementPool",
+          "name": "_reimbursementPool",
+          "type": "address"
+        }
+      ],
+      "stateMutability": "nonpayable",
+      "type": "constructor"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        }
+      ],
+      "name": "AuthorizationDecreaseApproved",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        },
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "operator",
+          "type": "address"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint96",
+          "name": "fromAmount",
+          "type": "uint96"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint96",
+          "name": "toAmount",
+          "type": "uint96"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint64",
+          "name": "decreasingAt",
+          "type": "uint64"
+        }
+      ],
+      "name": "AuthorizationDecreaseRequested",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        },
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "operator",
+          "type": "address"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint96",
+          "name": "fromAmount",
+          "type": "uint96"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint96",
+          "name": "toAmount",
+          "type": "uint96"
+        }
+      ],
+      "name": "AuthorizationIncreased",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": false,
+          "internalType": "uint96",
+          "name": "minimumAuthorization",
+          "type": "uint96"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint64",
+          "name": "authorizationDecreaseDelay",
+          "type": "uint64"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint64",
+          "name": "authorizationDecreaseChangePeriod",
+          "type": "uint64"
+        }
+      ],
+      "name": "AuthorizationParametersUpdated",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "entry",
+          "type": "uint256"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "entrySubmittedBlock",
+          "type": "uint256"
+        }
+      ],
+      "name": "CallbackFailed",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "bytes32",
+          "name": "resultHash",
+          "type": "bytes32"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "slashingAmount",
+          "type": "uint256"
+        },
+        {
+          "indexed": false,
+          "internalType": "address",
+          "name": "maliciousSubmitter",
+          "type": "address"
+        }
+      ],
+      "name": "DkgMaliciousResultSlashed",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "bytes32",
+          "name": "resultHash",
+          "type": "bytes32"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "slashingAmount",
+          "type": "uint256"
+        },
+        {
+          "indexed": false,
+          "internalType": "address",
+          "name": "maliciousSubmitter",
+          "type": "address"
+        }
+      ],
+      "name": "DkgMaliciousResultSlashingFailed",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "bytes32",
+          "name": "resultHash",
+          "type": "bytes32"
+        },
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "approver",
+          "type": "address"
+        }
+      ],
+      "name": "DkgResultApproved",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "bytes32",
+          "name": "resultHash",
+          "type": "bytes32"
+        },
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "challenger",
+          "type": "address"
+        },
+        {
+          "indexed": false,
+          "internalType": "string",
+          "name": "reason",
+          "type": "string"
+        }
+      ],
+      "name": "DkgResultChallenged",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "bytes32",
+          "name": "resultHash",
+          "type": "bytes32"
+        },
+        {
+          "indexed": true,
+          "internalType": "uint256",
+          "name": "seed",
+          "type": "uint256"
+        },
+        {
+          "components": [
+            {
+              "internalType": "uint256",
+              "name": "submitterMemberIndex",
+              "type": "uint256"
+            },
+            {
+              "internalType": "bytes",
+              "name": "groupPubKey",
+              "type": "bytes"
+            },
+            {
+              "internalType": "uint8[]",
+              "name": "misbehavedMembersIndices",
+              "type": "uint8[]"
+            },
+            {
+              "internalType": "bytes",
+              "name": "signatures",
+              "type": "bytes"
+            },
+            {
+              "internalType": "uint256[]",
+              "name": "signingMembersIndices",
+              "type": "uint256[]"
+            },
+            {
+              "internalType": "uint32[]",
+              "name": "members",
+              "type": "uint32[]"
+            },
+            {
+              "internalType": "bytes32",
+              "name": "membersHash",
+              "type": "bytes32"
+            }
+          ],
+          "indexed": false,
+          "internalType": "struct BeaconDkg.Result",
+          "name": "result",
+          "type": "tuple"
+        }
+      ],
+      "name": "DkgResultSubmitted",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [],
+      "name": "DkgSeedTimedOut",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "uint256",
+          "name": "seed",
+          "type": "uint256"
+        }
+      ],
+      "name": "DkgStarted",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [],
+      "name": "DkgStateLocked",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [],
+      "name": "DkgTimedOut",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "dkgResultSubmissionGas",
+          "type": "uint256"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "dkgResultApprovalGasOffset",
+          "type": "uint256"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "notifyOperatorInactivityGasOffset",
+          "type": "uint256"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "relayEntrySubmissionGasOffset",
+          "type": "uint256"
+        }
+      ],
+      "name": "GasParametersUpdated",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": false,
+          "internalType": "address",
+          "name": "oldGovernance",
+          "type": "address"
+        },
+        {
+          "indexed": false,
+          "internalType": "address",
+          "name": "newGovernance",
+          "type": "address"
+        }
+      ],
+      "name": "GovernanceTransferred",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "groupCreationFrequency",
+          "type": "uint256"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "groupLifetime",
+          "type": "uint256"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "dkgResultChallengePeriodLength",
+          "type": "uint256"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "dkgResultChallengeExtraGas",
+          "type": "uint256"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "dkgResultSubmissionTimeout",
+          "type": "uint256"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "dkgResultSubmitterPrecedencePeriodLength",
+          "type": "uint256"
+        }
+      ],
+      "name": "GroupCreationParametersUpdated",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "uint64",
+          "name": "groupId",
+          "type": "uint64"
+        },
+        {
+          "indexed": true,
+          "internalType": "bytes",
+          "name": "groupPubKey",
+          "type": "bytes"
+        }
+      ],
+      "name": "GroupRegistered",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "uint64",
+          "name": "groupId",
+          "type": "uint64"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "nonce",
+          "type": "uint256"
+        },
+        {
+          "indexed": false,
+          "internalType": "address",
+          "name": "notifier",
+          "type": "address"
+        }
+      ],
+      "name": "InactivityClaimed",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        },
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "operator",
+          "type": "address"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint96",
+          "name": "fromAmount",
+          "type": "uint96"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint96",
+          "name": "toAmount",
+          "type": "uint96"
+        }
+      ],
+      "name": "InvoluntaryAuthorizationDecreaseFailed",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        },
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "operator",
+          "type": "address"
+        }
+      ],
+      "name": "OperatorJoinedSortitionPool",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        },
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "operator",
+          "type": "address"
+        }
+      ],
+      "name": "OperatorRegistered",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        },
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "operator",
+          "type": "address"
+        }
+      ],
+      "name": "OperatorStatusUpdated",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": false,
+          "internalType": "address",
+          "name": "newReimbursementPool",
+          "type": "address"
+        }
+      ],
+      "name": "ReimbursementPoolUpdated",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "uint256",
+          "name": "requestId",
+          "type": "uint256"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "slashingAmount",
+          "type": "uint256"
+        },
+        {
+          "indexed": false,
+          "internalType": "address[]",
+          "name": "groupMembers",
+          "type": "address[]"
+        }
+      ],
+      "name": "RelayEntryDelaySlashed",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "uint256",
+          "name": "requestId",
+          "type": "uint256"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "slashingAmount",
+          "type": "uint256"
+        },
+        {
+          "indexed": false,
+          "internalType": "address[]",
+          "name": "groupMembers",
+          "type": "address[]"
+        }
+      ],
+      "name": "RelayEntryDelaySlashingFailed",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "relayEntrySoftTimeout",
+          "type": "uint256"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "relayEntryHardTimeout",
+          "type": "uint256"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "callbackGasLimit",
+          "type": "uint256"
+        }
+      ],
+      "name": "RelayEntryParametersUpdated",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "uint256",
+          "name": "requestId",
+          "type": "uint256"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint64",
+          "name": "groupId",
+          "type": "uint64"
+        },
+        {
+          "indexed": false,
+          "internalType": "bytes",
+          "name": "previousEntry",
+          "type": "bytes"
+        }
+      ],
+      "name": "RelayEntryRequested",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "uint256",
+          "name": "requestId",
+          "type": "uint256"
+        },
+        {
+          "indexed": false,
+          "internalType": "address",
+          "name": "submitter",
+          "type": "address"
+        },
+        {
+          "indexed": false,
+          "internalType": "bytes",
+          "name": "entry",
+          "type": "bytes"
+        }
+      ],
+      "name": "RelayEntrySubmitted",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "uint256",
+          "name": "requestId",
+          "type": "uint256"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint64",
+          "name": "terminatedGroupId",
+          "type": "uint64"
+        }
+      ],
+      "name": "RelayEntryTimedOut",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "uint256",
+          "name": "requestId",
+          "type": "uint256"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "slashingAmount",
+          "type": "uint256"
+        },
+        {
+          "indexed": false,
+          "internalType": "address[]",
+          "name": "groupMembers",
+          "type": "address[]"
+        }
+      ],
+      "name": "RelayEntryTimeoutSlashed",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "uint256",
+          "name": "requestId",
+          "type": "uint256"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "slashingAmount",
+          "type": "uint256"
+        },
+        {
+          "indexed": false,
+          "internalType": "address[]",
+          "name": "groupMembers",
+          "type": "address[]"
+        }
+      ],
+      "name": "RelayEntryTimeoutSlashingFailed",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "requester",
+          "type": "address"
+        },
+        {
+          "indexed": false,
+          "internalType": "bool",
+          "name": "isAuthorized",
+          "type": "bool"
+        }
+      ],
+      "name": "RequesterAuthorizationUpdated",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "sortitionPoolRewardsBanDuration",
+          "type": "uint256"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "relayEntryTimeoutNotificationRewardMultiplier",
+          "type": "uint256"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "unauthorizedSigningNotificationRewardMultiplier",
+          "type": "uint256"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "dkgMaliciousResultNotificationRewardMultiplier",
+          "type": "uint256"
+        }
+      ],
+      "name": "RewardParametersUpdated",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint96",
+          "name": "amount",
+          "type": "uint96"
+        }
+      ],
+      "name": "RewardsWithdrawn",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "relayEntrySubmissionFailureSlashingAmount",
+          "type": "uint256"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "maliciousDkgResultSlashingAmount",
+          "type": "uint256"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "unauthorizedSigningSlashingAmount",
+          "type": "uint256"
+        }
+      ],
+      "name": "SlashingParametersUpdated",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "uint64",
+          "name": "groupId",
+          "type": "uint64"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "unauthorizedSigningSlashingAmount",
+          "type": "uint256"
+        },
+        {
+          "indexed": false,
+          "internalType": "address[]",
+          "name": "groupMembers",
+          "type": "address[]"
+        }
+      ],
+      "name": "UnauthorizedSigningSlashed",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "uint64",
+          "name": "groupId",
+          "type": "uint64"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "unauthorizedSigningSlashingAmount",
+          "type": "uint256"
+        },
+        {
+          "indexed": false,
+          "internalType": "address[]",
+          "name": "groupMembers",
+          "type": "address[]"
+        }
+      ],
+      "name": "UnauthorizedSigningSlashingFailed",
+      "type": "event"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        }
+      ],
+      "name": "approveAuthorizationDecrease",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "components": [
+            {
+              "internalType": "uint256",
+              "name": "submitterMemberIndex",
+              "type": "uint256"
+            },
+            {
+              "internalType": "bytes",
+              "name": "groupPubKey",
+              "type": "bytes"
+            },
+            {
+              "internalType": "uint8[]",
+              "name": "misbehavedMembersIndices",
+              "type": "uint8[]"
+            },
+            {
+              "internalType": "bytes",
+              "name": "signatures",
+              "type": "bytes"
+            },
+            {
+              "internalType": "uint256[]",
+              "name": "signingMembersIndices",
+              "type": "uint256[]"
+            },
+            {
+              "internalType": "uint32[]",
+              "name": "members",
+              "type": "uint32[]"
+            },
+            {
+              "internalType": "bytes32",
+              "name": "membersHash",
+              "type": "bytes32"
+            }
+          ],
+          "internalType": "struct BeaconDkg.Result",
+          "name": "dkgResult",
+          "type": "tuple"
+        }
+      ],
+      "name": "approveDkgResult",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        },
+        {
+          "internalType": "uint96",
+          "name": "fromAmount",
+          "type": "uint96"
+        },
+        {
+          "internalType": "uint96",
+          "name": "toAmount",
+          "type": "uint96"
+        }
+      ],
+      "name": "authorizationDecreaseRequested",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        },
+        {
+          "internalType": "uint96",
+          "name": "fromAmount",
+          "type": "uint96"
+        },
+        {
+          "internalType": "uint96",
+          "name": "toAmount",
+          "type": "uint96"
+        }
+      ],
+      "name": "authorizationIncreased",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "authorizationParameters",
+      "outputs": [
+        {
+          "internalType": "uint96",
+          "name": "minimumAuthorization",
+          "type": "uint96"
+        },
+        {
+          "internalType": "uint64",
+          "name": "authorizationDecreaseDelay",
+          "type": "uint64"
+        },
+        {
+          "internalType": "uint64",
+          "name": "authorizationDecreaseChangePeriod",
+          "type": "uint64"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "",
+          "type": "address"
+        }
+      ],
+      "name": "authorizedRequesters",
+      "outputs": [
+        {
+          "internalType": "bool",
+          "name": "",
+          "type": "bool"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        }
+      ],
+      "name": "availableRewards",
+      "outputs": [
+        {
+          "internalType": "uint96",
+          "name": "",
+          "type": "uint96"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "components": [
+            {
+              "internalType": "uint256",
+              "name": "submitterMemberIndex",
+              "type": "uint256"
+            },
+            {
+              "internalType": "bytes",
+              "name": "groupPubKey",
+              "type": "bytes"
+            },
+            {
+              "internalType": "uint8[]",
+              "name": "misbehavedMembersIndices",
+              "type": "uint8[]"
+            },
+            {
+              "internalType": "bytes",
+              "name": "signatures",
+              "type": "bytes"
+            },
+            {
+              "internalType": "uint256[]",
+              "name": "signingMembersIndices",
+              "type": "uint256[]"
+            },
+            {
+              "internalType": "uint32[]",
+              "name": "members",
+              "type": "uint32[]"
+            },
+            {
+              "internalType": "bytes32",
+              "name": "membersHash",
+              "type": "bytes32"
+            }
+          ],
+          "internalType": "struct BeaconDkg.Result",
+          "name": "dkgResult",
+          "type": "tuple"
+        }
+      ],
+      "name": "challengeDkgResult",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        }
+      ],
+      "name": "eligibleStake",
+      "outputs": [
+        {
+          "internalType": "uint96",
+          "name": "",
+          "type": "uint96"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "gasParameters",
+      "outputs": [
+        {
+          "internalType": "uint256",
+          "name": "dkgResultSubmissionGas",
+          "type": "uint256"
+        },
+        {
+          "internalType": "uint256",
+          "name": "dkgResultApprovalGasOffset",
+          "type": "uint256"
+        },
+        {
+          "internalType": "uint256",
+          "name": "notifyOperatorInactivityGasOffset",
+          "type": "uint256"
+        },
+        {
+          "internalType": "uint256",
+          "name": "relayEntrySubmissionGasOffset",
+          "type": "uint256"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "genesis",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "uint64",
+          "name": "groupId",
+          "type": "uint64"
+        }
+      ],
+      "name": "getGroup",
+      "outputs": [
+        {
+          "components": [
+            {
+              "internalType": "bytes",
+              "name": "groupPubKey",
+              "type": "bytes"
+            },
+            {
+              "internalType": "uint256",
+              "name": "registrationBlockNumber",
+              "type": "uint256"
+            },
+            {
+              "internalType": "bytes32",
+              "name": "membersHash",
+              "type": "bytes32"
+            },
+            {
+              "internalType": "bool",
+              "name": "terminated",
+              "type": "bool"
+            }
+          ],
+          "internalType": "struct Groups.Group",
+          "name": "",
+          "type": "tuple"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "bytes",
+          "name": "groupPubKey",
+          "type": "bytes"
+        }
+      ],
+      "name": "getGroup",
+      "outputs": [
+        {
+          "components": [
+            {
+              "internalType": "bytes",
+              "name": "groupPubKey",
+              "type": "bytes"
+            },
+            {
+              "internalType": "uint256",
+              "name": "registrationBlockNumber",
+              "type": "uint256"
+            },
+            {
+              "internalType": "bytes32",
+              "name": "membersHash",
+              "type": "bytes32"
+            },
+            {
+              "internalType": "bool",
+              "name": "terminated",
+              "type": "bool"
+            }
+          ],
+          "internalType": "struct Groups.Group",
+          "name": "",
+          "type": "tuple"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "getGroupCreationState",
+      "outputs": [
+        {
+          "internalType": "enum BeaconDkg.State",
+          "name": "",
+          "type": "uint8"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "getGroupsRegistry",
+      "outputs": [
+        {
+          "internalType": "bytes32[]",
+          "name": "",
+          "type": "bytes32[]"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "governance",
+      "outputs": [
+        {
+          "internalType": "address",
+          "name": "",
+          "type": "address"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "groupCreationParameters",
+      "outputs": [
+        {
+          "internalType": "uint256",
+          "name": "groupCreationFrequency",
+          "type": "uint256"
+        },
+        {
+          "internalType": "uint256",
+          "name": "groupLifetime",
+          "type": "uint256"
+        },
+        {
+          "internalType": "uint256",
+          "name": "dkgResultChallengePeriodLength",
+          "type": "uint256"
+        },
+        {
+          "internalType": "uint256",
+          "name": "dkgResultChallengeExtraGas",
+          "type": "uint256"
+        },
+        {
+          "internalType": "uint256",
+          "name": "dkgResultSubmissionTimeout",
+          "type": "uint256"
+        },
+        {
+          "internalType": "uint256",
+          "name": "dkgSubmitterPrecedencePeriodLength",
+          "type": "uint256"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "hasDkgTimedOut",
+      "outputs": [
+        {
+          "internalType": "bool",
+          "name": "",
+          "type": "bool"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "uint64",
+          "name": "",
+          "type": "uint64"
+        }
+      ],
+      "name": "inactivityClaimNonce",
+      "outputs": [
+        {
+          "internalType": "uint256",
+          "name": "",
+          "type": "uint256"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        },
+        {
+          "internalType": "uint96",
+          "name": "fromAmount",
+          "type": "uint96"
+        },
+        {
+          "internalType": "uint96",
+          "name": "toAmount",
+          "type": "uint96"
+        }
+      ],
+      "name": "involuntaryAuthorizationDecrease",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "operator",
+          "type": "address"
+        }
+      ],
+      "name": "isOperatorInPool",
+      "outputs": [
+        {
+          "internalType": "bool",
+          "name": "",
+          "type": "bool"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "operator",
+          "type": "address"
+        }
+      ],
+      "name": "isOperatorUpToDate",
+      "outputs": [
+        {
+          "internalType": "bool",
+          "name": "",
+          "type": "bool"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "isRelayRequestInProgress",
+      "outputs": [
+        {
+          "internalType": "bool",
+          "name": "",
+          "type": "bool"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "joinSortitionPool",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "minimumAuthorization",
+      "outputs": [
+        {
+          "internalType": "uint96",
+          "name": "",
+          "type": "uint96"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "notifyDkgTimeout",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "components": [
+            {
+              "internalType": "uint64",
+              "name": "groupId",
+              "type": "uint64"
+            },
+            {
+              "internalType": "uint256[]",
+              "name": "inactiveMembersIndices",
+              "type": "uint256[]"
+            },
+            {
+              "internalType": "bytes",
+              "name": "signatures",
+              "type": "bytes"
+            },
+            {
+              "internalType": "uint256[]",
+              "name": "signingMembersIndices",
+              "type": "uint256[]"
+            }
+          ],
+          "internalType": "struct BeaconInactivity.Claim",
+          "name": "claim",
+          "type": "tuple"
+        },
+        {
+          "internalType": "uint256",
+          "name": "nonce",
+          "type": "uint256"
+        },
+        {
+          "internalType": "uint32[]",
+          "name": "groupMembers",
+          "type": "uint32[]"
+        }
+      ],
+      "name": "notifyOperatorInactivity",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "operator",
+          "type": "address"
+        }
+      ],
+      "name": "operatorToStakingProvider",
+      "outputs": [
+        {
+          "internalType": "address",
+          "name": "",
+          "type": "address"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        }
+      ],
+      "name": "pendingAuthorizationDecrease",
+      "outputs": [
+        {
+          "internalType": "uint96",
+          "name": "",
+          "type": "uint96"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "operator",
+          "type": "address"
+        }
+      ],
+      "name": "registerOperator",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "reimbursementPool",
+      "outputs": [
+        {
+          "internalType": "contract ReimbursementPool",
+          "name": "",
+          "type": "address"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "relayEntryParameters",
+      "outputs": [
+        {
+          "internalType": "uint256",
+          "name": "relayEntrySoftTimeout",
+          "type": "uint256"
+        },
+        {
+          "internalType": "uint256",
+          "name": "relayEntryHardTimeout",
+          "type": "uint256"
+        },
+        {
+          "internalType": "uint256",
+          "name": "callbackGasLimit",
+          "type": "uint256"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        }
+      ],
+      "name": "remainingAuthorizationDecreaseDelay",
+      "outputs": [
+        {
+          "internalType": "uint64",
+          "name": "",
+          "type": "uint64"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "uint32[]",
+          "name": "groupMembers",
+          "type": "uint32[]"
+        }
+      ],
+      "name": "reportRelayEntryTimeout",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "bytes",
+          "name": "signedMsgSender",
+          "type": "bytes"
+        },
+        {
+          "internalType": "uint64",
+          "name": "groupId",
+          "type": "uint64"
+        },
+        {
+          "internalType": "uint32[]",
+          "name": "groupMembers",
+          "type": "uint32[]"
+        }
+      ],
+      "name": "reportUnauthorizedSigning",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "contract IRandomBeaconConsumer",
+          "name": "callbackContract",
+          "type": "address"
+        }
+      ],
+      "name": "requestRelayEntry",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "rewardParameters",
+      "outputs": [
+        {
+          "internalType": "uint256",
+          "name": "sortitionPoolRewardsBanDuration",
+          "type": "uint256"
+        },
+        {
+          "internalType": "uint256",
+          "name": "relayEntryTimeoutNotificationRewardMultiplier",
+          "type": "uint256"
+        },
+        {
+          "internalType": "uint256",
+          "name": "unauthorizedSigningNotificationRewardMultiplier",
+          "type": "uint256"
+        },
+        {
+          "internalType": "uint256",
+          "name": "dkgMaliciousResultNotificationRewardMultiplier",
+          "type": "uint256"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "selectGroup",
+      "outputs": [
+        {
+          "internalType": "uint32[]",
+          "name": "",
+          "type": "uint32[]"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "requester",
+          "type": "address"
+        },
+        {
+          "internalType": "bool",
+          "name": "isAuthorized",
+          "type": "bool"
+        }
+      ],
+      "name": "setRequesterAuthorization",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "slashingParameters",
+      "outputs": [
+        {
+          "internalType": "uint96",
+          "name": "relayEntrySubmissionFailureSlashingAmount",
+          "type": "uint96"
+        },
+        {
+          "internalType": "uint96",
+          "name": "maliciousDkgResultSlashingAmount",
+          "type": "uint96"
+        },
+        {
+          "internalType": "uint96",
+          "name": "unauthorizedSigningSlashingAmount",
+          "type": "uint96"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "sortitionPool",
+      "outputs": [
+        {
+          "internalType": "contract SortitionPool",
+          "name": "",
+          "type": "address"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "staking",
+      "outputs": [
+        {
+          "internalType": "contract IStaking",
+          "name": "",
+          "type": "address"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        }
+      ],
+      "name": "stakingProviderToOperator",
+      "outputs": [
+        {
+          "internalType": "address",
+          "name": "",
+          "type": "address"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "components": [
+            {
+              "internalType": "uint256",
+              "name": "submitterMemberIndex",
+              "type": "uint256"
+            },
+            {
+              "internalType": "bytes",
+              "name": "groupPubKey",
+              "type": "bytes"
+            },
+            {
+              "internalType": "uint8[]",
+              "name": "misbehavedMembersIndices",
+              "type": "uint8[]"
+            },
+            {
+              "internalType": "bytes",
+              "name": "signatures",
+              "type": "bytes"
+            },
+            {
+              "internalType": "uint256[]",
+              "name": "signingMembersIndices",
+              "type": "uint256[]"
+            },
+            {
+              "internalType": "uint32[]",
+              "name": "members",
+              "type": "uint32[]"
+            },
+            {
+              "internalType": "bytes32",
+              "name": "membersHash",
+              "type": "bytes32"
+            }
+          ],
+          "internalType": "struct BeaconDkg.Result",
+          "name": "dkgResult",
+          "type": "tuple"
+        }
+      ],
+      "name": "submitDkgResult",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "bytes",
+          "name": "entry",
+          "type": "bytes"
+        },
+        {
+          "internalType": "uint32[]",
+          "name": "groupMembers",
+          "type": "uint32[]"
+        }
+      ],
+      "name": "submitRelayEntry",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "bytes",
+          "name": "entry",
+          "type": "bytes"
+        }
+      ],
+      "name": "submitRelayEntry",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "tToken",
+      "outputs": [
+        {
+          "internalType": "contract IERC20",
+          "name": "",
+          "type": "address"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "newGovernance",
+          "type": "address"
+        }
+      ],
+      "name": "transferGovernance",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "uint96",
+          "name": "_minimumAuthorization",
+          "type": "uint96"
+        },
+        {
+          "internalType": "uint64",
+          "name": "_authorizationDecreaseDelay",
+          "type": "uint64"
+        },
+        {
+          "internalType": "uint64",
+          "name": "_authorizationDecreaseChangePeriod",
+          "type": "uint64"
+        }
+      ],
+      "name": "updateAuthorizationParameters",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "uint256",
+          "name": "dkgResultSubmissionGas",
+          "type": "uint256"
+        },
+        {
+          "internalType": "uint256",
+          "name": "dkgResultApprovalGasOffset",
+          "type": "uint256"
+        },
+        {
+          "internalType": "uint256",
+          "name": "notifyOperatorInactivityGasOffset",
+          "type": "uint256"
+        },
+        {
+          "internalType": "uint256",
+          "name": "relayEntrySubmissionGasOffset",
+          "type": "uint256"
+        }
+      ],
+      "name": "updateGasParameters",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "uint256",
+          "name": "groupCreationFrequency",
+          "type": "uint256"
+        },
+        {
+          "internalType": "uint256",
+          "name": "groupLifetime",
+          "type": "uint256"
+        },
+        {
+          "internalType": "uint256",
+          "name": "dkgResultChallengePeriodLength",
+          "type": "uint256"
+        },
+        {
+          "internalType": "uint256",
+          "name": "dkgResultChallengeExtraGas",
+          "type": "uint256"
+        },
+        {
+          "internalType": "uint256",
+          "name": "dkgResultSubmissionTimeout",
+          "type": "uint256"
+        },
+        {
+          "internalType": "uint256",
+          "name": "dkgSubmitterPrecedencePeriodLength",
+          "type": "uint256"
+        }
+      ],
+      "name": "updateGroupCreationParameters",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "operator",
+          "type": "address"
+        }
+      ],
+      "name": "updateOperatorStatus",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "contract ReimbursementPool",
+          "name": "_reimbursementPool",
+          "type": "address"
+        }
+      ],
+      "name": "updateReimbursementPool",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "uint256",
+          "name": "relayEntrySoftTimeout",
+          "type": "uint256"
+        },
+        {
+          "internalType": "uint256",
+          "name": "relayEntryHardTimeout",
+          "type": "uint256"
+        },
+        {
+          "internalType": "uint256",
+          "name": "callbackGasLimit",
+          "type": "uint256"
+        }
+      ],
+      "name": "updateRelayEntryParameters",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "uint256",
+          "name": "sortitionPoolRewardsBanDuration",
+          "type": "uint256"
+        },
+        {
+          "internalType": "uint256",
+          "name": "relayEntryTimeoutNotificationRewardMultiplier",
+          "type": "uint256"
+        },
+        {
+          "internalType": "uint256",
+          "name": "unauthorizedSigningNotificationRewardMultiplier",
+          "type": "uint256"
+        },
+        {
+          "internalType": "uint256",
+          "name": "dkgMaliciousResultNotificationRewardMultiplier",
+          "type": "uint256"
+        }
+      ],
+      "name": "updateRewardParameters",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "uint96",
+          "name": "relayEntrySubmissionFailureSlashingAmount",
+          "type": "uint96"
+        },
+        {
+          "internalType": "uint96",
+          "name": "maliciousDkgResultSlashingAmount",
+          "type": "uint96"
+        },
+        {
+          "internalType": "uint96",
+          "name": "unauthorizedSigningSlashingAmount",
+          "type": "uint96"
+        }
+      ],
+      "name": "updateSlashingParameters",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "recipient",
+          "type": "address"
+        }
+      ],
+      "name": "withdrawIneligibleRewards",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        }
+      ],
+      "name": "withdrawRewards",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    }
+  ],
+  "transactionHash": "0x0b9ff095d08d6428936ff1aa63cf69c05bfc09756c986288c9c5b1e48fc9e80f",
+  "receipt": {
+    "to": null,
+    "from": "0x123694886DBf5Ac94DDA07135349534536D14cAf",
+    "contractAddress": "0x5499f54b4A1CB4816eefCf78962040461be3D80b",
+    "transactionIndex": 134,
+    "gasUsed": "5967896",
+    "logsBloom": "0x00000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000800000000000000000000000000002000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000",
+    "blockHash": "0x2a91baafb0d14ee461a2d80f4a45bd592d15716538c3509c470ae00676be2213",
+    "transactionHash": "0x0b9ff095d08d6428936ff1aa63cf69c05bfc09756c986288c9c5b1e48fc9e80f",
+    "logs": [
+      {
+        "transactionIndex": 134,
+        "blockNumber": 15638933,
+        "transactionHash": "0x0b9ff095d08d6428936ff1aa63cf69c05bfc09756c986288c9c5b1e48fc9e80f",
+        "address": "0x5499f54b4A1CB4816eefCf78962040461be3D80b",
+        "topics": [
+          "0x5f56bee8cffbe9a78652a74a60705edede02af10b0bbb888ca44b79a0d42ce80"
+        ],
+        "data": "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000123694886dbf5ac94dda07135349534536d14caf",
+        "logIndex": 219,
+        "blockHash": "0x2a91baafb0d14ee461a2d80f4a45bd592d15716538c3509c470ae00676be2213"
+      }
+    ],
+    "blockNumber": 15638933,
+    "cumulativeGasUsed": "18819477",
+    "status": 1,
+    "byzantium": true
+  },
+  "args": [
+    "0x4e4cBA3779d56386ED43631b4dCD6d8EacEcBCF6",
+    "0xCdF7028ceAB81fA0C6971208e83fa7872994beE5",
+    "0x01B67b1194C75264d06F808A921228a95C765dd7",
+    "0x4EDC83c5C5B0C41A594371485554B95280653f94",
+    "0x8adF3f35dBE4026112bCFc078872bcb967732Ea8"
+  ],
+  "numDeployments": 1,
+  "solcInputHash": "315dd8aa56418c14cbdc8d65adaa494b",
+  "libraries": {
+    "BLS": "0x6552059B6eFc6aA4AE3ea45f28ED4D92acE020cD",
+    "BeaconAuthorization": "0x632c2d58Ad870fbd4569da0A4E82dDf4B56E83E8",
+    "BeaconDkg": "0x024a697788918007592572f7CD020df2bC2ABD84",
+    "BeaconInactivity": "0x67A26f2ebDB2448605936Fe9a5f496cDA7941Ec0"
+  },
+  "devdoc": {
+    "details": "Should be owned by the governance contract controlling Random Beacon      parameters.",
+    "kind": "dev",
+    "methods": {
+      "approveDkgResult((uint256,bytes,uint8[],bytes,uint256[],uint32[],bytes32))": {
+        "params": {
+          "dkgResult": "Result to approve. Must match the submitted result        stored during `submitDkgResult`."
+        }
+      },
+      "authorizationDecreaseRequested(address,uint96,uint96)": {
+        "details": "Can only be called by T staking contract."
+      },
+      "authorizationIncreased(address,uint96,uint96)": {
+        "details": "Can only be called by T staking contract."
+      },
+      "authorizationParameters()": {
+        "details": "The minimum authorization is also returned by `minimumAuthorization()`      function, as a requirement of `IApplication` interface.",
+        "returns": {
+          "authorizationDecreaseChangePeriod": "Authorization decrease change        period in seconds. It is the time, before authorization decrease        delay end, during which the pending authorization decrease        request can be overwritten.        If set to 0, pending authorization decrease request can not be        overwritten until the entire `authorizationDecreaseDelay` ends.        If set to value equal `authorizationDecreaseDelay`, request can        always be overwritten.",
+          "authorizationDecreaseDelay": "Delay in seconds that needs to pass         between the time authorization decrease is requested and the         time that request gets approved. Protects against free-riders         earning rewards and not being active in the network.",
+          "minimumAuthorization": "The minimum authorization amount required         so that operator can participate in the random beacon. This         amount is required to execute slashing for providing a malicious         DKG result or when a relay entry times out."
+        }
+      },
+      "challengeDkgResult((uint256,bytes,uint8[],bytes,uint256[],uint32[],bytes32))": {
+        "details": "Due to EIP-150 1/64 of the gas is not forwarded to the call, and      will be kept to execute the remaining operations in the function      after the call inside the try-catch. To eliminate a class of      attacks related to the gas limit manipulation, this function      requires an extra amount of gas to be left at the end of the      execution.",
+        "params": {
+          "dkgResult": "Result to challenge. Must match the submitted result        stored during `submitDkgResult`."
+        }
+      },
+      "constructor": {
+        "details": "Assigns initial values to parameters to make the beacon work      safely. These parameters are just proposed defaults and they might      be updated with `update*` functions after the contract deployment      and before transferring the ownership to the governance contract."
+      },
+      "gasParameters()": {
+        "returns": {
+          "dkgResultApprovalGasOffset": "Gas that is meant to balance the DKG         result approval's overall cost.",
+          "dkgResultSubmissionGas": "Calculated gas cost for submitting a DKG         result. This will be refunded as part of the DKG approval         process.",
+          "notifyOperatorInactivityGasOffset": "Gas that is meant to balance         the operator inactivity notification cost.",
+          "relayEntrySubmissionGasOffset": "Gas that is meant to balance the         relay entry submission cost."
+        }
+      },
+      "groupCreationParameters()": {
+        "returns": {
+          "dkgResultChallengeExtraGas": "The extra gas required to be left at         the end of the challenge DKG result transaction.",
+          "dkgResultChallengePeriodLength": "The number of blocks for which         a DKG result can be challenged. Anyone can challenge DKG result         for a certain number of blocks before the result is fully         accepted and the group registered in the pool of active groups.         If the challenge gets accepted, all operators who signed the         malicious result get slashed for and the notifier gets rewarded.",
+          "dkgResultSubmissionTimeout": "Timeout in blocks for a group to         submit the DKG result. All members are eligible to submit the         DKG result. If `dkgResultSubmissionTimeout` passes without the         DKG result submitted, DKG is considered as timed out and no DKG         result for this group creation can be submitted anymore.",
+          "dkgSubmitterPrecedencePeriodLength": "Time during the DKG result         approval stage when the submitter of the DKG result takes the         precedence to approve the DKG result. After this time passes         anyone can approve the DKG result.",
+          "groupCreationFrequency": "The frequency of a new group creation.         Groups are created with a fixed frequency of relay requests.",
+          "groupLifetime": "Group lifetime in blocks. When a group reached its         lifetime, it is no longer selected for new relay requests but         may still be responsible for submitting relay entry if relay         request assigned to that group is still pending."
+        }
+      },
+      "hasDkgTimedOut()": {
+        "returns": {
+          "_0": "True if DKG timed out, false otherwise."
+        }
+      },
+      "isRelayRequestInProgress()": {
+        "returns": {
+          "_0": "Flag indicating whether a relay entry request is currently         in progress."
+        }
+      },
+      "notifyOperatorInactivity((uint64,uint256[],bytes,uint256[]),uint256,uint32[])": {
+        "params": {
+          "claim": "Operator inactivity claim.",
+          "groupMembers": "Identifiers of group members.",
+          "nonce": "Current inactivity claim nonce for the given group. Must        be the same as the stored one."
+        }
+      },
+      "relayEntryParameters()": {
+        "returns": {
+          "callbackGasLimit": "Relay entry callback gas limit. This is the gas         limit with which callback function provided in the relay request         transaction is executed. The callback is executed with a new         relay entry value in the same transaction the relay entry is         submitted.",
+          "relayEntryHardTimeout": "Hard timeout in blocks for a group to         submit the relay entry. After the soft timeout passes without         relay entry submitted, all group members start getting slashed.         The slashing amount increases linearly until the group submits         the relay entry or until `relayEntryHardTimeout` is reached.         When the hard timeout is reached, each group member will get         slashed for `_relayEntrySubmissionFailureSlashingAmount`.",
+          "relayEntrySoftTimeout": "Soft timeout in blocks for a group to         submit the relay entry. If the soft timeout is reached for         submitting the relay entry, the slashing starts."
+        }
+      },
+      "reportRelayEntryTimeout(uint32[])": {
+        "params": {
+          "groupMembers": "Identifiers of group members."
+        }
+      },
+      "reportUnauthorizedSigning(bytes,uint64,uint32[])": {
+        "params": {
+          "groupId": "Group that is being reported for leaking a private key.",
+          "groupMembers": "Identifiers of group members.",
+          "signedMsgSender": "Signature of the sender's address as a message."
+        }
+      },
+      "requestRelayEntry(address)": {
+        "params": {
+          "callbackContract": "Beacon consumer callback contract."
+        }
+      },
+      "rewardParameters()": {
+        "returns": {
+          "dkgMaliciousResultNotificationRewardMultiplier": "Percentage of the         staking contract malicious behavior notification reward which         will be transferred to the notifier reporting about a malicious         DKG result. Notifiers are rewarded from a notifiers treasury         pool. For example, if notification reward is 1000 and the value         of the multiplier is 5, the notifier will receive:         5% of 1000 = 50 per each operator affected.",
+          "relayEntryTimeoutNotificationRewardMultiplier": "Percentage of the         staking contract malicious behavior notification reward which         will be transferred to the notifier reporting about relay entry         timeout. Notifiers are rewarded from a notifiers treasury pool.         For example, if notification reward is 1000 and the value of the         multiplier is 5, the notifier will receive: 5% of 1000 = 50 per         each operator affected.",
+          "sortitionPoolRewardsBanDuration": "Duration of the sortition pool         rewards ban imposed on operators who misbehaved during DKG by         being inactive or disqualified and for operators that were         identified by the rest of group members as inactive via         `notifyOperatorInactivity`.",
+          "unauthorizedSigningNotificationRewardMultiplier": "Percentage of the         staking contract malicious behavior notification reward which         will be transferred to the notifier reporting about unauthorized         signing. Notifiers are rewarded from a notifiers treasury pool.         For example, if a notification reward is 1000 and the value of         the multiplier is 5, the notifier will receive: 5% of 1000 = 50         per each operator affected."
+        }
+      },
+      "selectGroup()": {
+        "returns": {
+          "_0": "IDs of selected group members."
+        }
+      },
+      "setRequesterAuthorization(address,bool)": {
+        "details": "Can be called only by the contract guvnor, which should be the      random beacon governance contract.",
+        "params": {
+          "isAuthorized": "True or false",
+          "requester": "Requester, can be a contract or EOA"
+        }
+      },
+      "slashingParameters()": {
+        "returns": {
+          "maliciousDkgResultSlashingAmount": "Slashing amount for submitting         a malicious DKG result. Every DKG result submitted can be         challenged for the time of `dkg.ResultChallengePeriodLength`.         If the DKG result submitted is challenged and proven to be         malicious, the operator who submitted the malicious result is         slashed for `maliciousDkgResultSlashingAmount`.",
+          "relayEntrySubmissionFailureSlashingAmount": "Slashing amount for         not submitting relay entry. When relay entry hard timeout is         reached without the relay entry submitted, each group member         gets slashed for `relayEntrySubmissionFailureSlashingAmount`.         If the relay entry gets submitted after the soft timeout, but         before the hard timeout, each group member gets slashed         proportionally to `relayEntrySubmissionFailureSlashingAmount`         and the time passed since the soft deadline.",
+          "unauthorizedSigningSlashingAmount": "Slashing amount when an         unauthorized signing has been proved, which means the private         key leaked and all the group members should be punished."
+        }
+      },
+      "submitDkgResult((uint256,bytes,uint8[],bytes,uint256[],uint32[],bytes32))": {
+        "params": {
+          "dkgResult": "DKG result."
+        }
+      },
+      "submitRelayEntry(bytes)": {
+        "params": {
+          "entry": "Group BLS signature over the previous entry."
+        }
+      },
+      "submitRelayEntry(bytes,uint32[])": {
+        "params": {
+          "entry": "Group BLS signature over the previous entry.",
+          "groupMembers": "Identifiers of group members."
+        }
+      },
+      "updateAuthorizationParameters(uint96,uint64,uint64)": {
+        "details": "Can be called only by the contract guvnor, which should be the      random beacon governance contract. The caller is responsible for      validating parameters.",
+        "params": {
+          "_authorizationDecreaseChangePeriod": "New authorization decrease        change period in seconds",
+          "_authorizationDecreaseDelay": "New authorization decrease delay in        seconds",
+          "_minimumAuthorization": "New minimum authorization amount"
+        }
+      },
+      "updateGasParameters(uint256,uint256,uint256,uint256)": {
+        "details": "Can be called only by the contract guvnor, which should be the      random beacon governance contract. The caller is responsible for      validating parameters.",
+        "params": {
+          "dkgResultApprovalGasOffset": "New DKG result approval gas offset",
+          "dkgResultSubmissionGas": "New DKG result submission gas",
+          "notifyOperatorInactivityGasOffset": "New operator inactivity        notification gas offset",
+          "relayEntrySubmissionGasOffset": "New relay entry submission gas        offset"
+        }
+      },
+      "updateGroupCreationParameters(uint256,uint256,uint256,uint256,uint256,uint256)": {
+        "details": "Can be called only by the contract guvnor, which should be the      random beacon governance contract. The caller is responsible for      validating parameters.",
+        "params": {
+          "dkgResultChallengeExtraGas": "New DKG result challenge extra gas",
+          "dkgResultChallengePeriodLength": "New DKG result challenge period        length",
+          "dkgResultSubmissionTimeout": "New DKG result submission timeout",
+          "dkgSubmitterPrecedencePeriodLength": "New DKG result submitter        precedence period length",
+          "groupCreationFrequency": "New group creation frequency",
+          "groupLifetime": "New group lifetime in blocks"
+        }
+      },
+      "updateRelayEntryParameters(uint256,uint256,uint256)": {
+        "details": "Can be called only by the contract guvnor, which should be the      random beacon governance contract. The caller is responsible for      validating parameters.",
+        "params": {
+          "callbackGasLimit": "New callback gas limit",
+          "relayEntryHardTimeout": "New relay entry hard timeout",
+          "relayEntrySoftTimeout": "New relay entry submission soft timeout"
+        }
+      },
+      "updateRewardParameters(uint256,uint256,uint256,uint256)": {
+        "details": "Can be called only by the contract guvnor, which should be the      random beacon governance contract. The caller is responsible for      validating parameters.",
+        "params": {
+          "dkgMaliciousResultNotificationRewardMultiplier": "New value of the        DKG malicious result notification reward multiplier",
+          "relayEntryTimeoutNotificationRewardMultiplier": "New value of the        relay entry timeout notification reward multiplier",
+          "sortitionPoolRewardsBanDuration": "New sortition pool rewards        ban duration in seconds.",
+          "unauthorizedSigningNotificationRewardMultiplier": "New value of the        unauthorized signing notification reward multiplier"
+        }
+      },
+      "updateSlashingParameters(uint96,uint96,uint96)": {
+        "details": "Can be called only by the contract guvnor, which should be the      random beacon governance contract. The caller is responsible for      validating parameters.",
+        "params": {
+          "maliciousDkgResultSlashingAmount": "New malicious DKG result        slashing amount",
+          "relayEntrySubmissionFailureSlashingAmount": "New relay entry        submission failure amount",
+          "unauthorizedSigningSlashingAmount": "New unauthorized signing        slashing amount"
+        }
+      },
+      "withdrawIneligibleRewards(address)": {
+        "details": "Can be called only by the contract guvnor, which should be the      random beacon governance contract.",
+        "params": {
+          "recipient": "Recipient of withdrawn rewards."
+        }
+      },
+      "withdrawRewards(address)": {
+        "details": "Emits `RewardsWithdrawn` event."
+      }
+    },
+    "title": "Keep Random Beacon",
+    "version": 1
+  },
+  "userdoc": {
+    "kind": "user",
+    "methods": {
+      "approveAuthorizationDecrease(address)": {
+        "notice": "Approves the previously registered authorization decrease         request. Reverts if authorization decrease delay has not passed         yet or if the authorization decrease was not requested for the         given staking provider."
+      },
+      "approveDkgResult((uint256,bytes,uint8[],bytes,uint256[],uint32[],bytes32))": {
+        "notice": "Approves DKG result. Can be called when the challenge period for         the submitted result is finished. Considers the submitted result         as valid, bans misbehaved group members from the sortition pool         rewards, and completes the group creation by activating the         candidate group. For the first `submitterPrecedencePeriodLength`         blocks after the end of the challenge period can be called only         by the DKG result submitter. After that time, can be called by         anyone."
+      },
+      "authorizationDecreaseRequested(address,uint96,uint96)": {
+        "notice": "Used by T staking contract to inform the beacon that the         authorization decrease for the given staking provider has been         requested.         Reverts if the amount after deauthorization would be non-zero         and lower than the minimum authorization.         Reverts if another authorization decrease request is pending for         the staking provider and not enough time passed since the         original request (see `authorizationDecreaseChangePeriod`).         If the operator is not known (`registerOperator` was not called)         it lets to `approveAuthorizationDecrease` immediately. If the         operator is known (`registerOperator` was called), the operator         needs to update state of the sortition pool with a call to         `joinSortitionPool` or `updateOperatorStatus`. After the         sortition pool state is in sync, authorization decrease delay         starts.         After authorization decrease delay passes, authorization         decrease request needs to be approved with a call to         `approveAuthorizationDecrease` function.         If there is a pending authorization decrease request, it is         overwritten, but only if enough time passed since the original         request. Otherwise, the function reverts."
+      },
+      "authorizationIncreased(address,uint96,uint96)": {
+        "notice": "Used by T staking contract to inform the beacon that the         authorized stake amount for the given staking provider increased.         Reverts if the authorization amount is below the minimum.         The function is not updating the sortition pool. Sortition pool         state needs to be updated by the operator with a call to         `joinSortitionPool` or `updateOperatorStatus`."
+      },
+      "authorizationParameters()": {
+        "notice": "Returns authorization-related parameters of the beacon."
+      },
+      "authorizedRequesters(address)": {
+        "notice": "Authorized addresses that can request a relay entry."
+      },
+      "availableRewards(address)": {
+        "notice": "Returns the amount of rewards available for withdrawal for the         given staking provider. Reverts if staking provider has not         registered the operator address."
+      },
+      "challengeDkgResult((uint256,bytes,uint8[],bytes,uint256[],uint32[],bytes32))": {
+        "notice": "Challenges DKG result. If the submitted result is proved to be         invalid it reverts the DKG back to the result submission phase.         It removes a candidate group that was previously registered with         the DKG result submission."
+      },
+      "eligibleStake(address)": {
+        "notice": "Returns the current value of the staking provider's eligible         stake. Eligible stake is defined as the currently authorized         stake minus the pending authorization decrease. Eligible stake         is what is used for operator's weight in the sortition pool.         If the authorized stake minus the pending authorization decrease         is below the minimum authorization, eligible stake is 0."
+      },
+      "gasParameters()": {
+        "notice": "Returns gas-related parameters of the beacon."
+      },
+      "genesis()": {
+        "notice": "Triggers group selection if there are no active groups."
+      },
+      "getGroupCreationState()": {
+        "notice": "Check current group creation state."
+      },
+      "groupCreationParameters()": {
+        "notice": "Returns group-creation-related parameters of the beacon."
+      },
+      "hasDkgTimedOut()": {
+        "notice": "Checks if DKG timed out. The DKG timeout period includes time required         for off-chain protocol execution and time for the result publication         for all group members. After this time result cannot be submitted         and DKG can be notified about the timeout."
+      },
+      "inactivityClaimNonce(uint64)": {
+        "notice": "Stores current operator inactivity claim nonce for given group.         Each claim is made with an unique nonce which protects         against claim replay."
+      },
+      "involuntaryAuthorizationDecrease(address,uint96,uint96)": {
+        "notice": "Used by T staking contract to inform the beacon the         authorization has been decreased for the given staking provider         involuntarily, as a result of slashing.         If the operator is not known (`registerOperator` was not called)         the function does nothing. The operator was never in a sortition         pool so there is nothing to update.         If the operator is known, sortition pool is unlocked, and the         operator is in the sortition pool, the sortition pool state is         updated. If the sortition pool is locked, update needs to be         postponed. Every other staker is incentivized to call         `updateOperatorStatus` for the problematic operator to increase         their own rewards in the pool."
+      },
+      "isOperatorInPool(address)": {
+        "notice": "Returns true if the given operator is in the sortition pool.         Otherwise, returns false."
+      },
+      "isOperatorUpToDate(address)": {
+        "notice": "Checks if the operator's authorized stake is in sync with         operator's weight in the sortition pool.         If the operator is not in the sortition pool and their         authorized stake is non-zero, function returns false."
+      },
+      "joinSortitionPool()": {
+        "notice": "Lets the operator join the sortition pool. The operator address         must be known - before calling this function, it has to be         appointed by the staking provider by calling `registerOperator`.         Also, the operator must have the minimum authorization required         by the beacon. Function reverts if there is no minimum stake         authorized or if the operator is not known. If there was an         authorization decrease requested, it is activated by starting         the authorization decrease delay."
+      },
+      "minimumAuthorization()": {
+        "notice": "The minimum authorization amount required so that operator can         participate in the random beacon. This amount is required to         execute slashing for providing a malicious DKG result or when         a relay entry times out."
+      },
+      "notifyDkgTimeout()": {
+        "notice": "Notifies about DKG timeout."
+      },
+      "notifyOperatorInactivity((uint64,uint256[],bytes,uint256[]),uint256,uint32[])": {
+        "notice": "Notifies about operators who are inactive. Using this function,         a majority of the group can decide about punishing specific         group members who constantly fail doing their job. If the provided         claim is proved to be valid and signed by sufficient number         of group members, operators of members deemed as inactive are         banned for sortition pool rewards for duration specified by         `_sortitionPoolRewardsBanDuration` parameter. The sender of         the claim must be one of the claim signers. This function can be         called only for active and non-terminated groups."
+      },
+      "operatorToStakingProvider(address)": {
+        "notice": "Returns staking provider of the given operator."
+      },
+      "pendingAuthorizationDecrease(address)": {
+        "notice": "Returns the amount of stake that is pending authorization         decrease for the given staking provider. If no authorization         decrease has been requested, returns zero."
+      },
+      "registerOperator(address)": {
+        "notice": "Used by staking provider to set operator address that will         operate a node. The given staking provider can set operator         address only one time. The operator address can not be changed         and must be unique. Reverts if the operator is already set for         the staking provider or if the operator address is already in         use. Reverts if there is a pending authorization decrease for         the staking provider."
+      },
+      "relayEntryParameters()": {
+        "notice": "Returns relay-entry-related parameters of the beacon."
+      },
+      "remainingAuthorizationDecreaseDelay(address)": {
+        "notice": "Returns the remaining time in seconds that needs to pass before         the requested authorization decrease can be approved.         If the sortition pool state was not updated yet by the operator         after requesting the authorization decrease, returns         `type(uint64).max`."
+      },
+      "reportRelayEntryTimeout(uint32[])": {
+        "notice": "Reports a relay entry timeout."
+      },
+      "reportUnauthorizedSigning(bytes,uint64,uint32[])": {
+        "notice": "Reports unauthorized groups signing. Must provide a valid signature         of the sender's address as a message. Successful signature         verification means the private key has been leaked and all group         members should be punished by slashing their tokens. Group has         to be active or expired. Unauthorized signing cannot be reported         for a terminated group. In case of reporting unauthorized         signing for a terminated group, or when the signature is invalid,         function reverts."
+      },
+      "requestRelayEntry(address)": {
+        "notice": "Creates a request to generate a new relay entry, which will         include a random number (by signing the previous entry's         random number). Requester must be previously authorized by the         governance."
+      },
+      "rewardParameters()": {
+        "notice": "Returns reward-related parameters of the beacon."
+      },
+      "selectGroup()": {
+        "notice": "Selects a new group of operators. Can only be called when DKG         is in progress and the pool is locked.         At least one operator has to be registered in the pool,         otherwise the function fails reverting the transaction."
+      },
+      "setRequesterAuthorization(address,bool)": {
+        "notice": "Set authorization for requesters that can request a relay         entry."
+      },
+      "slashingParameters()": {
+        "notice": "Returns slashing-related parameters of the beacon."
+      },
+      "stakingProviderToOperator(address)": {
+        "notice": "Returns operator registered for the given staking provider."
+      },
+      "submitDkgResult((uint256,bytes,uint8[],bytes,uint256[],uint32[],bytes32))": {
+        "notice": "`\\x19Ethereum signed message:\\n` before signing, so the message to      sign is:      `\\x19Ethereum signed message:\\n${keccak256(chainID,groupPubKey,misbehaved,startBlock)}`"
+      },
+      "submitRelayEntry(bytes)": {
+        "notice": "Creates a new relay entry. Gas-optimized version that can be         called only before the soft timeout. This should be the majority         of cases."
+      },
+      "submitRelayEntry(bytes,uint32[])": {
+        "notice": "Creates a new relay entry."
+      },
+      "transferGovernance(address)": {
+        "notice": "Transfers governance of the contract to `newGovernance`."
+      },
+      "updateAuthorizationParameters(uint96,uint64,uint64)": {
+        "notice": "Updates the values of authorization parameters."
+      },
+      "updateGasParameters(uint256,uint256,uint256,uint256)": {
+        "notice": "Updates the values of gas parameters."
+      },
+      "updateGroupCreationParameters(uint256,uint256,uint256,uint256,uint256,uint256)": {
+        "notice": "Updates the values of group creation parameters."
+      },
+      "updateOperatorStatus(address)": {
+        "notice": "Updates status of the operator in the sortition pool. If there         was an authorization decrease requested, it is activated by         starting the authorization decrease delay.         Function reverts if the operator is not known."
+      },
+      "updateRelayEntryParameters(uint256,uint256,uint256)": {
+        "notice": "Updates the values of relay entry parameters."
+      },
+      "updateRewardParameters(uint256,uint256,uint256,uint256)": {
+        "notice": "Updates the values of reward parameters."
+      },
+      "updateSlashingParameters(uint96,uint96,uint96)": {
+        "notice": "Updates the values of slashing parameters."
+      },
+      "withdrawIneligibleRewards(address)": {
+        "notice": "Withdraws rewards belonging to operators marked as ineligible         for sortition pool rewards."
+      },
+      "withdrawRewards(address)": {
+        "notice": "Withdraws application rewards for the given staking provider.         Rewards are withdrawn to the staking provider's beneficiary         address set in the staking contract. Reverts if staking provider         has not registered the operator address."
+      }
+    },
+    "notice": "Keep Random Beacon contract. It lets to request a new         relay entry and validates the new relay entry provided by the         network. This contract is in charge of all other Random Beacon         activities such as group lifecycle or slashing.",
+    "version": 1
+  },
+  "storageLayout": {
+    "storage": [
+      {
+        "astId": 9746,
+        "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+        "label": "governance",
+        "offset": 0,
+        "slot": "0",
+        "type": "t_address"
+      },
+      {
+        "astId": 9750,
+        "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+        "label": "__gap",
+        "offset": 0,
+        "slot": "1",
+        "type": "t_array(t_uint256)49_storage"
+      },
+      {
+        "astId": 14627,
+        "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+        "label": "reimbursementPool",
+        "offset": 0,
+        "slot": "50",
+        "type": "t_contract(ReimbursementPool)14957"
+      },
+      {
+        "astId": 14631,
+        "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+        "label": "__gap",
+        "offset": 0,
+        "slot": "51",
+        "type": "t_array(t_uint256)49_storage"
+      },
+      {
+        "astId": 9874,
+        "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+        "label": "_callbackGasLimit",
+        "offset": 0,
+        "slot": "100",
+        "type": "t_uint256"
+      },
+      {
+        "astId": 9877,
+        "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+        "label": "_groupCreationFrequency",
+        "offset": 0,
+        "slot": "101",
+        "type": "t_uint256"
+      },
+      {
+        "astId": 9880,
+        "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+        "label": "_maliciousDkgResultSlashingAmount",
+        "offset": 0,
+        "slot": "102",
+        "type": "t_uint96"
+      },
+      {
+        "astId": 9883,
+        "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+        "label": "_unauthorizedSigningSlashingAmount",
+        "offset": 12,
+        "slot": "102",
+        "type": "t_uint96"
+      },
+      {
+        "astId": 9886,
+        "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+        "label": "_sortitionPoolRewardsBanDuration",
+        "offset": 0,
+        "slot": "103",
+        "type": "t_uint256"
+      },
+      {
+        "astId": 9889,
+        "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+        "label": "_relayEntryTimeoutNotificationRewardMultiplier",
+        "offset": 0,
+        "slot": "104",
+        "type": "t_uint256"
+      },
+      {
+        "astId": 9892,
+        "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+        "label": "_unauthorizedSigningNotificationRewardMultiplier",
+        "offset": 0,
+        "slot": "105",
+        "type": "t_uint256"
+      },
+      {
+        "astId": 9895,
+        "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+        "label": "_dkgMaliciousResultNotificationRewardMultiplier",
+        "offset": 0,
+        "slot": "106",
+        "type": "t_uint256"
+      },
+      {
+        "astId": 9898,
+        "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+        "label": "_dkgResultSubmissionGas",
+        "offset": 0,
+        "slot": "107",
+        "type": "t_uint256"
+      },
+      {
+        "astId": 9901,
+        "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+        "label": "_dkgResultApprovalGasOffset",
+        "offset": 0,
+        "slot": "108",
+        "type": "t_uint256"
+      },
+      {
+        "astId": 9904,
+        "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+        "label": "_notifyOperatorInactivityGasOffset",
+        "offset": 0,
+        "slot": "109",
+        "type": "t_uint256"
+      },
+      {
+        "astId": 9907,
+        "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+        "label": "_relayEntrySubmissionGasOffset",
+        "offset": 0,
+        "slot": "110",
+        "type": "t_uint256"
+      },
+      {
+        "astId": 9912,
+        "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+        "label": "inactivityClaimNonce",
+        "offset": 0,
+        "slot": "111",
+        "type": "t_mapping(t_uint64,t_uint256)"
+      },
+      {
+        "astId": 9917,
+        "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+        "label": "authorizedRequesters",
+        "offset": 0,
+        "slot": "112",
+        "type": "t_mapping(t_address,t_bool)"
+      },
+      {
+        "astId": 9920,
+        "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+        "label": "sortitionPool",
+        "offset": 0,
+        "slot": "113",
+        "type": "t_contract(SortitionPool)1980"
+      },
+      {
+        "astId": 9923,
+        "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+        "label": "tToken",
+        "offset": 0,
+        "slot": "114",
+        "type": "t_contract(IERC20)4111"
+      },
+      {
+        "astId": 9926,
+        "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+        "label": "staking",
+        "offset": 0,
+        "slot": "115",
+        "type": "t_contract(IStaking)9081"
+      },
+      {
+        "astId": 9929,
+        "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+        "label": "authorization",
+        "offset": 0,
+        "slot": "116",
+        "type": "t_struct(Data)16552_storage"
+      },
+      {
+        "astId": 9932,
+        "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+        "label": "dkg",
+        "offset": 0,
+        "slot": "120",
+        "type": "t_struct(Data)17482_storage"
+      },
+      {
+        "astId": 9935,
+        "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+        "label": "groups",
+        "offset": 0,
+        "slot": "131",
+        "type": "t_struct(Data)18985_storage"
+      },
+      {
+        "astId": 9938,
+        "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+        "label": "relay",
+        "offset": 0,
+        "slot": "136",
+        "type": "t_struct(Data)19879_storage"
+      },
+      {
+        "astId": 9941,
+        "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+        "label": "callback",
+        "offset": 0,
+        "slot": "140",
+        "type": "t_struct(Data)18889_storage"
+      }
+    ],
+    "types": {
+      "t_address": {
+        "encoding": "inplace",
+        "label": "address",
+        "numberOfBytes": "20"
+      },
+      "t_array(t_bytes32)dyn_storage": {
+        "base": "t_bytes32",
+        "encoding": "dynamic_array",
+        "label": "bytes32[]",
+        "numberOfBytes": "32"
+      },
+      "t_array(t_uint256)49_storage": {
+        "base": "t_uint256",
+        "encoding": "inplace",
+        "label": "uint256[49]",
+        "numberOfBytes": "1568"
+      },
+      "t_array(t_uint64)dyn_storage": {
+        "base": "t_uint64",
+        "encoding": "dynamic_array",
+        "label": "uint64[]",
+        "numberOfBytes": "32"
+      },
+      "t_bool": {
+        "encoding": "inplace",
+        "label": "bool",
+        "numberOfBytes": "1"
+      },
+      "t_bytes32": {
+        "encoding": "inplace",
+        "label": "bytes32",
+        "numberOfBytes": "32"
+      },
+      "t_bytes_storage": {
+        "encoding": "bytes",
+        "label": "bytes",
+        "numberOfBytes": "32"
+      },
+      "t_contract(BeaconDkgValidator)9741": {
+        "encoding": "inplace",
+        "label": "contract BeaconDkgValidator",
+        "numberOfBytes": "20"
+      },
+      "t_contract(IERC20)4111": {
+        "encoding": "inplace",
+        "label": "contract IERC20",
+        "numberOfBytes": "20"
+      },
+      "t_contract(IRandomBeaconConsumer)14980": {
+        "encoding": "inplace",
+        "label": "contract IRandomBeaconConsumer",
+        "numberOfBytes": "20"
+      },
+      "t_contract(IStaking)9081": {
+        "encoding": "inplace",
+        "label": "contract IStaking",
+        "numberOfBytes": "20"
+      },
+      "t_contract(ReimbursementPool)14957": {
+        "encoding": "inplace",
+        "label": "contract ReimbursementPool",
+        "numberOfBytes": "20"
+      },
+      "t_contract(SortitionPool)1980": {
+        "encoding": "inplace",
+        "label": "contract SortitionPool",
+        "numberOfBytes": "20"
+      },
+      "t_mapping(t_address,t_address)": {
+        "encoding": "mapping",
+        "key": "t_address",
+        "label": "mapping(address => address)",
+        "numberOfBytes": "32",
+        "value": "t_address"
+      },
+      "t_mapping(t_address,t_bool)": {
+        "encoding": "mapping",
+        "key": "t_address",
+        "label": "mapping(address => bool)",
+        "numberOfBytes": "32",
+        "value": "t_bool"
+      },
+      "t_mapping(t_address,t_struct(AuthorizationDecrease)16535_storage)": {
+        "encoding": "mapping",
+        "key": "t_address",
+        "label": "mapping(address => struct BeaconAuthorization.AuthorizationDecrease)",
+        "numberOfBytes": "32",
+        "value": "t_struct(AuthorizationDecrease)16535_storage"
+      },
+      "t_mapping(t_bytes32,t_struct(Group)18969_storage)": {
+        "encoding": "mapping",
+        "key": "t_bytes32",
+        "label": "mapping(bytes32 => struct Groups.Group)",
+        "numberOfBytes": "32",
+        "value": "t_struct(Group)18969_storage"
+      },
+      "t_mapping(t_uint64,t_uint256)": {
+        "encoding": "mapping",
+        "key": "t_uint64",
+        "label": "mapping(uint64 => uint256)",
+        "numberOfBytes": "32",
+        "value": "t_uint256"
+      },
+      "t_struct(AuthorizationDecrease)16535_storage": {
+        "encoding": "inplace",
+        "label": "struct BeaconAuthorization.AuthorizationDecrease",
+        "members": [
+          {
+            "astId": 16532,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "decreasingBy",
+            "offset": 0,
+            "slot": "0",
+            "type": "t_uint96"
+          },
+          {
+            "astId": 16534,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "decreasingAt",
+            "offset": 12,
+            "slot": "0",
+            "type": "t_uint64"
+          }
+        ],
+        "numberOfBytes": "32"
+      },
+      "t_struct(Data)16552_storage": {
+        "encoding": "inplace",
+        "label": "struct BeaconAuthorization.Data",
+        "members": [
+          {
+            "astId": 16538,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "parameters",
+            "offset": 0,
+            "slot": "0",
+            "type": "t_struct(Parameters)16530_storage"
+          },
+          {
+            "astId": 16542,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "stakingProviderToOperator",
+            "offset": 0,
+            "slot": "1",
+            "type": "t_mapping(t_address,t_address)"
+          },
+          {
+            "astId": 16546,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "operatorToStakingProvider",
+            "offset": 0,
+            "slot": "2",
+            "type": "t_mapping(t_address,t_address)"
+          },
+          {
+            "astId": 16551,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "pendingDecreases",
+            "offset": 0,
+            "slot": "3",
+            "type": "t_mapping(t_address,t_struct(AuthorizationDecrease)16535_storage)"
+          }
+        ],
+        "numberOfBytes": "128"
+      },
+      "t_struct(Data)17482_storage": {
+        "encoding": "inplace",
+        "label": "struct BeaconDkg.Data",
+        "members": [
+          {
+            "astId": 17465,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "sortitionPool",
+            "offset": 0,
+            "slot": "0",
+            "type": "t_contract(SortitionPool)1980"
+          },
+          {
+            "astId": 17468,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "dkgValidator",
+            "offset": 0,
+            "slot": "1",
+            "type": "t_contract(BeaconDkgValidator)9741"
+          },
+          {
+            "astId": 17471,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "parameters",
+            "offset": 0,
+            "slot": "2",
+            "type": "t_struct(Parameters)17462_storage"
+          },
+          {
+            "astId": 17473,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "startBlock",
+            "offset": 0,
+            "slot": "6",
+            "type": "t_uint256"
+          },
+          {
+            "astId": 17475,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "seed",
+            "offset": 0,
+            "slot": "7",
+            "type": "t_uint256"
+          },
+          {
+            "astId": 17477,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "resultSubmissionStartBlockOffset",
+            "offset": 0,
+            "slot": "8",
+            "type": "t_uint256"
+          },
+          {
+            "astId": 17479,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "submittedResultHash",
+            "offset": 0,
+            "slot": "9",
+            "type": "t_bytes32"
+          },
+          {
+            "astId": 17481,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "submittedResultBlock",
+            "offset": 0,
+            "slot": "10",
+            "type": "t_uint256"
+          }
+        ],
+        "numberOfBytes": "352"
+      },
+      "t_struct(Data)18889_storage": {
+        "encoding": "inplace",
+        "label": "struct Callback.Data",
+        "members": [
+          {
+            "astId": 18888,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "callbackContract",
+            "offset": 0,
+            "slot": "0",
+            "type": "t_contract(IRandomBeaconConsumer)14980"
+          }
+        ],
+        "numberOfBytes": "32"
+      },
+      "t_struct(Data)18985_storage": {
+        "encoding": "inplace",
+        "label": "struct Groups.Data",
+        "members": [
+          {
+            "astId": 18974,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "groupsData",
+            "offset": 0,
+            "slot": "0",
+            "type": "t_mapping(t_bytes32,t_struct(Group)18969_storage)"
+          },
+          {
+            "astId": 18977,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "groupsRegistry",
+            "offset": 0,
+            "slot": "1",
+            "type": "t_array(t_bytes32)dyn_storage"
+          },
+          {
+            "astId": 18980,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "activeTerminatedGroups",
+            "offset": 0,
+            "slot": "2",
+            "type": "t_array(t_uint64)dyn_storage"
+          },
+          {
+            "astId": 18982,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "expiredGroupOffset",
+            "offset": 0,
+            "slot": "3",
+            "type": "t_uint64"
+          },
+          {
+            "astId": 18984,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "groupLifetime",
+            "offset": 0,
+            "slot": "4",
+            "type": "t_uint256"
+          }
+        ],
+        "numberOfBytes": "160"
+      },
+      "t_struct(Data)19879_storage": {
+        "encoding": "inplace",
+        "label": "struct Relay.Data",
+        "members": [
+          {
+            "astId": 19863,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "requestCount",
+            "offset": 0,
+            "slot": "0",
+            "type": "t_uint64"
+          },
+          {
+            "astId": 19865,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "currentRequestID",
+            "offset": 8,
+            "slot": "0",
+            "type": "t_uint64"
+          },
+          {
+            "astId": 19867,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "currentRequestGroupID",
+            "offset": 16,
+            "slot": "0",
+            "type": "t_uint64"
+          },
+          {
+            "astId": 19869,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "currentRequestStartBlock",
+            "offset": 24,
+            "slot": "0",
+            "type": "t_uint64"
+          },
+          {
+            "astId": 19872,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "previousEntry",
+            "offset": 0,
+            "slot": "1",
+            "type": "t_struct(G1Point)14992_storage"
+          },
+          {
+            "astId": 19874,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "relayEntrySoftTimeout",
+            "offset": 0,
+            "slot": "3",
+            "type": "t_uint32"
+          },
+          {
+            "astId": 19876,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "relayEntryHardTimeout",
+            "offset": 4,
+            "slot": "3",
+            "type": "t_uint32"
+          },
+          {
+            "astId": 19878,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "relayEntrySubmissionFailureSlashingAmount",
+            "offset": 8,
+            "slot": "3",
+            "type": "t_uint96"
+          }
+        ],
+        "numberOfBytes": "128"
+      },
+      "t_struct(G1Point)14992_storage": {
+        "encoding": "inplace",
+        "label": "struct AltBn128.G1Point",
+        "members": [
+          {
+            "astId": 14989,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "x",
+            "offset": 0,
+            "slot": "0",
+            "type": "t_uint256"
+          },
+          {
+            "astId": 14991,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "y",
+            "offset": 0,
+            "slot": "1",
+            "type": "t_uint256"
+          }
+        ],
+        "numberOfBytes": "64"
+      },
+      "t_struct(Group)18969_storage": {
+        "encoding": "inplace",
+        "label": "struct Groups.Group",
+        "members": [
+          {
+            "astId": 18962,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "groupPubKey",
+            "offset": 0,
+            "slot": "0",
+            "type": "t_bytes_storage"
+          },
+          {
+            "astId": 18964,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "registrationBlockNumber",
+            "offset": 0,
+            "slot": "1",
+            "type": "t_uint256"
+          },
+          {
+            "astId": 18966,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "membersHash",
+            "offset": 0,
+            "slot": "2",
+            "type": "t_bytes32"
+          },
+          {
+            "astId": 18968,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "terminated",
+            "offset": 0,
+            "slot": "3",
+            "type": "t_bool"
+          }
+        ],
+        "numberOfBytes": "128"
+      },
+      "t_struct(Parameters)16530_storage": {
+        "encoding": "inplace",
+        "label": "struct BeaconAuthorization.Parameters",
+        "members": [
+          {
+            "astId": 16525,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "minimumAuthorization",
+            "offset": 0,
+            "slot": "0",
+            "type": "t_uint96"
+          },
+          {
+            "astId": 16527,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "authorizationDecreaseDelay",
+            "offset": 12,
+            "slot": "0",
+            "type": "t_uint64"
+          },
+          {
+            "astId": 16529,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "authorizationDecreaseChangePeriod",
+            "offset": 20,
+            "slot": "0",
+            "type": "t_uint64"
+          }
+        ],
+        "numberOfBytes": "32"
+      },
+      "t_struct(Parameters)17462_storage": {
+        "encoding": "inplace",
+        "label": "struct BeaconDkg.Parameters",
+        "members": [
+          {
+            "astId": 17455,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "resultChallengePeriodLength",
+            "offset": 0,
+            "slot": "0",
+            "type": "t_uint256"
+          },
+          {
+            "astId": 17457,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "resultChallengeExtraGas",
+            "offset": 0,
+            "slot": "1",
+            "type": "t_uint256"
+          },
+          {
+            "astId": 17459,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "resultSubmissionTimeout",
+            "offset": 0,
+            "slot": "2",
+            "type": "t_uint256"
+          },
+          {
+            "astId": 17461,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "submitterPrecedencePeriodLength",
+            "offset": 0,
+            "slot": "3",
+            "type": "t_uint256"
+          }
+        ],
+        "numberOfBytes": "128"
+      },
+      "t_uint256": {
+        "encoding": "inplace",
+        "label": "uint256",
+        "numberOfBytes": "32"
+      },
+      "t_uint32": {
+        "encoding": "inplace",
+        "label": "uint32",
+        "numberOfBytes": "4"
+      },
+      "t_uint64": {
+        "encoding": "inplace",
+        "label": "uint64",
+        "numberOfBytes": "8"
+      },
+      "t_uint96": {
+        "encoding": "inplace",
+        "label": "uint96",
+        "numberOfBytes": "12"
+      }
+    }
+  }
+}
diff --git a/src/threshold-ts/tbtc/mainnet-artifacts/RandomBeacon.json b/src/threshold-ts/tbtc/mainnet-artifacts/RandomBeacon.json
new file mode 100644
index 000000000..d27c373b3
--- /dev/null
+++ b/src/threshold-ts/tbtc/mainnet-artifacts/RandomBeacon.json
@@ -0,0 +1,3269 @@
+{
+  "address": "0x5499f54b4A1CB4816eefCf78962040461be3D80b",
+  "abi": [
+    {
+      "inputs": [
+        {
+          "internalType": "contract SortitionPool",
+          "name": "_sortitionPool",
+          "type": "address"
+        },
+        {
+          "internalType": "contract IERC20",
+          "name": "_tToken",
+          "type": "address"
+        },
+        {
+          "internalType": "contract IStaking",
+          "name": "_staking",
+          "type": "address"
+        },
+        {
+          "internalType": "contract BeaconDkgValidator",
+          "name": "_dkgValidator",
+          "type": "address"
+        },
+        {
+          "internalType": "contract ReimbursementPool",
+          "name": "_reimbursementPool",
+          "type": "address"
+        }
+      ],
+      "stateMutability": "nonpayable",
+      "type": "constructor"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        }
+      ],
+      "name": "AuthorizationDecreaseApproved",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        },
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "operator",
+          "type": "address"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint96",
+          "name": "fromAmount",
+          "type": "uint96"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint96",
+          "name": "toAmount",
+          "type": "uint96"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint64",
+          "name": "decreasingAt",
+          "type": "uint64"
+        }
+      ],
+      "name": "AuthorizationDecreaseRequested",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        },
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "operator",
+          "type": "address"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint96",
+          "name": "fromAmount",
+          "type": "uint96"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint96",
+          "name": "toAmount",
+          "type": "uint96"
+        }
+      ],
+      "name": "AuthorizationIncreased",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": false,
+          "internalType": "uint96",
+          "name": "minimumAuthorization",
+          "type": "uint96"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint64",
+          "name": "authorizationDecreaseDelay",
+          "type": "uint64"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint64",
+          "name": "authorizationDecreaseChangePeriod",
+          "type": "uint64"
+        }
+      ],
+      "name": "AuthorizationParametersUpdated",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "entry",
+          "type": "uint256"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "entrySubmittedBlock",
+          "type": "uint256"
+        }
+      ],
+      "name": "CallbackFailed",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "bytes32",
+          "name": "resultHash",
+          "type": "bytes32"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "slashingAmount",
+          "type": "uint256"
+        },
+        {
+          "indexed": false,
+          "internalType": "address",
+          "name": "maliciousSubmitter",
+          "type": "address"
+        }
+      ],
+      "name": "DkgMaliciousResultSlashed",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "bytes32",
+          "name": "resultHash",
+          "type": "bytes32"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "slashingAmount",
+          "type": "uint256"
+        },
+        {
+          "indexed": false,
+          "internalType": "address",
+          "name": "maliciousSubmitter",
+          "type": "address"
+        }
+      ],
+      "name": "DkgMaliciousResultSlashingFailed",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "bytes32",
+          "name": "resultHash",
+          "type": "bytes32"
+        },
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "approver",
+          "type": "address"
+        }
+      ],
+      "name": "DkgResultApproved",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "bytes32",
+          "name": "resultHash",
+          "type": "bytes32"
+        },
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "challenger",
+          "type": "address"
+        },
+        {
+          "indexed": false,
+          "internalType": "string",
+          "name": "reason",
+          "type": "string"
+        }
+      ],
+      "name": "DkgResultChallenged",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "bytes32",
+          "name": "resultHash",
+          "type": "bytes32"
+        },
+        {
+          "indexed": true,
+          "internalType": "uint256",
+          "name": "seed",
+          "type": "uint256"
+        },
+        {
+          "components": [
+            {
+              "internalType": "uint256",
+              "name": "submitterMemberIndex",
+              "type": "uint256"
+            },
+            {
+              "internalType": "bytes",
+              "name": "groupPubKey",
+              "type": "bytes"
+            },
+            {
+              "internalType": "uint8[]",
+              "name": "misbehavedMembersIndices",
+              "type": "uint8[]"
+            },
+            {
+              "internalType": "bytes",
+              "name": "signatures",
+              "type": "bytes"
+            },
+            {
+              "internalType": "uint256[]",
+              "name": "signingMembersIndices",
+              "type": "uint256[]"
+            },
+            {
+              "internalType": "uint32[]",
+              "name": "members",
+              "type": "uint32[]"
+            },
+            {
+              "internalType": "bytes32",
+              "name": "membersHash",
+              "type": "bytes32"
+            }
+          ],
+          "indexed": false,
+          "internalType": "struct BeaconDkg.Result",
+          "name": "result",
+          "type": "tuple"
+        }
+      ],
+      "name": "DkgResultSubmitted",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [],
+      "name": "DkgSeedTimedOut",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "uint256",
+          "name": "seed",
+          "type": "uint256"
+        }
+      ],
+      "name": "DkgStarted",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [],
+      "name": "DkgStateLocked",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [],
+      "name": "DkgTimedOut",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "dkgResultSubmissionGas",
+          "type": "uint256"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "dkgResultApprovalGasOffset",
+          "type": "uint256"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "notifyOperatorInactivityGasOffset",
+          "type": "uint256"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "relayEntrySubmissionGasOffset",
+          "type": "uint256"
+        }
+      ],
+      "name": "GasParametersUpdated",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": false,
+          "internalType": "address",
+          "name": "oldGovernance",
+          "type": "address"
+        },
+        {
+          "indexed": false,
+          "internalType": "address",
+          "name": "newGovernance",
+          "type": "address"
+        }
+      ],
+      "name": "GovernanceTransferred",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "groupCreationFrequency",
+          "type": "uint256"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "groupLifetime",
+          "type": "uint256"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "dkgResultChallengePeriodLength",
+          "type": "uint256"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "dkgResultChallengeExtraGas",
+          "type": "uint256"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "dkgResultSubmissionTimeout",
+          "type": "uint256"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "dkgResultSubmitterPrecedencePeriodLength",
+          "type": "uint256"
+        }
+      ],
+      "name": "GroupCreationParametersUpdated",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "uint64",
+          "name": "groupId",
+          "type": "uint64"
+        },
+        {
+          "indexed": true,
+          "internalType": "bytes",
+          "name": "groupPubKey",
+          "type": "bytes"
+        }
+      ],
+      "name": "GroupRegistered",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "uint64",
+          "name": "groupId",
+          "type": "uint64"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "nonce",
+          "type": "uint256"
+        },
+        {
+          "indexed": false,
+          "internalType": "address",
+          "name": "notifier",
+          "type": "address"
+        }
+      ],
+      "name": "InactivityClaimed",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        },
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "operator",
+          "type": "address"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint96",
+          "name": "fromAmount",
+          "type": "uint96"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint96",
+          "name": "toAmount",
+          "type": "uint96"
+        }
+      ],
+      "name": "InvoluntaryAuthorizationDecreaseFailed",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        },
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "operator",
+          "type": "address"
+        }
+      ],
+      "name": "OperatorJoinedSortitionPool",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        },
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "operator",
+          "type": "address"
+        }
+      ],
+      "name": "OperatorRegistered",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        },
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "operator",
+          "type": "address"
+        }
+      ],
+      "name": "OperatorStatusUpdated",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": false,
+          "internalType": "address",
+          "name": "newReimbursementPool",
+          "type": "address"
+        }
+      ],
+      "name": "ReimbursementPoolUpdated",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "uint256",
+          "name": "requestId",
+          "type": "uint256"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "slashingAmount",
+          "type": "uint256"
+        },
+        {
+          "indexed": false,
+          "internalType": "address[]",
+          "name": "groupMembers",
+          "type": "address[]"
+        }
+      ],
+      "name": "RelayEntryDelaySlashed",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "uint256",
+          "name": "requestId",
+          "type": "uint256"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "slashingAmount",
+          "type": "uint256"
+        },
+        {
+          "indexed": false,
+          "internalType": "address[]",
+          "name": "groupMembers",
+          "type": "address[]"
+        }
+      ],
+      "name": "RelayEntryDelaySlashingFailed",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "relayEntrySoftTimeout",
+          "type": "uint256"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "relayEntryHardTimeout",
+          "type": "uint256"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "callbackGasLimit",
+          "type": "uint256"
+        }
+      ],
+      "name": "RelayEntryParametersUpdated",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "uint256",
+          "name": "requestId",
+          "type": "uint256"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint64",
+          "name": "groupId",
+          "type": "uint64"
+        },
+        {
+          "indexed": false,
+          "internalType": "bytes",
+          "name": "previousEntry",
+          "type": "bytes"
+        }
+      ],
+      "name": "RelayEntryRequested",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "uint256",
+          "name": "requestId",
+          "type": "uint256"
+        },
+        {
+          "indexed": false,
+          "internalType": "address",
+          "name": "submitter",
+          "type": "address"
+        },
+        {
+          "indexed": false,
+          "internalType": "bytes",
+          "name": "entry",
+          "type": "bytes"
+        }
+      ],
+      "name": "RelayEntrySubmitted",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "uint256",
+          "name": "requestId",
+          "type": "uint256"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint64",
+          "name": "terminatedGroupId",
+          "type": "uint64"
+        }
+      ],
+      "name": "RelayEntryTimedOut",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "uint256",
+          "name": "requestId",
+          "type": "uint256"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "slashingAmount",
+          "type": "uint256"
+        },
+        {
+          "indexed": false,
+          "internalType": "address[]",
+          "name": "groupMembers",
+          "type": "address[]"
+        }
+      ],
+      "name": "RelayEntryTimeoutSlashed",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "uint256",
+          "name": "requestId",
+          "type": "uint256"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "slashingAmount",
+          "type": "uint256"
+        },
+        {
+          "indexed": false,
+          "internalType": "address[]",
+          "name": "groupMembers",
+          "type": "address[]"
+        }
+      ],
+      "name": "RelayEntryTimeoutSlashingFailed",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "requester",
+          "type": "address"
+        },
+        {
+          "indexed": false,
+          "internalType": "bool",
+          "name": "isAuthorized",
+          "type": "bool"
+        }
+      ],
+      "name": "RequesterAuthorizationUpdated",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "sortitionPoolRewardsBanDuration",
+          "type": "uint256"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "relayEntryTimeoutNotificationRewardMultiplier",
+          "type": "uint256"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "unauthorizedSigningNotificationRewardMultiplier",
+          "type": "uint256"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "dkgMaliciousResultNotificationRewardMultiplier",
+          "type": "uint256"
+        }
+      ],
+      "name": "RewardParametersUpdated",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint96",
+          "name": "amount",
+          "type": "uint96"
+        }
+      ],
+      "name": "RewardsWithdrawn",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "relayEntrySubmissionFailureSlashingAmount",
+          "type": "uint256"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "maliciousDkgResultSlashingAmount",
+          "type": "uint256"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "unauthorizedSigningSlashingAmount",
+          "type": "uint256"
+        }
+      ],
+      "name": "SlashingParametersUpdated",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "uint64",
+          "name": "groupId",
+          "type": "uint64"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "unauthorizedSigningSlashingAmount",
+          "type": "uint256"
+        },
+        {
+          "indexed": false,
+          "internalType": "address[]",
+          "name": "groupMembers",
+          "type": "address[]"
+        }
+      ],
+      "name": "UnauthorizedSigningSlashed",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "uint64",
+          "name": "groupId",
+          "type": "uint64"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "unauthorizedSigningSlashingAmount",
+          "type": "uint256"
+        },
+        {
+          "indexed": false,
+          "internalType": "address[]",
+          "name": "groupMembers",
+          "type": "address[]"
+        }
+      ],
+      "name": "UnauthorizedSigningSlashingFailed",
+      "type": "event"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        }
+      ],
+      "name": "approveAuthorizationDecrease",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "components": [
+            {
+              "internalType": "uint256",
+              "name": "submitterMemberIndex",
+              "type": "uint256"
+            },
+            {
+              "internalType": "bytes",
+              "name": "groupPubKey",
+              "type": "bytes"
+            },
+            {
+              "internalType": "uint8[]",
+              "name": "misbehavedMembersIndices",
+              "type": "uint8[]"
+            },
+            {
+              "internalType": "bytes",
+              "name": "signatures",
+              "type": "bytes"
+            },
+            {
+              "internalType": "uint256[]",
+              "name": "signingMembersIndices",
+              "type": "uint256[]"
+            },
+            {
+              "internalType": "uint32[]",
+              "name": "members",
+              "type": "uint32[]"
+            },
+            {
+              "internalType": "bytes32",
+              "name": "membersHash",
+              "type": "bytes32"
+            }
+          ],
+          "internalType": "struct BeaconDkg.Result",
+          "name": "dkgResult",
+          "type": "tuple"
+        }
+      ],
+      "name": "approveDkgResult",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        },
+        {
+          "internalType": "uint96",
+          "name": "fromAmount",
+          "type": "uint96"
+        },
+        {
+          "internalType": "uint96",
+          "name": "toAmount",
+          "type": "uint96"
+        }
+      ],
+      "name": "authorizationDecreaseRequested",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        },
+        {
+          "internalType": "uint96",
+          "name": "fromAmount",
+          "type": "uint96"
+        },
+        {
+          "internalType": "uint96",
+          "name": "toAmount",
+          "type": "uint96"
+        }
+      ],
+      "name": "authorizationIncreased",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "authorizationParameters",
+      "outputs": [
+        {
+          "internalType": "uint96",
+          "name": "minimumAuthorization",
+          "type": "uint96"
+        },
+        {
+          "internalType": "uint64",
+          "name": "authorizationDecreaseDelay",
+          "type": "uint64"
+        },
+        {
+          "internalType": "uint64",
+          "name": "authorizationDecreaseChangePeriod",
+          "type": "uint64"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "",
+          "type": "address"
+        }
+      ],
+      "name": "authorizedRequesters",
+      "outputs": [
+        {
+          "internalType": "bool",
+          "name": "",
+          "type": "bool"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        }
+      ],
+      "name": "availableRewards",
+      "outputs": [
+        {
+          "internalType": "uint96",
+          "name": "",
+          "type": "uint96"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "components": [
+            {
+              "internalType": "uint256",
+              "name": "submitterMemberIndex",
+              "type": "uint256"
+            },
+            {
+              "internalType": "bytes",
+              "name": "groupPubKey",
+              "type": "bytes"
+            },
+            {
+              "internalType": "uint8[]",
+              "name": "misbehavedMembersIndices",
+              "type": "uint8[]"
+            },
+            {
+              "internalType": "bytes",
+              "name": "signatures",
+              "type": "bytes"
+            },
+            {
+              "internalType": "uint256[]",
+              "name": "signingMembersIndices",
+              "type": "uint256[]"
+            },
+            {
+              "internalType": "uint32[]",
+              "name": "members",
+              "type": "uint32[]"
+            },
+            {
+              "internalType": "bytes32",
+              "name": "membersHash",
+              "type": "bytes32"
+            }
+          ],
+          "internalType": "struct BeaconDkg.Result",
+          "name": "dkgResult",
+          "type": "tuple"
+        }
+      ],
+      "name": "challengeDkgResult",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        }
+      ],
+      "name": "eligibleStake",
+      "outputs": [
+        {
+          "internalType": "uint96",
+          "name": "",
+          "type": "uint96"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "gasParameters",
+      "outputs": [
+        {
+          "internalType": "uint256",
+          "name": "dkgResultSubmissionGas",
+          "type": "uint256"
+        },
+        {
+          "internalType": "uint256",
+          "name": "dkgResultApprovalGasOffset",
+          "type": "uint256"
+        },
+        {
+          "internalType": "uint256",
+          "name": "notifyOperatorInactivityGasOffset",
+          "type": "uint256"
+        },
+        {
+          "internalType": "uint256",
+          "name": "relayEntrySubmissionGasOffset",
+          "type": "uint256"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "genesis",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "uint64",
+          "name": "groupId",
+          "type": "uint64"
+        }
+      ],
+      "name": "getGroup",
+      "outputs": [
+        {
+          "components": [
+            {
+              "internalType": "bytes",
+              "name": "groupPubKey",
+              "type": "bytes"
+            },
+            {
+              "internalType": "uint256",
+              "name": "registrationBlockNumber",
+              "type": "uint256"
+            },
+            {
+              "internalType": "bytes32",
+              "name": "membersHash",
+              "type": "bytes32"
+            },
+            {
+              "internalType": "bool",
+              "name": "terminated",
+              "type": "bool"
+            }
+          ],
+          "internalType": "struct Groups.Group",
+          "name": "",
+          "type": "tuple"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "bytes",
+          "name": "groupPubKey",
+          "type": "bytes"
+        }
+      ],
+      "name": "getGroup",
+      "outputs": [
+        {
+          "components": [
+            {
+              "internalType": "bytes",
+              "name": "groupPubKey",
+              "type": "bytes"
+            },
+            {
+              "internalType": "uint256",
+              "name": "registrationBlockNumber",
+              "type": "uint256"
+            },
+            {
+              "internalType": "bytes32",
+              "name": "membersHash",
+              "type": "bytes32"
+            },
+            {
+              "internalType": "bool",
+              "name": "terminated",
+              "type": "bool"
+            }
+          ],
+          "internalType": "struct Groups.Group",
+          "name": "",
+          "type": "tuple"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "getGroupCreationState",
+      "outputs": [
+        {
+          "internalType": "enum BeaconDkg.State",
+          "name": "",
+          "type": "uint8"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "getGroupsRegistry",
+      "outputs": [
+        {
+          "internalType": "bytes32[]",
+          "name": "",
+          "type": "bytes32[]"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "governance",
+      "outputs": [
+        {
+          "internalType": "address",
+          "name": "",
+          "type": "address"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "groupCreationParameters",
+      "outputs": [
+        {
+          "internalType": "uint256",
+          "name": "groupCreationFrequency",
+          "type": "uint256"
+        },
+        {
+          "internalType": "uint256",
+          "name": "groupLifetime",
+          "type": "uint256"
+        },
+        {
+          "internalType": "uint256",
+          "name": "dkgResultChallengePeriodLength",
+          "type": "uint256"
+        },
+        {
+          "internalType": "uint256",
+          "name": "dkgResultChallengeExtraGas",
+          "type": "uint256"
+        },
+        {
+          "internalType": "uint256",
+          "name": "dkgResultSubmissionTimeout",
+          "type": "uint256"
+        },
+        {
+          "internalType": "uint256",
+          "name": "dkgSubmitterPrecedencePeriodLength",
+          "type": "uint256"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "hasDkgTimedOut",
+      "outputs": [
+        {
+          "internalType": "bool",
+          "name": "",
+          "type": "bool"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "uint64",
+          "name": "",
+          "type": "uint64"
+        }
+      ],
+      "name": "inactivityClaimNonce",
+      "outputs": [
+        {
+          "internalType": "uint256",
+          "name": "",
+          "type": "uint256"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        },
+        {
+          "internalType": "uint96",
+          "name": "fromAmount",
+          "type": "uint96"
+        },
+        {
+          "internalType": "uint96",
+          "name": "toAmount",
+          "type": "uint96"
+        }
+      ],
+      "name": "involuntaryAuthorizationDecrease",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "operator",
+          "type": "address"
+        }
+      ],
+      "name": "isOperatorInPool",
+      "outputs": [
+        {
+          "internalType": "bool",
+          "name": "",
+          "type": "bool"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "operator",
+          "type": "address"
+        }
+      ],
+      "name": "isOperatorUpToDate",
+      "outputs": [
+        {
+          "internalType": "bool",
+          "name": "",
+          "type": "bool"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "isRelayRequestInProgress",
+      "outputs": [
+        {
+          "internalType": "bool",
+          "name": "",
+          "type": "bool"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "joinSortitionPool",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "minimumAuthorization",
+      "outputs": [
+        {
+          "internalType": "uint96",
+          "name": "",
+          "type": "uint96"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "notifyDkgTimeout",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "components": [
+            {
+              "internalType": "uint64",
+              "name": "groupId",
+              "type": "uint64"
+            },
+            {
+              "internalType": "uint256[]",
+              "name": "inactiveMembersIndices",
+              "type": "uint256[]"
+            },
+            {
+              "internalType": "bytes",
+              "name": "signatures",
+              "type": "bytes"
+            },
+            {
+              "internalType": "uint256[]",
+              "name": "signingMembersIndices",
+              "type": "uint256[]"
+            }
+          ],
+          "internalType": "struct BeaconInactivity.Claim",
+          "name": "claim",
+          "type": "tuple"
+        },
+        {
+          "internalType": "uint256",
+          "name": "nonce",
+          "type": "uint256"
+        },
+        {
+          "internalType": "uint32[]",
+          "name": "groupMembers",
+          "type": "uint32[]"
+        }
+      ],
+      "name": "notifyOperatorInactivity",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "operator",
+          "type": "address"
+        }
+      ],
+      "name": "operatorToStakingProvider",
+      "outputs": [
+        {
+          "internalType": "address",
+          "name": "",
+          "type": "address"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        }
+      ],
+      "name": "pendingAuthorizationDecrease",
+      "outputs": [
+        {
+          "internalType": "uint96",
+          "name": "",
+          "type": "uint96"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "operator",
+          "type": "address"
+        }
+      ],
+      "name": "registerOperator",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "reimbursementPool",
+      "outputs": [
+        {
+          "internalType": "contract ReimbursementPool",
+          "name": "",
+          "type": "address"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "relayEntryParameters",
+      "outputs": [
+        {
+          "internalType": "uint256",
+          "name": "relayEntrySoftTimeout",
+          "type": "uint256"
+        },
+        {
+          "internalType": "uint256",
+          "name": "relayEntryHardTimeout",
+          "type": "uint256"
+        },
+        {
+          "internalType": "uint256",
+          "name": "callbackGasLimit",
+          "type": "uint256"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        }
+      ],
+      "name": "remainingAuthorizationDecreaseDelay",
+      "outputs": [
+        {
+          "internalType": "uint64",
+          "name": "",
+          "type": "uint64"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "uint32[]",
+          "name": "groupMembers",
+          "type": "uint32[]"
+        }
+      ],
+      "name": "reportRelayEntryTimeout",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "bytes",
+          "name": "signedMsgSender",
+          "type": "bytes"
+        },
+        {
+          "internalType": "uint64",
+          "name": "groupId",
+          "type": "uint64"
+        },
+        {
+          "internalType": "uint32[]",
+          "name": "groupMembers",
+          "type": "uint32[]"
+        }
+      ],
+      "name": "reportUnauthorizedSigning",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "contract IRandomBeaconConsumer",
+          "name": "callbackContract",
+          "type": "address"
+        }
+      ],
+      "name": "requestRelayEntry",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "rewardParameters",
+      "outputs": [
+        {
+          "internalType": "uint256",
+          "name": "sortitionPoolRewardsBanDuration",
+          "type": "uint256"
+        },
+        {
+          "internalType": "uint256",
+          "name": "relayEntryTimeoutNotificationRewardMultiplier",
+          "type": "uint256"
+        },
+        {
+          "internalType": "uint256",
+          "name": "unauthorizedSigningNotificationRewardMultiplier",
+          "type": "uint256"
+        },
+        {
+          "internalType": "uint256",
+          "name": "dkgMaliciousResultNotificationRewardMultiplier",
+          "type": "uint256"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "selectGroup",
+      "outputs": [
+        {
+          "internalType": "uint32[]",
+          "name": "",
+          "type": "uint32[]"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "requester",
+          "type": "address"
+        },
+        {
+          "internalType": "bool",
+          "name": "isAuthorized",
+          "type": "bool"
+        }
+      ],
+      "name": "setRequesterAuthorization",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "slashingParameters",
+      "outputs": [
+        {
+          "internalType": "uint96",
+          "name": "relayEntrySubmissionFailureSlashingAmount",
+          "type": "uint96"
+        },
+        {
+          "internalType": "uint96",
+          "name": "maliciousDkgResultSlashingAmount",
+          "type": "uint96"
+        },
+        {
+          "internalType": "uint96",
+          "name": "unauthorizedSigningSlashingAmount",
+          "type": "uint96"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "sortitionPool",
+      "outputs": [
+        {
+          "internalType": "contract SortitionPool",
+          "name": "",
+          "type": "address"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "staking",
+      "outputs": [
+        {
+          "internalType": "contract IStaking",
+          "name": "",
+          "type": "address"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        }
+      ],
+      "name": "stakingProviderToOperator",
+      "outputs": [
+        {
+          "internalType": "address",
+          "name": "",
+          "type": "address"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "components": [
+            {
+              "internalType": "uint256",
+              "name": "submitterMemberIndex",
+              "type": "uint256"
+            },
+            {
+              "internalType": "bytes",
+              "name": "groupPubKey",
+              "type": "bytes"
+            },
+            {
+              "internalType": "uint8[]",
+              "name": "misbehavedMembersIndices",
+              "type": "uint8[]"
+            },
+            {
+              "internalType": "bytes",
+              "name": "signatures",
+              "type": "bytes"
+            },
+            {
+              "internalType": "uint256[]",
+              "name": "signingMembersIndices",
+              "type": "uint256[]"
+            },
+            {
+              "internalType": "uint32[]",
+              "name": "members",
+              "type": "uint32[]"
+            },
+            {
+              "internalType": "bytes32",
+              "name": "membersHash",
+              "type": "bytes32"
+            }
+          ],
+          "internalType": "struct BeaconDkg.Result",
+          "name": "dkgResult",
+          "type": "tuple"
+        }
+      ],
+      "name": "submitDkgResult",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "bytes",
+          "name": "entry",
+          "type": "bytes"
+        },
+        {
+          "internalType": "uint32[]",
+          "name": "groupMembers",
+          "type": "uint32[]"
+        }
+      ],
+      "name": "submitRelayEntry",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "bytes",
+          "name": "entry",
+          "type": "bytes"
+        }
+      ],
+      "name": "submitRelayEntry",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "tToken",
+      "outputs": [
+        {
+          "internalType": "contract IERC20",
+          "name": "",
+          "type": "address"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "newGovernance",
+          "type": "address"
+        }
+      ],
+      "name": "transferGovernance",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "uint96",
+          "name": "_minimumAuthorization",
+          "type": "uint96"
+        },
+        {
+          "internalType": "uint64",
+          "name": "_authorizationDecreaseDelay",
+          "type": "uint64"
+        },
+        {
+          "internalType": "uint64",
+          "name": "_authorizationDecreaseChangePeriod",
+          "type": "uint64"
+        }
+      ],
+      "name": "updateAuthorizationParameters",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "uint256",
+          "name": "dkgResultSubmissionGas",
+          "type": "uint256"
+        },
+        {
+          "internalType": "uint256",
+          "name": "dkgResultApprovalGasOffset",
+          "type": "uint256"
+        },
+        {
+          "internalType": "uint256",
+          "name": "notifyOperatorInactivityGasOffset",
+          "type": "uint256"
+        },
+        {
+          "internalType": "uint256",
+          "name": "relayEntrySubmissionGasOffset",
+          "type": "uint256"
+        }
+      ],
+      "name": "updateGasParameters",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "uint256",
+          "name": "groupCreationFrequency",
+          "type": "uint256"
+        },
+        {
+          "internalType": "uint256",
+          "name": "groupLifetime",
+          "type": "uint256"
+        },
+        {
+          "internalType": "uint256",
+          "name": "dkgResultChallengePeriodLength",
+          "type": "uint256"
+        },
+        {
+          "internalType": "uint256",
+          "name": "dkgResultChallengeExtraGas",
+          "type": "uint256"
+        },
+        {
+          "internalType": "uint256",
+          "name": "dkgResultSubmissionTimeout",
+          "type": "uint256"
+        },
+        {
+          "internalType": "uint256",
+          "name": "dkgSubmitterPrecedencePeriodLength",
+          "type": "uint256"
+        }
+      ],
+      "name": "updateGroupCreationParameters",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "operator",
+          "type": "address"
+        }
+      ],
+      "name": "updateOperatorStatus",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "contract ReimbursementPool",
+          "name": "_reimbursementPool",
+          "type": "address"
+        }
+      ],
+      "name": "updateReimbursementPool",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "uint256",
+          "name": "relayEntrySoftTimeout",
+          "type": "uint256"
+        },
+        {
+          "internalType": "uint256",
+          "name": "relayEntryHardTimeout",
+          "type": "uint256"
+        },
+        {
+          "internalType": "uint256",
+          "name": "callbackGasLimit",
+          "type": "uint256"
+        }
+      ],
+      "name": "updateRelayEntryParameters",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "uint256",
+          "name": "sortitionPoolRewardsBanDuration",
+          "type": "uint256"
+        },
+        {
+          "internalType": "uint256",
+          "name": "relayEntryTimeoutNotificationRewardMultiplier",
+          "type": "uint256"
+        },
+        {
+          "internalType": "uint256",
+          "name": "unauthorizedSigningNotificationRewardMultiplier",
+          "type": "uint256"
+        },
+        {
+          "internalType": "uint256",
+          "name": "dkgMaliciousResultNotificationRewardMultiplier",
+          "type": "uint256"
+        }
+      ],
+      "name": "updateRewardParameters",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "uint96",
+          "name": "relayEntrySubmissionFailureSlashingAmount",
+          "type": "uint96"
+        },
+        {
+          "internalType": "uint96",
+          "name": "maliciousDkgResultSlashingAmount",
+          "type": "uint96"
+        },
+        {
+          "internalType": "uint96",
+          "name": "unauthorizedSigningSlashingAmount",
+          "type": "uint96"
+        }
+      ],
+      "name": "updateSlashingParameters",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "recipient",
+          "type": "address"
+        }
+      ],
+      "name": "withdrawIneligibleRewards",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        }
+      ],
+      "name": "withdrawRewards",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    }
+  ],
+  "transactionHash": "0x0b9ff095d08d6428936ff1aa63cf69c05bfc09756c986288c9c5b1e48fc9e80f",
+  "receipt": {
+    "to": null,
+    "from": "0x123694886DBf5Ac94DDA07135349534536D14cAf",
+    "contractAddress": "0x5499f54b4A1CB4816eefCf78962040461be3D80b",
+    "transactionIndex": 134,
+    "gasUsed": "5967896",
+    "logsBloom": "0x00000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000800000000000000000000000000002000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000",
+    "blockHash": "0x2a91baafb0d14ee461a2d80f4a45bd592d15716538c3509c470ae00676be2213",
+    "transactionHash": "0x0b9ff095d08d6428936ff1aa63cf69c05bfc09756c986288c9c5b1e48fc9e80f",
+    "logs": [
+      {
+        "transactionIndex": 134,
+        "blockNumber": 15638933,
+        "transactionHash": "0x0b9ff095d08d6428936ff1aa63cf69c05bfc09756c986288c9c5b1e48fc9e80f",
+        "address": "0x5499f54b4A1CB4816eefCf78962040461be3D80b",
+        "topics": [
+          "0x5f56bee8cffbe9a78652a74a60705edede02af10b0bbb888ca44b79a0d42ce80"
+        ],
+        "data": "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000123694886dbf5ac94dda07135349534536d14caf",
+        "logIndex": 219,
+        "blockHash": "0x2a91baafb0d14ee461a2d80f4a45bd592d15716538c3509c470ae00676be2213"
+      }
+    ],
+    "blockNumber": 15638933,
+    "cumulativeGasUsed": "18819477",
+    "status": 1,
+    "byzantium": true
+  },
+  "args": [
+    "0x4e4cBA3779d56386ED43631b4dCD6d8EacEcBCF6",
+    "0xCdF7028ceAB81fA0C6971208e83fa7872994beE5",
+    "0x01B67b1194C75264d06F808A921228a95C765dd7",
+    "0x4EDC83c5C5B0C41A594371485554B95280653f94",
+    "0x8adF3f35dBE4026112bCFc078872bcb967732Ea8"
+  ],
+  "numDeployments": 1,
+  "solcInputHash": "315dd8aa56418c14cbdc8d65adaa494b",
+  "libraries": {
+    "BLS": "0x6552059B6eFc6aA4AE3ea45f28ED4D92acE020cD",
+    "BeaconAuthorization": "0x632c2d58Ad870fbd4569da0A4E82dDf4B56E83E8",
+    "BeaconDkg": "0x024a697788918007592572f7CD020df2bC2ABD84",
+    "BeaconInactivity": "0x67A26f2ebDB2448605936Fe9a5f496cDA7941Ec0"
+  },
+  "devdoc": {
+    "details": "Should be owned by the governance contract controlling Random Beacon      parameters.",
+    "kind": "dev",
+    "methods": {
+      "approveDkgResult((uint256,bytes,uint8[],bytes,uint256[],uint32[],bytes32))": {
+        "params": {
+          "dkgResult": "Result to approve. Must match the submitted result        stored during `submitDkgResult`."
+        }
+      },
+      "authorizationDecreaseRequested(address,uint96,uint96)": {
+        "details": "Can only be called by T staking contract."
+      },
+      "authorizationIncreased(address,uint96,uint96)": {
+        "details": "Can only be called by T staking contract."
+      },
+      "authorizationParameters()": {
+        "details": "The minimum authorization is also returned by `minimumAuthorization()`      function, as a requirement of `IApplication` interface.",
+        "returns": {
+          "authorizationDecreaseChangePeriod": "Authorization decrease change        period in seconds. It is the time, before authorization decrease        delay end, during which the pending authorization decrease        request can be overwritten.        If set to 0, pending authorization decrease request can not be        overwritten until the entire `authorizationDecreaseDelay` ends.        If set to value equal `authorizationDecreaseDelay`, request can        always be overwritten.",
+          "authorizationDecreaseDelay": "Delay in seconds that needs to pass         between the time authorization decrease is requested and the         time that request gets approved. Protects against free-riders         earning rewards and not being active in the network.",
+          "minimumAuthorization": "The minimum authorization amount required         so that operator can participate in the random beacon. This         amount is required to execute slashing for providing a malicious         DKG result or when a relay entry times out."
+        }
+      },
+      "challengeDkgResult((uint256,bytes,uint8[],bytes,uint256[],uint32[],bytes32))": {
+        "details": "Due to EIP-150 1/64 of the gas is not forwarded to the call, and      will be kept to execute the remaining operations in the function      after the call inside the try-catch. To eliminate a class of      attacks related to the gas limit manipulation, this function      requires an extra amount of gas to be left at the end of the      execution.",
+        "params": {
+          "dkgResult": "Result to challenge. Must match the submitted result        stored during `submitDkgResult`."
+        }
+      },
+      "constructor": {
+        "details": "Assigns initial values to parameters to make the beacon work      safely. These parameters are just proposed defaults and they might      be updated with `update*` functions after the contract deployment      and before transferring the ownership to the governance contract."
+      },
+      "gasParameters()": {
+        "returns": {
+          "dkgResultApprovalGasOffset": "Gas that is meant to balance the DKG         result approval's overall cost.",
+          "dkgResultSubmissionGas": "Calculated gas cost for submitting a DKG         result. This will be refunded as part of the DKG approval         process.",
+          "notifyOperatorInactivityGasOffset": "Gas that is meant to balance         the operator inactivity notification cost.",
+          "relayEntrySubmissionGasOffset": "Gas that is meant to balance the         relay entry submission cost."
+        }
+      },
+      "groupCreationParameters()": {
+        "returns": {
+          "dkgResultChallengeExtraGas": "The extra gas required to be left at         the end of the challenge DKG result transaction.",
+          "dkgResultChallengePeriodLength": "The number of blocks for which         a DKG result can be challenged. Anyone can challenge DKG result         for a certain number of blocks before the result is fully         accepted and the group registered in the pool of active groups.         If the challenge gets accepted, all operators who signed the         malicious result get slashed for and the notifier gets rewarded.",
+          "dkgResultSubmissionTimeout": "Timeout in blocks for a group to         submit the DKG result. All members are eligible to submit the         DKG result. If `dkgResultSubmissionTimeout` passes without the         DKG result submitted, DKG is considered as timed out and no DKG         result for this group creation can be submitted anymore.",
+          "dkgSubmitterPrecedencePeriodLength": "Time during the DKG result         approval stage when the submitter of the DKG result takes the         precedence to approve the DKG result. After this time passes         anyone can approve the DKG result.",
+          "groupCreationFrequency": "The frequency of a new group creation.         Groups are created with a fixed frequency of relay requests.",
+          "groupLifetime": "Group lifetime in blocks. When a group reached its         lifetime, it is no longer selected for new relay requests but         may still be responsible for submitting relay entry if relay         request assigned to that group is still pending."
+        }
+      },
+      "hasDkgTimedOut()": {
+        "returns": {
+          "_0": "True if DKG timed out, false otherwise."
+        }
+      },
+      "isRelayRequestInProgress()": {
+        "returns": {
+          "_0": "Flag indicating whether a relay entry request is currently         in progress."
+        }
+      },
+      "notifyOperatorInactivity((uint64,uint256[],bytes,uint256[]),uint256,uint32[])": {
+        "params": {
+          "claim": "Operator inactivity claim.",
+          "groupMembers": "Identifiers of group members.",
+          "nonce": "Current inactivity claim nonce for the given group. Must        be the same as the stored one."
+        }
+      },
+      "relayEntryParameters()": {
+        "returns": {
+          "callbackGasLimit": "Relay entry callback gas limit. This is the gas         limit with which callback function provided in the relay request         transaction is executed. The callback is executed with a new         relay entry value in the same transaction the relay entry is         submitted.",
+          "relayEntryHardTimeout": "Hard timeout in blocks for a group to         submit the relay entry. After the soft timeout passes without         relay entry submitted, all group members start getting slashed.         The slashing amount increases linearly until the group submits         the relay entry or until `relayEntryHardTimeout` is reached.         When the hard timeout is reached, each group member will get         slashed for `_relayEntrySubmissionFailureSlashingAmount`.",
+          "relayEntrySoftTimeout": "Soft timeout in blocks for a group to         submit the relay entry. If the soft timeout is reached for         submitting the relay entry, the slashing starts."
+        }
+      },
+      "reportRelayEntryTimeout(uint32[])": {
+        "params": {
+          "groupMembers": "Identifiers of group members."
+        }
+      },
+      "reportUnauthorizedSigning(bytes,uint64,uint32[])": {
+        "params": {
+          "groupId": "Group that is being reported for leaking a private key.",
+          "groupMembers": "Identifiers of group members.",
+          "signedMsgSender": "Signature of the sender's address as a message."
+        }
+      },
+      "requestRelayEntry(address)": {
+        "params": {
+          "callbackContract": "Beacon consumer callback contract."
+        }
+      },
+      "rewardParameters()": {
+        "returns": {
+          "dkgMaliciousResultNotificationRewardMultiplier": "Percentage of the         staking contract malicious behavior notification reward which         will be transferred to the notifier reporting about a malicious         DKG result. Notifiers are rewarded from a notifiers treasury         pool. For example, if notification reward is 1000 and the value         of the multiplier is 5, the notifier will receive:         5% of 1000 = 50 per each operator affected.",
+          "relayEntryTimeoutNotificationRewardMultiplier": "Percentage of the         staking contract malicious behavior notification reward which         will be transferred to the notifier reporting about relay entry         timeout. Notifiers are rewarded from a notifiers treasury pool.         For example, if notification reward is 1000 and the value of the         multiplier is 5, the notifier will receive: 5% of 1000 = 50 per         each operator affected.",
+          "sortitionPoolRewardsBanDuration": "Duration of the sortition pool         rewards ban imposed on operators who misbehaved during DKG by         being inactive or disqualified and for operators that were         identified by the rest of group members as inactive via         `notifyOperatorInactivity`.",
+          "unauthorizedSigningNotificationRewardMultiplier": "Percentage of the         staking contract malicious behavior notification reward which         will be transferred to the notifier reporting about unauthorized         signing. Notifiers are rewarded from a notifiers treasury pool.         For example, if a notification reward is 1000 and the value of         the multiplier is 5, the notifier will receive: 5% of 1000 = 50         per each operator affected."
+        }
+      },
+      "selectGroup()": {
+        "returns": {
+          "_0": "IDs of selected group members."
+        }
+      },
+      "setRequesterAuthorization(address,bool)": {
+        "details": "Can be called only by the contract guvnor, which should be the      random beacon governance contract.",
+        "params": {
+          "isAuthorized": "True or false",
+          "requester": "Requester, can be a contract or EOA"
+        }
+      },
+      "slashingParameters()": {
+        "returns": {
+          "maliciousDkgResultSlashingAmount": "Slashing amount for submitting         a malicious DKG result. Every DKG result submitted can be         challenged for the time of `dkg.ResultChallengePeriodLength`.         If the DKG result submitted is challenged and proven to be         malicious, the operator who submitted the malicious result is         slashed for `maliciousDkgResultSlashingAmount`.",
+          "relayEntrySubmissionFailureSlashingAmount": "Slashing amount for         not submitting relay entry. When relay entry hard timeout is         reached without the relay entry submitted, each group member         gets slashed for `relayEntrySubmissionFailureSlashingAmount`.         If the relay entry gets submitted after the soft timeout, but         before the hard timeout, each group member gets slashed         proportionally to `relayEntrySubmissionFailureSlashingAmount`         and the time passed since the soft deadline.",
+          "unauthorizedSigningSlashingAmount": "Slashing amount when an         unauthorized signing has been proved, which means the private         key leaked and all the group members should be punished."
+        }
+      },
+      "submitDkgResult((uint256,bytes,uint8[],bytes,uint256[],uint32[],bytes32))": {
+        "params": {
+          "dkgResult": "DKG result."
+        }
+      },
+      "submitRelayEntry(bytes)": {
+        "params": {
+          "entry": "Group BLS signature over the previous entry."
+        }
+      },
+      "submitRelayEntry(bytes,uint32[])": {
+        "params": {
+          "entry": "Group BLS signature over the previous entry.",
+          "groupMembers": "Identifiers of group members."
+        }
+      },
+      "updateAuthorizationParameters(uint96,uint64,uint64)": {
+        "details": "Can be called only by the contract guvnor, which should be the      random beacon governance contract. The caller is responsible for      validating parameters.",
+        "params": {
+          "_authorizationDecreaseChangePeriod": "New authorization decrease        change period in seconds",
+          "_authorizationDecreaseDelay": "New authorization decrease delay in        seconds",
+          "_minimumAuthorization": "New minimum authorization amount"
+        }
+      },
+      "updateGasParameters(uint256,uint256,uint256,uint256)": {
+        "details": "Can be called only by the contract guvnor, which should be the      random beacon governance contract. The caller is responsible for      validating parameters.",
+        "params": {
+          "dkgResultApprovalGasOffset": "New DKG result approval gas offset",
+          "dkgResultSubmissionGas": "New DKG result submission gas",
+          "notifyOperatorInactivityGasOffset": "New operator inactivity        notification gas offset",
+          "relayEntrySubmissionGasOffset": "New relay entry submission gas        offset"
+        }
+      },
+      "updateGroupCreationParameters(uint256,uint256,uint256,uint256,uint256,uint256)": {
+        "details": "Can be called only by the contract guvnor, which should be the      random beacon governance contract. The caller is responsible for      validating parameters.",
+        "params": {
+          "dkgResultChallengeExtraGas": "New DKG result challenge extra gas",
+          "dkgResultChallengePeriodLength": "New DKG result challenge period        length",
+          "dkgResultSubmissionTimeout": "New DKG result submission timeout",
+          "dkgSubmitterPrecedencePeriodLength": "New DKG result submitter        precedence period length",
+          "groupCreationFrequency": "New group creation frequency",
+          "groupLifetime": "New group lifetime in blocks"
+        }
+      },
+      "updateRelayEntryParameters(uint256,uint256,uint256)": {
+        "details": "Can be called only by the contract guvnor, which should be the      random beacon governance contract. The caller is responsible for      validating parameters.",
+        "params": {
+          "callbackGasLimit": "New callback gas limit",
+          "relayEntryHardTimeout": "New relay entry hard timeout",
+          "relayEntrySoftTimeout": "New relay entry submission soft timeout"
+        }
+      },
+      "updateRewardParameters(uint256,uint256,uint256,uint256)": {
+        "details": "Can be called only by the contract guvnor, which should be the      random beacon governance contract. The caller is responsible for      validating parameters.",
+        "params": {
+          "dkgMaliciousResultNotificationRewardMultiplier": "New value of the        DKG malicious result notification reward multiplier",
+          "relayEntryTimeoutNotificationRewardMultiplier": "New value of the        relay entry timeout notification reward multiplier",
+          "sortitionPoolRewardsBanDuration": "New sortition pool rewards        ban duration in seconds.",
+          "unauthorizedSigningNotificationRewardMultiplier": "New value of the        unauthorized signing notification reward multiplier"
+        }
+      },
+      "updateSlashingParameters(uint96,uint96,uint96)": {
+        "details": "Can be called only by the contract guvnor, which should be the      random beacon governance contract. The caller is responsible for      validating parameters.",
+        "params": {
+          "maliciousDkgResultSlashingAmount": "New malicious DKG result        slashing amount",
+          "relayEntrySubmissionFailureSlashingAmount": "New relay entry        submission failure amount",
+          "unauthorizedSigningSlashingAmount": "New unauthorized signing        slashing amount"
+        }
+      },
+      "withdrawIneligibleRewards(address)": {
+        "details": "Can be called only by the contract guvnor, which should be the      random beacon governance contract.",
+        "params": {
+          "recipient": "Recipient of withdrawn rewards."
+        }
+      },
+      "withdrawRewards(address)": {
+        "details": "Emits `RewardsWithdrawn` event."
+      }
+    },
+    "title": "Keep Random Beacon",
+    "version": 1
+  },
+  "userdoc": {
+    "kind": "user",
+    "methods": {
+      "approveAuthorizationDecrease(address)": {
+        "notice": "Approves the previously registered authorization decrease         request. Reverts if authorization decrease delay has not passed         yet or if the authorization decrease was not requested for the         given staking provider."
+      },
+      "approveDkgResult((uint256,bytes,uint8[],bytes,uint256[],uint32[],bytes32))": {
+        "notice": "Approves DKG result. Can be called when the challenge period for         the submitted result is finished. Considers the submitted result         as valid, bans misbehaved group members from the sortition pool         rewards, and completes the group creation by activating the         candidate group. For the first `submitterPrecedencePeriodLength`         blocks after the end of the challenge period can be called only         by the DKG result submitter. After that time, can be called by         anyone."
+      },
+      "authorizationDecreaseRequested(address,uint96,uint96)": {
+        "notice": "Used by T staking contract to inform the beacon that the         authorization decrease for the given staking provider has been         requested.         Reverts if the amount after deauthorization would be non-zero         and lower than the minimum authorization.         Reverts if another authorization decrease request is pending for         the staking provider and not enough time passed since the         original request (see `authorizationDecreaseChangePeriod`).         If the operator is not known (`registerOperator` was not called)         it lets to `approveAuthorizationDecrease` immediately. If the         operator is known (`registerOperator` was called), the operator         needs to update state of the sortition pool with a call to         `joinSortitionPool` or `updateOperatorStatus`. After the         sortition pool state is in sync, authorization decrease delay         starts.         After authorization decrease delay passes, authorization         decrease request needs to be approved with a call to         `approveAuthorizationDecrease` function.         If there is a pending authorization decrease request, it is         overwritten, but only if enough time passed since the original         request. Otherwise, the function reverts."
+      },
+      "authorizationIncreased(address,uint96,uint96)": {
+        "notice": "Used by T staking contract to inform the beacon that the         authorized stake amount for the given staking provider increased.         Reverts if the authorization amount is below the minimum.         The function is not updating the sortition pool. Sortition pool         state needs to be updated by the operator with a call to         `joinSortitionPool` or `updateOperatorStatus`."
+      },
+      "authorizationParameters()": {
+        "notice": "Returns authorization-related parameters of the beacon."
+      },
+      "authorizedRequesters(address)": {
+        "notice": "Authorized addresses that can request a relay entry."
+      },
+      "availableRewards(address)": {
+        "notice": "Returns the amount of rewards available for withdrawal for the         given staking provider. Reverts if staking provider has not         registered the operator address."
+      },
+      "challengeDkgResult((uint256,bytes,uint8[],bytes,uint256[],uint32[],bytes32))": {
+        "notice": "Challenges DKG result. If the submitted result is proved to be         invalid it reverts the DKG back to the result submission phase.         It removes a candidate group that was previously registered with         the DKG result submission."
+      },
+      "eligibleStake(address)": {
+        "notice": "Returns the current value of the staking provider's eligible         stake. Eligible stake is defined as the currently authorized         stake minus the pending authorization decrease. Eligible stake         is what is used for operator's weight in the sortition pool.         If the authorized stake minus the pending authorization decrease         is below the minimum authorization, eligible stake is 0."
+      },
+      "gasParameters()": {
+        "notice": "Returns gas-related parameters of the beacon."
+      },
+      "genesis()": {
+        "notice": "Triggers group selection if there are no active groups."
+      },
+      "getGroupCreationState()": {
+        "notice": "Check current group creation state."
+      },
+      "groupCreationParameters()": {
+        "notice": "Returns group-creation-related parameters of the beacon."
+      },
+      "hasDkgTimedOut()": {
+        "notice": "Checks if DKG timed out. The DKG timeout period includes time required         for off-chain protocol execution and time for the result publication         for all group members. After this time result cannot be submitted         and DKG can be notified about the timeout."
+      },
+      "inactivityClaimNonce(uint64)": {
+        "notice": "Stores current operator inactivity claim nonce for given group.         Each claim is made with an unique nonce which protects         against claim replay."
+      },
+      "involuntaryAuthorizationDecrease(address,uint96,uint96)": {
+        "notice": "Used by T staking contract to inform the beacon the         authorization has been decreased for the given staking provider         involuntarily, as a result of slashing.         If the operator is not known (`registerOperator` was not called)         the function does nothing. The operator was never in a sortition         pool so there is nothing to update.         If the operator is known, sortition pool is unlocked, and the         operator is in the sortition pool, the sortition pool state is         updated. If the sortition pool is locked, update needs to be         postponed. Every other staker is incentivized to call         `updateOperatorStatus` for the problematic operator to increase         their own rewards in the pool."
+      },
+      "isOperatorInPool(address)": {
+        "notice": "Returns true if the given operator is in the sortition pool.         Otherwise, returns false."
+      },
+      "isOperatorUpToDate(address)": {
+        "notice": "Checks if the operator's authorized stake is in sync with         operator's weight in the sortition pool.         If the operator is not in the sortition pool and their         authorized stake is non-zero, function returns false."
+      },
+      "joinSortitionPool()": {
+        "notice": "Lets the operator join the sortition pool. The operator address         must be known - before calling this function, it has to be         appointed by the staking provider by calling `registerOperator`.         Also, the operator must have the minimum authorization required         by the beacon. Function reverts if there is no minimum stake         authorized or if the operator is not known. If there was an         authorization decrease requested, it is activated by starting         the authorization decrease delay."
+      },
+      "minimumAuthorization()": {
+        "notice": "The minimum authorization amount required so that operator can         participate in the random beacon. This amount is required to         execute slashing for providing a malicious DKG result or when         a relay entry times out."
+      },
+      "notifyDkgTimeout()": {
+        "notice": "Notifies about DKG timeout."
+      },
+      "notifyOperatorInactivity((uint64,uint256[],bytes,uint256[]),uint256,uint32[])": {
+        "notice": "Notifies about operators who are inactive. Using this function,         a majority of the group can decide about punishing specific         group members who constantly fail doing their job. If the provided         claim is proved to be valid and signed by sufficient number         of group members, operators of members deemed as inactive are         banned for sortition pool rewards for duration specified by         `_sortitionPoolRewardsBanDuration` parameter. The sender of         the claim must be one of the claim signers. This function can be         called only for active and non-terminated groups."
+      },
+      "operatorToStakingProvider(address)": {
+        "notice": "Returns staking provider of the given operator."
+      },
+      "pendingAuthorizationDecrease(address)": {
+        "notice": "Returns the amount of stake that is pending authorization         decrease for the given staking provider. If no authorization         decrease has been requested, returns zero."
+      },
+      "registerOperator(address)": {
+        "notice": "Used by staking provider to set operator address that will         operate a node. The given staking provider can set operator         address only one time. The operator address can not be changed         and must be unique. Reverts if the operator is already set for         the staking provider or if the operator address is already in         use. Reverts if there is a pending authorization decrease for         the staking provider."
+      },
+      "relayEntryParameters()": {
+        "notice": "Returns relay-entry-related parameters of the beacon."
+      },
+      "remainingAuthorizationDecreaseDelay(address)": {
+        "notice": "Returns the remaining time in seconds that needs to pass before         the requested authorization decrease can be approved.         If the sortition pool state was not updated yet by the operator         after requesting the authorization decrease, returns         `type(uint64).max`."
+      },
+      "reportRelayEntryTimeout(uint32[])": {
+        "notice": "Reports a relay entry timeout."
+      },
+      "reportUnauthorizedSigning(bytes,uint64,uint32[])": {
+        "notice": "Reports unauthorized groups signing. Must provide a valid signature         of the sender's address as a message. Successful signature         verification means the private key has been leaked and all group         members should be punished by slashing their tokens. Group has         to be active or expired. Unauthorized signing cannot be reported         for a terminated group. In case of reporting unauthorized         signing for a terminated group, or when the signature is invalid,         function reverts."
+      },
+      "requestRelayEntry(address)": {
+        "notice": "Creates a request to generate a new relay entry, which will         include a random number (by signing the previous entry's         random number). Requester must be previously authorized by the         governance."
+      },
+      "rewardParameters()": {
+        "notice": "Returns reward-related parameters of the beacon."
+      },
+      "selectGroup()": {
+        "notice": "Selects a new group of operators. Can only be called when DKG         is in progress and the pool is locked.         At least one operator has to be registered in the pool,         otherwise the function fails reverting the transaction."
+      },
+      "setRequesterAuthorization(address,bool)": {
+        "notice": "Set authorization for requesters that can request a relay         entry."
+      },
+      "slashingParameters()": {
+        "notice": "Returns slashing-related parameters of the beacon."
+      },
+      "stakingProviderToOperator(address)": {
+        "notice": "Returns operator registered for the given staking provider."
+      },
+      "submitDkgResult((uint256,bytes,uint8[],bytes,uint256[],uint32[],bytes32))": {
+        "notice": "`\\x19Ethereum signed message:\\n` before signing, so the message to      sign is:      `\\x19Ethereum signed message:\\n${keccak256(chainID,groupPubKey,misbehaved,startBlock)}`"
+      },
+      "submitRelayEntry(bytes)": {
+        "notice": "Creates a new relay entry. Gas-optimized version that can be         called only before the soft timeout. This should be the majority         of cases."
+      },
+      "submitRelayEntry(bytes,uint32[])": {
+        "notice": "Creates a new relay entry."
+      },
+      "transferGovernance(address)": {
+        "notice": "Transfers governance of the contract to `newGovernance`."
+      },
+      "updateAuthorizationParameters(uint96,uint64,uint64)": {
+        "notice": "Updates the values of authorization parameters."
+      },
+      "updateGasParameters(uint256,uint256,uint256,uint256)": {
+        "notice": "Updates the values of gas parameters."
+      },
+      "updateGroupCreationParameters(uint256,uint256,uint256,uint256,uint256,uint256)": {
+        "notice": "Updates the values of group creation parameters."
+      },
+      "updateOperatorStatus(address)": {
+        "notice": "Updates status of the operator in the sortition pool. If there         was an authorization decrease requested, it is activated by         starting the authorization decrease delay.         Function reverts if the operator is not known."
+      },
+      "updateRelayEntryParameters(uint256,uint256,uint256)": {
+        "notice": "Updates the values of relay entry parameters."
+      },
+      "updateRewardParameters(uint256,uint256,uint256,uint256)": {
+        "notice": "Updates the values of reward parameters."
+      },
+      "updateSlashingParameters(uint96,uint96,uint96)": {
+        "notice": "Updates the values of slashing parameters."
+      },
+      "withdrawIneligibleRewards(address)": {
+        "notice": "Withdraws rewards belonging to operators marked as ineligible         for sortition pool rewards."
+      },
+      "withdrawRewards(address)": {
+        "notice": "Withdraws application rewards for the given staking provider.         Rewards are withdrawn to the staking provider's beneficiary         address set in the staking contract. Reverts if staking provider         has not registered the operator address."
+      }
+    },
+    "notice": "Keep Random Beacon contract. It lets to request a new         relay entry and validates the new relay entry provided by the         network. This contract is in charge of all other Random Beacon         activities such as group lifecycle or slashing.",
+    "version": 1
+  },
+  "storageLayout": {
+    "storage": [
+      {
+        "astId": 9746,
+        "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+        "label": "governance",
+        "offset": 0,
+        "slot": "0",
+        "type": "t_address"
+      },
+      {
+        "astId": 9750,
+        "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+        "label": "__gap",
+        "offset": 0,
+        "slot": "1",
+        "type": "t_array(t_uint256)49_storage"
+      },
+      {
+        "astId": 14627,
+        "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+        "label": "reimbursementPool",
+        "offset": 0,
+        "slot": "50",
+        "type": "t_contract(ReimbursementPool)14957"
+      },
+      {
+        "astId": 14631,
+        "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+        "label": "__gap",
+        "offset": 0,
+        "slot": "51",
+        "type": "t_array(t_uint256)49_storage"
+      },
+      {
+        "astId": 9874,
+        "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+        "label": "_callbackGasLimit",
+        "offset": 0,
+        "slot": "100",
+        "type": "t_uint256"
+      },
+      {
+        "astId": 9877,
+        "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+        "label": "_groupCreationFrequency",
+        "offset": 0,
+        "slot": "101",
+        "type": "t_uint256"
+      },
+      {
+        "astId": 9880,
+        "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+        "label": "_maliciousDkgResultSlashingAmount",
+        "offset": 0,
+        "slot": "102",
+        "type": "t_uint96"
+      },
+      {
+        "astId": 9883,
+        "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+        "label": "_unauthorizedSigningSlashingAmount",
+        "offset": 12,
+        "slot": "102",
+        "type": "t_uint96"
+      },
+      {
+        "astId": 9886,
+        "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+        "label": "_sortitionPoolRewardsBanDuration",
+        "offset": 0,
+        "slot": "103",
+        "type": "t_uint256"
+      },
+      {
+        "astId": 9889,
+        "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+        "label": "_relayEntryTimeoutNotificationRewardMultiplier",
+        "offset": 0,
+        "slot": "104",
+        "type": "t_uint256"
+      },
+      {
+        "astId": 9892,
+        "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+        "label": "_unauthorizedSigningNotificationRewardMultiplier",
+        "offset": 0,
+        "slot": "105",
+        "type": "t_uint256"
+      },
+      {
+        "astId": 9895,
+        "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+        "label": "_dkgMaliciousResultNotificationRewardMultiplier",
+        "offset": 0,
+        "slot": "106",
+        "type": "t_uint256"
+      },
+      {
+        "astId": 9898,
+        "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+        "label": "_dkgResultSubmissionGas",
+        "offset": 0,
+        "slot": "107",
+        "type": "t_uint256"
+      },
+      {
+        "astId": 9901,
+        "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+        "label": "_dkgResultApprovalGasOffset",
+        "offset": 0,
+        "slot": "108",
+        "type": "t_uint256"
+      },
+      {
+        "astId": 9904,
+        "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+        "label": "_notifyOperatorInactivityGasOffset",
+        "offset": 0,
+        "slot": "109",
+        "type": "t_uint256"
+      },
+      {
+        "astId": 9907,
+        "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+        "label": "_relayEntrySubmissionGasOffset",
+        "offset": 0,
+        "slot": "110",
+        "type": "t_uint256"
+      },
+      {
+        "astId": 9912,
+        "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+        "label": "inactivityClaimNonce",
+        "offset": 0,
+        "slot": "111",
+        "type": "t_mapping(t_uint64,t_uint256)"
+      },
+      {
+        "astId": 9917,
+        "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+        "label": "authorizedRequesters",
+        "offset": 0,
+        "slot": "112",
+        "type": "t_mapping(t_address,t_bool)"
+      },
+      {
+        "astId": 9920,
+        "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+        "label": "sortitionPool",
+        "offset": 0,
+        "slot": "113",
+        "type": "t_contract(SortitionPool)1980"
+      },
+      {
+        "astId": 9923,
+        "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+        "label": "tToken",
+        "offset": 0,
+        "slot": "114",
+        "type": "t_contract(IERC20)4111"
+      },
+      {
+        "astId": 9926,
+        "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+        "label": "staking",
+        "offset": 0,
+        "slot": "115",
+        "type": "t_contract(IStaking)9081"
+      },
+      {
+        "astId": 9929,
+        "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+        "label": "authorization",
+        "offset": 0,
+        "slot": "116",
+        "type": "t_struct(Data)16552_storage"
+      },
+      {
+        "astId": 9932,
+        "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+        "label": "dkg",
+        "offset": 0,
+        "slot": "120",
+        "type": "t_struct(Data)17482_storage"
+      },
+      {
+        "astId": 9935,
+        "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+        "label": "groups",
+        "offset": 0,
+        "slot": "131",
+        "type": "t_struct(Data)18985_storage"
+      },
+      {
+        "astId": 9938,
+        "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+        "label": "relay",
+        "offset": 0,
+        "slot": "136",
+        "type": "t_struct(Data)19879_storage"
+      },
+      {
+        "astId": 9941,
+        "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+        "label": "callback",
+        "offset": 0,
+        "slot": "140",
+        "type": "t_struct(Data)18889_storage"
+      }
+    ],
+    "types": {
+      "t_address": {
+        "encoding": "inplace",
+        "label": "address",
+        "numberOfBytes": "20"
+      },
+      "t_array(t_bytes32)dyn_storage": {
+        "base": "t_bytes32",
+        "encoding": "dynamic_array",
+        "label": "bytes32[]",
+        "numberOfBytes": "32"
+      },
+      "t_array(t_uint256)49_storage": {
+        "base": "t_uint256",
+        "encoding": "inplace",
+        "label": "uint256[49]",
+        "numberOfBytes": "1568"
+      },
+      "t_array(t_uint64)dyn_storage": {
+        "base": "t_uint64",
+        "encoding": "dynamic_array",
+        "label": "uint64[]",
+        "numberOfBytes": "32"
+      },
+      "t_bool": {
+        "encoding": "inplace",
+        "label": "bool",
+        "numberOfBytes": "1"
+      },
+      "t_bytes32": {
+        "encoding": "inplace",
+        "label": "bytes32",
+        "numberOfBytes": "32"
+      },
+      "t_bytes_storage": {
+        "encoding": "bytes",
+        "label": "bytes",
+        "numberOfBytes": "32"
+      },
+      "t_contract(BeaconDkgValidator)9741": {
+        "encoding": "inplace",
+        "label": "contract BeaconDkgValidator",
+        "numberOfBytes": "20"
+      },
+      "t_contract(IERC20)4111": {
+        "encoding": "inplace",
+        "label": "contract IERC20",
+        "numberOfBytes": "20"
+      },
+      "t_contract(IRandomBeaconConsumer)14980": {
+        "encoding": "inplace",
+        "label": "contract IRandomBeaconConsumer",
+        "numberOfBytes": "20"
+      },
+      "t_contract(IStaking)9081": {
+        "encoding": "inplace",
+        "label": "contract IStaking",
+        "numberOfBytes": "20"
+      },
+      "t_contract(ReimbursementPool)14957": {
+        "encoding": "inplace",
+        "label": "contract ReimbursementPool",
+        "numberOfBytes": "20"
+      },
+      "t_contract(SortitionPool)1980": {
+        "encoding": "inplace",
+        "label": "contract SortitionPool",
+        "numberOfBytes": "20"
+      },
+      "t_mapping(t_address,t_address)": {
+        "encoding": "mapping",
+        "key": "t_address",
+        "label": "mapping(address => address)",
+        "numberOfBytes": "32",
+        "value": "t_address"
+      },
+      "t_mapping(t_address,t_bool)": {
+        "encoding": "mapping",
+        "key": "t_address",
+        "label": "mapping(address => bool)",
+        "numberOfBytes": "32",
+        "value": "t_bool"
+      },
+      "t_mapping(t_address,t_struct(AuthorizationDecrease)16535_storage)": {
+        "encoding": "mapping",
+        "key": "t_address",
+        "label": "mapping(address => struct BeaconAuthorization.AuthorizationDecrease)",
+        "numberOfBytes": "32",
+        "value": "t_struct(AuthorizationDecrease)16535_storage"
+      },
+      "t_mapping(t_bytes32,t_struct(Group)18969_storage)": {
+        "encoding": "mapping",
+        "key": "t_bytes32",
+        "label": "mapping(bytes32 => struct Groups.Group)",
+        "numberOfBytes": "32",
+        "value": "t_struct(Group)18969_storage"
+      },
+      "t_mapping(t_uint64,t_uint256)": {
+        "encoding": "mapping",
+        "key": "t_uint64",
+        "label": "mapping(uint64 => uint256)",
+        "numberOfBytes": "32",
+        "value": "t_uint256"
+      },
+      "t_struct(AuthorizationDecrease)16535_storage": {
+        "encoding": "inplace",
+        "label": "struct BeaconAuthorization.AuthorizationDecrease",
+        "members": [
+          {
+            "astId": 16532,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "decreasingBy",
+            "offset": 0,
+            "slot": "0",
+            "type": "t_uint96"
+          },
+          {
+            "astId": 16534,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "decreasingAt",
+            "offset": 12,
+            "slot": "0",
+            "type": "t_uint64"
+          }
+        ],
+        "numberOfBytes": "32"
+      },
+      "t_struct(Data)16552_storage": {
+        "encoding": "inplace",
+        "label": "struct BeaconAuthorization.Data",
+        "members": [
+          {
+            "astId": 16538,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "parameters",
+            "offset": 0,
+            "slot": "0",
+            "type": "t_struct(Parameters)16530_storage"
+          },
+          {
+            "astId": 16542,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "stakingProviderToOperator",
+            "offset": 0,
+            "slot": "1",
+            "type": "t_mapping(t_address,t_address)"
+          },
+          {
+            "astId": 16546,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "operatorToStakingProvider",
+            "offset": 0,
+            "slot": "2",
+            "type": "t_mapping(t_address,t_address)"
+          },
+          {
+            "astId": 16551,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "pendingDecreases",
+            "offset": 0,
+            "slot": "3",
+            "type": "t_mapping(t_address,t_struct(AuthorizationDecrease)16535_storage)"
+          }
+        ],
+        "numberOfBytes": "128"
+      },
+      "t_struct(Data)17482_storage": {
+        "encoding": "inplace",
+        "label": "struct BeaconDkg.Data",
+        "members": [
+          {
+            "astId": 17465,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "sortitionPool",
+            "offset": 0,
+            "slot": "0",
+            "type": "t_contract(SortitionPool)1980"
+          },
+          {
+            "astId": 17468,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "dkgValidator",
+            "offset": 0,
+            "slot": "1",
+            "type": "t_contract(BeaconDkgValidator)9741"
+          },
+          {
+            "astId": 17471,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "parameters",
+            "offset": 0,
+            "slot": "2",
+            "type": "t_struct(Parameters)17462_storage"
+          },
+          {
+            "astId": 17473,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "startBlock",
+            "offset": 0,
+            "slot": "6",
+            "type": "t_uint256"
+          },
+          {
+            "astId": 17475,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "seed",
+            "offset": 0,
+            "slot": "7",
+            "type": "t_uint256"
+          },
+          {
+            "astId": 17477,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "resultSubmissionStartBlockOffset",
+            "offset": 0,
+            "slot": "8",
+            "type": "t_uint256"
+          },
+          {
+            "astId": 17479,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "submittedResultHash",
+            "offset": 0,
+            "slot": "9",
+            "type": "t_bytes32"
+          },
+          {
+            "astId": 17481,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "submittedResultBlock",
+            "offset": 0,
+            "slot": "10",
+            "type": "t_uint256"
+          }
+        ],
+        "numberOfBytes": "352"
+      },
+      "t_struct(Data)18889_storage": {
+        "encoding": "inplace",
+        "label": "struct Callback.Data",
+        "members": [
+          {
+            "astId": 18888,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "callbackContract",
+            "offset": 0,
+            "slot": "0",
+            "type": "t_contract(IRandomBeaconConsumer)14980"
+          }
+        ],
+        "numberOfBytes": "32"
+      },
+      "t_struct(Data)18985_storage": {
+        "encoding": "inplace",
+        "label": "struct Groups.Data",
+        "members": [
+          {
+            "astId": 18974,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "groupsData",
+            "offset": 0,
+            "slot": "0",
+            "type": "t_mapping(t_bytes32,t_struct(Group)18969_storage)"
+          },
+          {
+            "astId": 18977,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "groupsRegistry",
+            "offset": 0,
+            "slot": "1",
+            "type": "t_array(t_bytes32)dyn_storage"
+          },
+          {
+            "astId": 18980,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "activeTerminatedGroups",
+            "offset": 0,
+            "slot": "2",
+            "type": "t_array(t_uint64)dyn_storage"
+          },
+          {
+            "astId": 18982,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "expiredGroupOffset",
+            "offset": 0,
+            "slot": "3",
+            "type": "t_uint64"
+          },
+          {
+            "astId": 18984,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "groupLifetime",
+            "offset": 0,
+            "slot": "4",
+            "type": "t_uint256"
+          }
+        ],
+        "numberOfBytes": "160"
+      },
+      "t_struct(Data)19879_storage": {
+        "encoding": "inplace",
+        "label": "struct Relay.Data",
+        "members": [
+          {
+            "astId": 19863,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "requestCount",
+            "offset": 0,
+            "slot": "0",
+            "type": "t_uint64"
+          },
+          {
+            "astId": 19865,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "currentRequestID",
+            "offset": 8,
+            "slot": "0",
+            "type": "t_uint64"
+          },
+          {
+            "astId": 19867,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "currentRequestGroupID",
+            "offset": 16,
+            "slot": "0",
+            "type": "t_uint64"
+          },
+          {
+            "astId": 19869,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "currentRequestStartBlock",
+            "offset": 24,
+            "slot": "0",
+            "type": "t_uint64"
+          },
+          {
+            "astId": 19872,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "previousEntry",
+            "offset": 0,
+            "slot": "1",
+            "type": "t_struct(G1Point)14992_storage"
+          },
+          {
+            "astId": 19874,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "relayEntrySoftTimeout",
+            "offset": 0,
+            "slot": "3",
+            "type": "t_uint32"
+          },
+          {
+            "astId": 19876,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "relayEntryHardTimeout",
+            "offset": 4,
+            "slot": "3",
+            "type": "t_uint32"
+          },
+          {
+            "astId": 19878,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "relayEntrySubmissionFailureSlashingAmount",
+            "offset": 8,
+            "slot": "3",
+            "type": "t_uint96"
+          }
+        ],
+        "numberOfBytes": "128"
+      },
+      "t_struct(G1Point)14992_storage": {
+        "encoding": "inplace",
+        "label": "struct AltBn128.G1Point",
+        "members": [
+          {
+            "astId": 14989,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "x",
+            "offset": 0,
+            "slot": "0",
+            "type": "t_uint256"
+          },
+          {
+            "astId": 14991,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "y",
+            "offset": 0,
+            "slot": "1",
+            "type": "t_uint256"
+          }
+        ],
+        "numberOfBytes": "64"
+      },
+      "t_struct(Group)18969_storage": {
+        "encoding": "inplace",
+        "label": "struct Groups.Group",
+        "members": [
+          {
+            "astId": 18962,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "groupPubKey",
+            "offset": 0,
+            "slot": "0",
+            "type": "t_bytes_storage"
+          },
+          {
+            "astId": 18964,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "registrationBlockNumber",
+            "offset": 0,
+            "slot": "1",
+            "type": "t_uint256"
+          },
+          {
+            "astId": 18966,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "membersHash",
+            "offset": 0,
+            "slot": "2",
+            "type": "t_bytes32"
+          },
+          {
+            "astId": 18968,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "terminated",
+            "offset": 0,
+            "slot": "3",
+            "type": "t_bool"
+          }
+        ],
+        "numberOfBytes": "128"
+      },
+      "t_struct(Parameters)16530_storage": {
+        "encoding": "inplace",
+        "label": "struct BeaconAuthorization.Parameters",
+        "members": [
+          {
+            "astId": 16525,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "minimumAuthorization",
+            "offset": 0,
+            "slot": "0",
+            "type": "t_uint96"
+          },
+          {
+            "astId": 16527,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "authorizationDecreaseDelay",
+            "offset": 12,
+            "slot": "0",
+            "type": "t_uint64"
+          },
+          {
+            "astId": 16529,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "authorizationDecreaseChangePeriod",
+            "offset": 20,
+            "slot": "0",
+            "type": "t_uint64"
+          }
+        ],
+        "numberOfBytes": "32"
+      },
+      "t_struct(Parameters)17462_storage": {
+        "encoding": "inplace",
+        "label": "struct BeaconDkg.Parameters",
+        "members": [
+          {
+            "astId": 17455,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "resultChallengePeriodLength",
+            "offset": 0,
+            "slot": "0",
+            "type": "t_uint256"
+          },
+          {
+            "astId": 17457,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "resultChallengeExtraGas",
+            "offset": 0,
+            "slot": "1",
+            "type": "t_uint256"
+          },
+          {
+            "astId": 17459,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "resultSubmissionTimeout",
+            "offset": 0,
+            "slot": "2",
+            "type": "t_uint256"
+          },
+          {
+            "astId": 17461,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "submitterPrecedencePeriodLength",
+            "offset": 0,
+            "slot": "3",
+            "type": "t_uint256"
+          }
+        ],
+        "numberOfBytes": "128"
+      },
+      "t_uint256": {
+        "encoding": "inplace",
+        "label": "uint256",
+        "numberOfBytes": "32"
+      },
+      "t_uint32": {
+        "encoding": "inplace",
+        "label": "uint32",
+        "numberOfBytes": "4"
+      },
+      "t_uint64": {
+        "encoding": "inplace",
+        "label": "uint64",
+        "numberOfBytes": "8"
+      },
+      "t_uint96": {
+        "encoding": "inplace",
+        "label": "uint96",
+        "numberOfBytes": "12"
+      }
+    }
+  }
+}
diff --git a/src/threshold-ts/tbtc/sepolia-artifacts/RandomBeacon.json b/src/threshold-ts/tbtc/sepolia-artifacts/RandomBeacon.json
new file mode 100644
index 000000000..6ca0e0e63
--- /dev/null
+++ b/src/threshold-ts/tbtc/sepolia-artifacts/RandomBeacon.json
@@ -0,0 +1,3269 @@
+{
+  "address": "0x02CBA6D77CF9fB019e322c55b34c9d42f2eF4D74",
+  "abi": [
+    {
+      "inputs": [
+        {
+          "internalType": "contract SortitionPool",
+          "name": "_sortitionPool",
+          "type": "address"
+        },
+        {
+          "internalType": "contract IERC20",
+          "name": "_tToken",
+          "type": "address"
+        },
+        {
+          "internalType": "contract IStaking",
+          "name": "_staking",
+          "type": "address"
+        },
+        {
+          "internalType": "contract BeaconDkgValidator",
+          "name": "_dkgValidator",
+          "type": "address"
+        },
+        {
+          "internalType": "contract ReimbursementPool",
+          "name": "_reimbursementPool",
+          "type": "address"
+        }
+      ],
+      "stateMutability": "nonpayable",
+      "type": "constructor"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        }
+      ],
+      "name": "AuthorizationDecreaseApproved",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        },
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "operator",
+          "type": "address"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint96",
+          "name": "fromAmount",
+          "type": "uint96"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint96",
+          "name": "toAmount",
+          "type": "uint96"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint64",
+          "name": "decreasingAt",
+          "type": "uint64"
+        }
+      ],
+      "name": "AuthorizationDecreaseRequested",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        },
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "operator",
+          "type": "address"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint96",
+          "name": "fromAmount",
+          "type": "uint96"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint96",
+          "name": "toAmount",
+          "type": "uint96"
+        }
+      ],
+      "name": "AuthorizationIncreased",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": false,
+          "internalType": "uint96",
+          "name": "minimumAuthorization",
+          "type": "uint96"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint64",
+          "name": "authorizationDecreaseDelay",
+          "type": "uint64"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint64",
+          "name": "authorizationDecreaseChangePeriod",
+          "type": "uint64"
+        }
+      ],
+      "name": "AuthorizationParametersUpdated",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "entry",
+          "type": "uint256"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "entrySubmittedBlock",
+          "type": "uint256"
+        }
+      ],
+      "name": "CallbackFailed",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "bytes32",
+          "name": "resultHash",
+          "type": "bytes32"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "slashingAmount",
+          "type": "uint256"
+        },
+        {
+          "indexed": false,
+          "internalType": "address",
+          "name": "maliciousSubmitter",
+          "type": "address"
+        }
+      ],
+      "name": "DkgMaliciousResultSlashed",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "bytes32",
+          "name": "resultHash",
+          "type": "bytes32"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "slashingAmount",
+          "type": "uint256"
+        },
+        {
+          "indexed": false,
+          "internalType": "address",
+          "name": "maliciousSubmitter",
+          "type": "address"
+        }
+      ],
+      "name": "DkgMaliciousResultSlashingFailed",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "bytes32",
+          "name": "resultHash",
+          "type": "bytes32"
+        },
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "approver",
+          "type": "address"
+        }
+      ],
+      "name": "DkgResultApproved",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "bytes32",
+          "name": "resultHash",
+          "type": "bytes32"
+        },
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "challenger",
+          "type": "address"
+        },
+        {
+          "indexed": false,
+          "internalType": "string",
+          "name": "reason",
+          "type": "string"
+        }
+      ],
+      "name": "DkgResultChallenged",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "bytes32",
+          "name": "resultHash",
+          "type": "bytes32"
+        },
+        {
+          "indexed": true,
+          "internalType": "uint256",
+          "name": "seed",
+          "type": "uint256"
+        },
+        {
+          "components": [
+            {
+              "internalType": "uint256",
+              "name": "submitterMemberIndex",
+              "type": "uint256"
+            },
+            {
+              "internalType": "bytes",
+              "name": "groupPubKey",
+              "type": "bytes"
+            },
+            {
+              "internalType": "uint8[]",
+              "name": "misbehavedMembersIndices",
+              "type": "uint8[]"
+            },
+            {
+              "internalType": "bytes",
+              "name": "signatures",
+              "type": "bytes"
+            },
+            {
+              "internalType": "uint256[]",
+              "name": "signingMembersIndices",
+              "type": "uint256[]"
+            },
+            {
+              "internalType": "uint32[]",
+              "name": "members",
+              "type": "uint32[]"
+            },
+            {
+              "internalType": "bytes32",
+              "name": "membersHash",
+              "type": "bytes32"
+            }
+          ],
+          "indexed": false,
+          "internalType": "struct BeaconDkg.Result",
+          "name": "result",
+          "type": "tuple"
+        }
+      ],
+      "name": "DkgResultSubmitted",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [],
+      "name": "DkgSeedTimedOut",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "uint256",
+          "name": "seed",
+          "type": "uint256"
+        }
+      ],
+      "name": "DkgStarted",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [],
+      "name": "DkgStateLocked",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [],
+      "name": "DkgTimedOut",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "dkgResultSubmissionGas",
+          "type": "uint256"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "dkgResultApprovalGasOffset",
+          "type": "uint256"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "notifyOperatorInactivityGasOffset",
+          "type": "uint256"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "relayEntrySubmissionGasOffset",
+          "type": "uint256"
+        }
+      ],
+      "name": "GasParametersUpdated",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": false,
+          "internalType": "address",
+          "name": "oldGovernance",
+          "type": "address"
+        },
+        {
+          "indexed": false,
+          "internalType": "address",
+          "name": "newGovernance",
+          "type": "address"
+        }
+      ],
+      "name": "GovernanceTransferred",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "groupCreationFrequency",
+          "type": "uint256"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "groupLifetime",
+          "type": "uint256"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "dkgResultChallengePeriodLength",
+          "type": "uint256"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "dkgResultChallengeExtraGas",
+          "type": "uint256"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "dkgResultSubmissionTimeout",
+          "type": "uint256"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "dkgResultSubmitterPrecedencePeriodLength",
+          "type": "uint256"
+        }
+      ],
+      "name": "GroupCreationParametersUpdated",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "uint64",
+          "name": "groupId",
+          "type": "uint64"
+        },
+        {
+          "indexed": true,
+          "internalType": "bytes",
+          "name": "groupPubKey",
+          "type": "bytes"
+        }
+      ],
+      "name": "GroupRegistered",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "uint64",
+          "name": "groupId",
+          "type": "uint64"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "nonce",
+          "type": "uint256"
+        },
+        {
+          "indexed": false,
+          "internalType": "address",
+          "name": "notifier",
+          "type": "address"
+        }
+      ],
+      "name": "InactivityClaimed",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        },
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "operator",
+          "type": "address"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint96",
+          "name": "fromAmount",
+          "type": "uint96"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint96",
+          "name": "toAmount",
+          "type": "uint96"
+        }
+      ],
+      "name": "InvoluntaryAuthorizationDecreaseFailed",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        },
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "operator",
+          "type": "address"
+        }
+      ],
+      "name": "OperatorJoinedSortitionPool",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        },
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "operator",
+          "type": "address"
+        }
+      ],
+      "name": "OperatorRegistered",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        },
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "operator",
+          "type": "address"
+        }
+      ],
+      "name": "OperatorStatusUpdated",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": false,
+          "internalType": "address",
+          "name": "newReimbursementPool",
+          "type": "address"
+        }
+      ],
+      "name": "ReimbursementPoolUpdated",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "uint256",
+          "name": "requestId",
+          "type": "uint256"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "slashingAmount",
+          "type": "uint256"
+        },
+        {
+          "indexed": false,
+          "internalType": "address[]",
+          "name": "groupMembers",
+          "type": "address[]"
+        }
+      ],
+      "name": "RelayEntryDelaySlashed",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "uint256",
+          "name": "requestId",
+          "type": "uint256"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "slashingAmount",
+          "type": "uint256"
+        },
+        {
+          "indexed": false,
+          "internalType": "address[]",
+          "name": "groupMembers",
+          "type": "address[]"
+        }
+      ],
+      "name": "RelayEntryDelaySlashingFailed",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "relayEntrySoftTimeout",
+          "type": "uint256"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "relayEntryHardTimeout",
+          "type": "uint256"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "callbackGasLimit",
+          "type": "uint256"
+        }
+      ],
+      "name": "RelayEntryParametersUpdated",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "uint256",
+          "name": "requestId",
+          "type": "uint256"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint64",
+          "name": "groupId",
+          "type": "uint64"
+        },
+        {
+          "indexed": false,
+          "internalType": "bytes",
+          "name": "previousEntry",
+          "type": "bytes"
+        }
+      ],
+      "name": "RelayEntryRequested",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "uint256",
+          "name": "requestId",
+          "type": "uint256"
+        },
+        {
+          "indexed": false,
+          "internalType": "address",
+          "name": "submitter",
+          "type": "address"
+        },
+        {
+          "indexed": false,
+          "internalType": "bytes",
+          "name": "entry",
+          "type": "bytes"
+        }
+      ],
+      "name": "RelayEntrySubmitted",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "uint256",
+          "name": "requestId",
+          "type": "uint256"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint64",
+          "name": "terminatedGroupId",
+          "type": "uint64"
+        }
+      ],
+      "name": "RelayEntryTimedOut",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "uint256",
+          "name": "requestId",
+          "type": "uint256"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "slashingAmount",
+          "type": "uint256"
+        },
+        {
+          "indexed": false,
+          "internalType": "address[]",
+          "name": "groupMembers",
+          "type": "address[]"
+        }
+      ],
+      "name": "RelayEntryTimeoutSlashed",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "uint256",
+          "name": "requestId",
+          "type": "uint256"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "slashingAmount",
+          "type": "uint256"
+        },
+        {
+          "indexed": false,
+          "internalType": "address[]",
+          "name": "groupMembers",
+          "type": "address[]"
+        }
+      ],
+      "name": "RelayEntryTimeoutSlashingFailed",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "requester",
+          "type": "address"
+        },
+        {
+          "indexed": false,
+          "internalType": "bool",
+          "name": "isAuthorized",
+          "type": "bool"
+        }
+      ],
+      "name": "RequesterAuthorizationUpdated",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "sortitionPoolRewardsBanDuration",
+          "type": "uint256"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "relayEntryTimeoutNotificationRewardMultiplier",
+          "type": "uint256"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "unauthorizedSigningNotificationRewardMultiplier",
+          "type": "uint256"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "dkgMaliciousResultNotificationRewardMultiplier",
+          "type": "uint256"
+        }
+      ],
+      "name": "RewardParametersUpdated",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint96",
+          "name": "amount",
+          "type": "uint96"
+        }
+      ],
+      "name": "RewardsWithdrawn",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "relayEntrySubmissionFailureSlashingAmount",
+          "type": "uint256"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "maliciousDkgResultSlashingAmount",
+          "type": "uint256"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "unauthorizedSigningSlashingAmount",
+          "type": "uint256"
+        }
+      ],
+      "name": "SlashingParametersUpdated",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "uint64",
+          "name": "groupId",
+          "type": "uint64"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "unauthorizedSigningSlashingAmount",
+          "type": "uint256"
+        },
+        {
+          "indexed": false,
+          "internalType": "address[]",
+          "name": "groupMembers",
+          "type": "address[]"
+        }
+      ],
+      "name": "UnauthorizedSigningSlashed",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "uint64",
+          "name": "groupId",
+          "type": "uint64"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "unauthorizedSigningSlashingAmount",
+          "type": "uint256"
+        },
+        {
+          "indexed": false,
+          "internalType": "address[]",
+          "name": "groupMembers",
+          "type": "address[]"
+        }
+      ],
+      "name": "UnauthorizedSigningSlashingFailed",
+      "type": "event"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        }
+      ],
+      "name": "approveAuthorizationDecrease",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "components": [
+            {
+              "internalType": "uint256",
+              "name": "submitterMemberIndex",
+              "type": "uint256"
+            },
+            {
+              "internalType": "bytes",
+              "name": "groupPubKey",
+              "type": "bytes"
+            },
+            {
+              "internalType": "uint8[]",
+              "name": "misbehavedMembersIndices",
+              "type": "uint8[]"
+            },
+            {
+              "internalType": "bytes",
+              "name": "signatures",
+              "type": "bytes"
+            },
+            {
+              "internalType": "uint256[]",
+              "name": "signingMembersIndices",
+              "type": "uint256[]"
+            },
+            {
+              "internalType": "uint32[]",
+              "name": "members",
+              "type": "uint32[]"
+            },
+            {
+              "internalType": "bytes32",
+              "name": "membersHash",
+              "type": "bytes32"
+            }
+          ],
+          "internalType": "struct BeaconDkg.Result",
+          "name": "dkgResult",
+          "type": "tuple"
+        }
+      ],
+      "name": "approveDkgResult",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        },
+        {
+          "internalType": "uint96",
+          "name": "fromAmount",
+          "type": "uint96"
+        },
+        {
+          "internalType": "uint96",
+          "name": "toAmount",
+          "type": "uint96"
+        }
+      ],
+      "name": "authorizationDecreaseRequested",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        },
+        {
+          "internalType": "uint96",
+          "name": "fromAmount",
+          "type": "uint96"
+        },
+        {
+          "internalType": "uint96",
+          "name": "toAmount",
+          "type": "uint96"
+        }
+      ],
+      "name": "authorizationIncreased",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "authorizationParameters",
+      "outputs": [
+        {
+          "internalType": "uint96",
+          "name": "minimumAuthorization",
+          "type": "uint96"
+        },
+        {
+          "internalType": "uint64",
+          "name": "authorizationDecreaseDelay",
+          "type": "uint64"
+        },
+        {
+          "internalType": "uint64",
+          "name": "authorizationDecreaseChangePeriod",
+          "type": "uint64"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "",
+          "type": "address"
+        }
+      ],
+      "name": "authorizedRequesters",
+      "outputs": [
+        {
+          "internalType": "bool",
+          "name": "",
+          "type": "bool"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        }
+      ],
+      "name": "availableRewards",
+      "outputs": [
+        {
+          "internalType": "uint96",
+          "name": "",
+          "type": "uint96"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "components": [
+            {
+              "internalType": "uint256",
+              "name": "submitterMemberIndex",
+              "type": "uint256"
+            },
+            {
+              "internalType": "bytes",
+              "name": "groupPubKey",
+              "type": "bytes"
+            },
+            {
+              "internalType": "uint8[]",
+              "name": "misbehavedMembersIndices",
+              "type": "uint8[]"
+            },
+            {
+              "internalType": "bytes",
+              "name": "signatures",
+              "type": "bytes"
+            },
+            {
+              "internalType": "uint256[]",
+              "name": "signingMembersIndices",
+              "type": "uint256[]"
+            },
+            {
+              "internalType": "uint32[]",
+              "name": "members",
+              "type": "uint32[]"
+            },
+            {
+              "internalType": "bytes32",
+              "name": "membersHash",
+              "type": "bytes32"
+            }
+          ],
+          "internalType": "struct BeaconDkg.Result",
+          "name": "dkgResult",
+          "type": "tuple"
+        }
+      ],
+      "name": "challengeDkgResult",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        }
+      ],
+      "name": "eligibleStake",
+      "outputs": [
+        {
+          "internalType": "uint96",
+          "name": "",
+          "type": "uint96"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "gasParameters",
+      "outputs": [
+        {
+          "internalType": "uint256",
+          "name": "dkgResultSubmissionGas",
+          "type": "uint256"
+        },
+        {
+          "internalType": "uint256",
+          "name": "dkgResultApprovalGasOffset",
+          "type": "uint256"
+        },
+        {
+          "internalType": "uint256",
+          "name": "notifyOperatorInactivityGasOffset",
+          "type": "uint256"
+        },
+        {
+          "internalType": "uint256",
+          "name": "relayEntrySubmissionGasOffset",
+          "type": "uint256"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "genesis",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "uint64",
+          "name": "groupId",
+          "type": "uint64"
+        }
+      ],
+      "name": "getGroup",
+      "outputs": [
+        {
+          "components": [
+            {
+              "internalType": "bytes",
+              "name": "groupPubKey",
+              "type": "bytes"
+            },
+            {
+              "internalType": "uint256",
+              "name": "registrationBlockNumber",
+              "type": "uint256"
+            },
+            {
+              "internalType": "bytes32",
+              "name": "membersHash",
+              "type": "bytes32"
+            },
+            {
+              "internalType": "bool",
+              "name": "terminated",
+              "type": "bool"
+            }
+          ],
+          "internalType": "struct Groups.Group",
+          "name": "",
+          "type": "tuple"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "bytes",
+          "name": "groupPubKey",
+          "type": "bytes"
+        }
+      ],
+      "name": "getGroup",
+      "outputs": [
+        {
+          "components": [
+            {
+              "internalType": "bytes",
+              "name": "groupPubKey",
+              "type": "bytes"
+            },
+            {
+              "internalType": "uint256",
+              "name": "registrationBlockNumber",
+              "type": "uint256"
+            },
+            {
+              "internalType": "bytes32",
+              "name": "membersHash",
+              "type": "bytes32"
+            },
+            {
+              "internalType": "bool",
+              "name": "terminated",
+              "type": "bool"
+            }
+          ],
+          "internalType": "struct Groups.Group",
+          "name": "",
+          "type": "tuple"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "getGroupCreationState",
+      "outputs": [
+        {
+          "internalType": "enum BeaconDkg.State",
+          "name": "",
+          "type": "uint8"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "getGroupsRegistry",
+      "outputs": [
+        {
+          "internalType": "bytes32[]",
+          "name": "",
+          "type": "bytes32[]"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "governance",
+      "outputs": [
+        {
+          "internalType": "address",
+          "name": "",
+          "type": "address"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "groupCreationParameters",
+      "outputs": [
+        {
+          "internalType": "uint256",
+          "name": "groupCreationFrequency",
+          "type": "uint256"
+        },
+        {
+          "internalType": "uint256",
+          "name": "groupLifetime",
+          "type": "uint256"
+        },
+        {
+          "internalType": "uint256",
+          "name": "dkgResultChallengePeriodLength",
+          "type": "uint256"
+        },
+        {
+          "internalType": "uint256",
+          "name": "dkgResultChallengeExtraGas",
+          "type": "uint256"
+        },
+        {
+          "internalType": "uint256",
+          "name": "dkgResultSubmissionTimeout",
+          "type": "uint256"
+        },
+        {
+          "internalType": "uint256",
+          "name": "dkgSubmitterPrecedencePeriodLength",
+          "type": "uint256"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "hasDkgTimedOut",
+      "outputs": [
+        {
+          "internalType": "bool",
+          "name": "",
+          "type": "bool"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "uint64",
+          "name": "",
+          "type": "uint64"
+        }
+      ],
+      "name": "inactivityClaimNonce",
+      "outputs": [
+        {
+          "internalType": "uint256",
+          "name": "",
+          "type": "uint256"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        },
+        {
+          "internalType": "uint96",
+          "name": "fromAmount",
+          "type": "uint96"
+        },
+        {
+          "internalType": "uint96",
+          "name": "toAmount",
+          "type": "uint96"
+        }
+      ],
+      "name": "involuntaryAuthorizationDecrease",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "operator",
+          "type": "address"
+        }
+      ],
+      "name": "isOperatorInPool",
+      "outputs": [
+        {
+          "internalType": "bool",
+          "name": "",
+          "type": "bool"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "operator",
+          "type": "address"
+        }
+      ],
+      "name": "isOperatorUpToDate",
+      "outputs": [
+        {
+          "internalType": "bool",
+          "name": "",
+          "type": "bool"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "isRelayRequestInProgress",
+      "outputs": [
+        {
+          "internalType": "bool",
+          "name": "",
+          "type": "bool"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "joinSortitionPool",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "minimumAuthorization",
+      "outputs": [
+        {
+          "internalType": "uint96",
+          "name": "",
+          "type": "uint96"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "notifyDkgTimeout",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "components": [
+            {
+              "internalType": "uint64",
+              "name": "groupId",
+              "type": "uint64"
+            },
+            {
+              "internalType": "uint256[]",
+              "name": "inactiveMembersIndices",
+              "type": "uint256[]"
+            },
+            {
+              "internalType": "bytes",
+              "name": "signatures",
+              "type": "bytes"
+            },
+            {
+              "internalType": "uint256[]",
+              "name": "signingMembersIndices",
+              "type": "uint256[]"
+            }
+          ],
+          "internalType": "struct BeaconInactivity.Claim",
+          "name": "claim",
+          "type": "tuple"
+        },
+        {
+          "internalType": "uint256",
+          "name": "nonce",
+          "type": "uint256"
+        },
+        {
+          "internalType": "uint32[]",
+          "name": "groupMembers",
+          "type": "uint32[]"
+        }
+      ],
+      "name": "notifyOperatorInactivity",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "operator",
+          "type": "address"
+        }
+      ],
+      "name": "operatorToStakingProvider",
+      "outputs": [
+        {
+          "internalType": "address",
+          "name": "",
+          "type": "address"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        }
+      ],
+      "name": "pendingAuthorizationDecrease",
+      "outputs": [
+        {
+          "internalType": "uint96",
+          "name": "",
+          "type": "uint96"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "operator",
+          "type": "address"
+        }
+      ],
+      "name": "registerOperator",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "reimbursementPool",
+      "outputs": [
+        {
+          "internalType": "contract ReimbursementPool",
+          "name": "",
+          "type": "address"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "relayEntryParameters",
+      "outputs": [
+        {
+          "internalType": "uint256",
+          "name": "relayEntrySoftTimeout",
+          "type": "uint256"
+        },
+        {
+          "internalType": "uint256",
+          "name": "relayEntryHardTimeout",
+          "type": "uint256"
+        },
+        {
+          "internalType": "uint256",
+          "name": "callbackGasLimit",
+          "type": "uint256"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        }
+      ],
+      "name": "remainingAuthorizationDecreaseDelay",
+      "outputs": [
+        {
+          "internalType": "uint64",
+          "name": "",
+          "type": "uint64"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "uint32[]",
+          "name": "groupMembers",
+          "type": "uint32[]"
+        }
+      ],
+      "name": "reportRelayEntryTimeout",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "bytes",
+          "name": "signedMsgSender",
+          "type": "bytes"
+        },
+        {
+          "internalType": "uint64",
+          "name": "groupId",
+          "type": "uint64"
+        },
+        {
+          "internalType": "uint32[]",
+          "name": "groupMembers",
+          "type": "uint32[]"
+        }
+      ],
+      "name": "reportUnauthorizedSigning",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "contract IRandomBeaconConsumer",
+          "name": "callbackContract",
+          "type": "address"
+        }
+      ],
+      "name": "requestRelayEntry",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "rewardParameters",
+      "outputs": [
+        {
+          "internalType": "uint256",
+          "name": "sortitionPoolRewardsBanDuration",
+          "type": "uint256"
+        },
+        {
+          "internalType": "uint256",
+          "name": "relayEntryTimeoutNotificationRewardMultiplier",
+          "type": "uint256"
+        },
+        {
+          "internalType": "uint256",
+          "name": "unauthorizedSigningNotificationRewardMultiplier",
+          "type": "uint256"
+        },
+        {
+          "internalType": "uint256",
+          "name": "dkgMaliciousResultNotificationRewardMultiplier",
+          "type": "uint256"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "selectGroup",
+      "outputs": [
+        {
+          "internalType": "uint32[]",
+          "name": "",
+          "type": "uint32[]"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "requester",
+          "type": "address"
+        },
+        {
+          "internalType": "bool",
+          "name": "isAuthorized",
+          "type": "bool"
+        }
+      ],
+      "name": "setRequesterAuthorization",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "slashingParameters",
+      "outputs": [
+        {
+          "internalType": "uint96",
+          "name": "relayEntrySubmissionFailureSlashingAmount",
+          "type": "uint96"
+        },
+        {
+          "internalType": "uint96",
+          "name": "maliciousDkgResultSlashingAmount",
+          "type": "uint96"
+        },
+        {
+          "internalType": "uint96",
+          "name": "unauthorizedSigningSlashingAmount",
+          "type": "uint96"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "sortitionPool",
+      "outputs": [
+        {
+          "internalType": "contract SortitionPool",
+          "name": "",
+          "type": "address"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "staking",
+      "outputs": [
+        {
+          "internalType": "contract IStaking",
+          "name": "",
+          "type": "address"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        }
+      ],
+      "name": "stakingProviderToOperator",
+      "outputs": [
+        {
+          "internalType": "address",
+          "name": "",
+          "type": "address"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "components": [
+            {
+              "internalType": "uint256",
+              "name": "submitterMemberIndex",
+              "type": "uint256"
+            },
+            {
+              "internalType": "bytes",
+              "name": "groupPubKey",
+              "type": "bytes"
+            },
+            {
+              "internalType": "uint8[]",
+              "name": "misbehavedMembersIndices",
+              "type": "uint8[]"
+            },
+            {
+              "internalType": "bytes",
+              "name": "signatures",
+              "type": "bytes"
+            },
+            {
+              "internalType": "uint256[]",
+              "name": "signingMembersIndices",
+              "type": "uint256[]"
+            },
+            {
+              "internalType": "uint32[]",
+              "name": "members",
+              "type": "uint32[]"
+            },
+            {
+              "internalType": "bytes32",
+              "name": "membersHash",
+              "type": "bytes32"
+            }
+          ],
+          "internalType": "struct BeaconDkg.Result",
+          "name": "dkgResult",
+          "type": "tuple"
+        }
+      ],
+      "name": "submitDkgResult",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "bytes",
+          "name": "entry",
+          "type": "bytes"
+        },
+        {
+          "internalType": "uint32[]",
+          "name": "groupMembers",
+          "type": "uint32[]"
+        }
+      ],
+      "name": "submitRelayEntry",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "bytes",
+          "name": "entry",
+          "type": "bytes"
+        }
+      ],
+      "name": "submitRelayEntry",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "tToken",
+      "outputs": [
+        {
+          "internalType": "contract IERC20",
+          "name": "",
+          "type": "address"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "newGovernance",
+          "type": "address"
+        }
+      ],
+      "name": "transferGovernance",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "uint96",
+          "name": "_minimumAuthorization",
+          "type": "uint96"
+        },
+        {
+          "internalType": "uint64",
+          "name": "_authorizationDecreaseDelay",
+          "type": "uint64"
+        },
+        {
+          "internalType": "uint64",
+          "name": "_authorizationDecreaseChangePeriod",
+          "type": "uint64"
+        }
+      ],
+      "name": "updateAuthorizationParameters",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "uint256",
+          "name": "dkgResultSubmissionGas",
+          "type": "uint256"
+        },
+        {
+          "internalType": "uint256",
+          "name": "dkgResultApprovalGasOffset",
+          "type": "uint256"
+        },
+        {
+          "internalType": "uint256",
+          "name": "notifyOperatorInactivityGasOffset",
+          "type": "uint256"
+        },
+        {
+          "internalType": "uint256",
+          "name": "relayEntrySubmissionGasOffset",
+          "type": "uint256"
+        }
+      ],
+      "name": "updateGasParameters",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "uint256",
+          "name": "groupCreationFrequency",
+          "type": "uint256"
+        },
+        {
+          "internalType": "uint256",
+          "name": "groupLifetime",
+          "type": "uint256"
+        },
+        {
+          "internalType": "uint256",
+          "name": "dkgResultChallengePeriodLength",
+          "type": "uint256"
+        },
+        {
+          "internalType": "uint256",
+          "name": "dkgResultChallengeExtraGas",
+          "type": "uint256"
+        },
+        {
+          "internalType": "uint256",
+          "name": "dkgResultSubmissionTimeout",
+          "type": "uint256"
+        },
+        {
+          "internalType": "uint256",
+          "name": "dkgSubmitterPrecedencePeriodLength",
+          "type": "uint256"
+        }
+      ],
+      "name": "updateGroupCreationParameters",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "operator",
+          "type": "address"
+        }
+      ],
+      "name": "updateOperatorStatus",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "contract ReimbursementPool",
+          "name": "_reimbursementPool",
+          "type": "address"
+        }
+      ],
+      "name": "updateReimbursementPool",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "uint256",
+          "name": "relayEntrySoftTimeout",
+          "type": "uint256"
+        },
+        {
+          "internalType": "uint256",
+          "name": "relayEntryHardTimeout",
+          "type": "uint256"
+        },
+        {
+          "internalType": "uint256",
+          "name": "callbackGasLimit",
+          "type": "uint256"
+        }
+      ],
+      "name": "updateRelayEntryParameters",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "uint256",
+          "name": "sortitionPoolRewardsBanDuration",
+          "type": "uint256"
+        },
+        {
+          "internalType": "uint256",
+          "name": "relayEntryTimeoutNotificationRewardMultiplier",
+          "type": "uint256"
+        },
+        {
+          "internalType": "uint256",
+          "name": "unauthorizedSigningNotificationRewardMultiplier",
+          "type": "uint256"
+        },
+        {
+          "internalType": "uint256",
+          "name": "dkgMaliciousResultNotificationRewardMultiplier",
+          "type": "uint256"
+        }
+      ],
+      "name": "updateRewardParameters",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "uint96",
+          "name": "relayEntrySubmissionFailureSlashingAmount",
+          "type": "uint96"
+        },
+        {
+          "internalType": "uint96",
+          "name": "maliciousDkgResultSlashingAmount",
+          "type": "uint96"
+        },
+        {
+          "internalType": "uint96",
+          "name": "unauthorizedSigningSlashingAmount",
+          "type": "uint96"
+        }
+      ],
+      "name": "updateSlashingParameters",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "recipient",
+          "type": "address"
+        }
+      ],
+      "name": "withdrawIneligibleRewards",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "stakingProvider",
+          "type": "address"
+        }
+      ],
+      "name": "withdrawRewards",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    }
+  ],
+  "transactionHash": "0x0b9ff095d08d6428936ff1aa63cf69c05bfc09756c986288c9c5b1e48fc9e80f",
+  "receipt": {
+    "to": null,
+    "from": "0x123694886DBf5Ac94DDA07135349534536D14cAf",
+    "contractAddress": "0x5499f54b4A1CB4816eefCf78962040461be3D80b",
+    "transactionIndex": 134,
+    "gasUsed": "5967896",
+    "logsBloom": "0x00000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000800000000000000000000000000002000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000",
+    "blockHash": "0x2a91baafb0d14ee461a2d80f4a45bd592d15716538c3509c470ae00676be2213",
+    "transactionHash": "0x0b9ff095d08d6428936ff1aa63cf69c05bfc09756c986288c9c5b1e48fc9e80f",
+    "logs": [
+      {
+        "transactionIndex": 134,
+        "blockNumber": 15638933,
+        "transactionHash": "0x0b9ff095d08d6428936ff1aa63cf69c05bfc09756c986288c9c5b1e48fc9e80f",
+        "address": "0x5499f54b4A1CB4816eefCf78962040461be3D80b",
+        "topics": [
+          "0x5f56bee8cffbe9a78652a74a60705edede02af10b0bbb888ca44b79a0d42ce80"
+        ],
+        "data": "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000123694886dbf5ac94dda07135349534536d14caf",
+        "logIndex": 219,
+        "blockHash": "0x2a91baafb0d14ee461a2d80f4a45bd592d15716538c3509c470ae00676be2213"
+      }
+    ],
+    "blockNumber": 15638933,
+    "cumulativeGasUsed": "18819477",
+    "status": 1,
+    "byzantium": true
+  },
+  "args": [
+    "0x4e4cBA3779d56386ED43631b4dCD6d8EacEcBCF6",
+    "0xCdF7028ceAB81fA0C6971208e83fa7872994beE5",
+    "0x01B67b1194C75264d06F808A921228a95C765dd7",
+    "0x4EDC83c5C5B0C41A594371485554B95280653f94",
+    "0x8adF3f35dBE4026112bCFc078872bcb967732Ea8"
+  ],
+  "numDeployments": 1,
+  "solcInputHash": "315dd8aa56418c14cbdc8d65adaa494b",
+  "libraries": {
+    "BLS": "0x6552059B6eFc6aA4AE3ea45f28ED4D92acE020cD",
+    "BeaconAuthorization": "0x632c2d58Ad870fbd4569da0A4E82dDf4B56E83E8",
+    "BeaconDkg": "0x024a697788918007592572f7CD020df2bC2ABD84",
+    "BeaconInactivity": "0x67A26f2ebDB2448605936Fe9a5f496cDA7941Ec0"
+  },
+  "devdoc": {
+    "details": "Should be owned by the governance contract controlling Random Beacon      parameters.",
+    "kind": "dev",
+    "methods": {
+      "approveDkgResult((uint256,bytes,uint8[],bytes,uint256[],uint32[],bytes32))": {
+        "params": {
+          "dkgResult": "Result to approve. Must match the submitted result        stored during `submitDkgResult`."
+        }
+      },
+      "authorizationDecreaseRequested(address,uint96,uint96)": {
+        "details": "Can only be called by T staking contract."
+      },
+      "authorizationIncreased(address,uint96,uint96)": {
+        "details": "Can only be called by T staking contract."
+      },
+      "authorizationParameters()": {
+        "details": "The minimum authorization is also returned by `minimumAuthorization()`      function, as a requirement of `IApplication` interface.",
+        "returns": {
+          "authorizationDecreaseChangePeriod": "Authorization decrease change        period in seconds. It is the time, before authorization decrease        delay end, during which the pending authorization decrease        request can be overwritten.        If set to 0, pending authorization decrease request can not be        overwritten until the entire `authorizationDecreaseDelay` ends.        If set to value equal `authorizationDecreaseDelay`, request can        always be overwritten.",
+          "authorizationDecreaseDelay": "Delay in seconds that needs to pass         between the time authorization decrease is requested and the         time that request gets approved. Protects against free-riders         earning rewards and not being active in the network.",
+          "minimumAuthorization": "The minimum authorization amount required         so that operator can participate in the random beacon. This         amount is required to execute slashing for providing a malicious         DKG result or when a relay entry times out."
+        }
+      },
+      "challengeDkgResult((uint256,bytes,uint8[],bytes,uint256[],uint32[],bytes32))": {
+        "details": "Due to EIP-150 1/64 of the gas is not forwarded to the call, and      will be kept to execute the remaining operations in the function      after the call inside the try-catch. To eliminate a class of      attacks related to the gas limit manipulation, this function      requires an extra amount of gas to be left at the end of the      execution.",
+        "params": {
+          "dkgResult": "Result to challenge. Must match the submitted result        stored during `submitDkgResult`."
+        }
+      },
+      "constructor": {
+        "details": "Assigns initial values to parameters to make the beacon work      safely. These parameters are just proposed defaults and they might      be updated with `update*` functions after the contract deployment      and before transferring the ownership to the governance contract."
+      },
+      "gasParameters()": {
+        "returns": {
+          "dkgResultApprovalGasOffset": "Gas that is meant to balance the DKG         result approval's overall cost.",
+          "dkgResultSubmissionGas": "Calculated gas cost for submitting a DKG         result. This will be refunded as part of the DKG approval         process.",
+          "notifyOperatorInactivityGasOffset": "Gas that is meant to balance         the operator inactivity notification cost.",
+          "relayEntrySubmissionGasOffset": "Gas that is meant to balance the         relay entry submission cost."
+        }
+      },
+      "groupCreationParameters()": {
+        "returns": {
+          "dkgResultChallengeExtraGas": "The extra gas required to be left at         the end of the challenge DKG result transaction.",
+          "dkgResultChallengePeriodLength": "The number of blocks for which         a DKG result can be challenged. Anyone can challenge DKG result         for a certain number of blocks before the result is fully         accepted and the group registered in the pool of active groups.         If the challenge gets accepted, all operators who signed the         malicious result get slashed for and the notifier gets rewarded.",
+          "dkgResultSubmissionTimeout": "Timeout in blocks for a group to         submit the DKG result. All members are eligible to submit the         DKG result. If `dkgResultSubmissionTimeout` passes without the         DKG result submitted, DKG is considered as timed out and no DKG         result for this group creation can be submitted anymore.",
+          "dkgSubmitterPrecedencePeriodLength": "Time during the DKG result         approval stage when the submitter of the DKG result takes the         precedence to approve the DKG result. After this time passes         anyone can approve the DKG result.",
+          "groupCreationFrequency": "The frequency of a new group creation.         Groups are created with a fixed frequency of relay requests.",
+          "groupLifetime": "Group lifetime in blocks. When a group reached its         lifetime, it is no longer selected for new relay requests but         may still be responsible for submitting relay entry if relay         request assigned to that group is still pending."
+        }
+      },
+      "hasDkgTimedOut()": {
+        "returns": {
+          "_0": "True if DKG timed out, false otherwise."
+        }
+      },
+      "isRelayRequestInProgress()": {
+        "returns": {
+          "_0": "Flag indicating whether a relay entry request is currently         in progress."
+        }
+      },
+      "notifyOperatorInactivity((uint64,uint256[],bytes,uint256[]),uint256,uint32[])": {
+        "params": {
+          "claim": "Operator inactivity claim.",
+          "groupMembers": "Identifiers of group members.",
+          "nonce": "Current inactivity claim nonce for the given group. Must        be the same as the stored one."
+        }
+      },
+      "relayEntryParameters()": {
+        "returns": {
+          "callbackGasLimit": "Relay entry callback gas limit. This is the gas         limit with which callback function provided in the relay request         transaction is executed. The callback is executed with a new         relay entry value in the same transaction the relay entry is         submitted.",
+          "relayEntryHardTimeout": "Hard timeout in blocks for a group to         submit the relay entry. After the soft timeout passes without         relay entry submitted, all group members start getting slashed.         The slashing amount increases linearly until the group submits         the relay entry or until `relayEntryHardTimeout` is reached.         When the hard timeout is reached, each group member will get         slashed for `_relayEntrySubmissionFailureSlashingAmount`.",
+          "relayEntrySoftTimeout": "Soft timeout in blocks for a group to         submit the relay entry. If the soft timeout is reached for         submitting the relay entry, the slashing starts."
+        }
+      },
+      "reportRelayEntryTimeout(uint32[])": {
+        "params": {
+          "groupMembers": "Identifiers of group members."
+        }
+      },
+      "reportUnauthorizedSigning(bytes,uint64,uint32[])": {
+        "params": {
+          "groupId": "Group that is being reported for leaking a private key.",
+          "groupMembers": "Identifiers of group members.",
+          "signedMsgSender": "Signature of the sender's address as a message."
+        }
+      },
+      "requestRelayEntry(address)": {
+        "params": {
+          "callbackContract": "Beacon consumer callback contract."
+        }
+      },
+      "rewardParameters()": {
+        "returns": {
+          "dkgMaliciousResultNotificationRewardMultiplier": "Percentage of the         staking contract malicious behavior notification reward which         will be transferred to the notifier reporting about a malicious         DKG result. Notifiers are rewarded from a notifiers treasury         pool. For example, if notification reward is 1000 and the value         of the multiplier is 5, the notifier will receive:         5% of 1000 = 50 per each operator affected.",
+          "relayEntryTimeoutNotificationRewardMultiplier": "Percentage of the         staking contract malicious behavior notification reward which         will be transferred to the notifier reporting about relay entry         timeout. Notifiers are rewarded from a notifiers treasury pool.         For example, if notification reward is 1000 and the value of the         multiplier is 5, the notifier will receive: 5% of 1000 = 50 per         each operator affected.",
+          "sortitionPoolRewardsBanDuration": "Duration of the sortition pool         rewards ban imposed on operators who misbehaved during DKG by         being inactive or disqualified and for operators that were         identified by the rest of group members as inactive via         `notifyOperatorInactivity`.",
+          "unauthorizedSigningNotificationRewardMultiplier": "Percentage of the         staking contract malicious behavior notification reward which         will be transferred to the notifier reporting about unauthorized         signing. Notifiers are rewarded from a notifiers treasury pool.         For example, if a notification reward is 1000 and the value of         the multiplier is 5, the notifier will receive: 5% of 1000 = 50         per each operator affected."
+        }
+      },
+      "selectGroup()": {
+        "returns": {
+          "_0": "IDs of selected group members."
+        }
+      },
+      "setRequesterAuthorization(address,bool)": {
+        "details": "Can be called only by the contract guvnor, which should be the      random beacon governance contract.",
+        "params": {
+          "isAuthorized": "True or false",
+          "requester": "Requester, can be a contract or EOA"
+        }
+      },
+      "slashingParameters()": {
+        "returns": {
+          "maliciousDkgResultSlashingAmount": "Slashing amount for submitting         a malicious DKG result. Every DKG result submitted can be         challenged for the time of `dkg.ResultChallengePeriodLength`.         If the DKG result submitted is challenged and proven to be         malicious, the operator who submitted the malicious result is         slashed for `maliciousDkgResultSlashingAmount`.",
+          "relayEntrySubmissionFailureSlashingAmount": "Slashing amount for         not submitting relay entry. When relay entry hard timeout is         reached without the relay entry submitted, each group member         gets slashed for `relayEntrySubmissionFailureSlashingAmount`.         If the relay entry gets submitted after the soft timeout, but         before the hard timeout, each group member gets slashed         proportionally to `relayEntrySubmissionFailureSlashingAmount`         and the time passed since the soft deadline.",
+          "unauthorizedSigningSlashingAmount": "Slashing amount when an         unauthorized signing has been proved, which means the private         key leaked and all the group members should be punished."
+        }
+      },
+      "submitDkgResult((uint256,bytes,uint8[],bytes,uint256[],uint32[],bytes32))": {
+        "params": {
+          "dkgResult": "DKG result."
+        }
+      },
+      "submitRelayEntry(bytes)": {
+        "params": {
+          "entry": "Group BLS signature over the previous entry."
+        }
+      },
+      "submitRelayEntry(bytes,uint32[])": {
+        "params": {
+          "entry": "Group BLS signature over the previous entry.",
+          "groupMembers": "Identifiers of group members."
+        }
+      },
+      "updateAuthorizationParameters(uint96,uint64,uint64)": {
+        "details": "Can be called only by the contract guvnor, which should be the      random beacon governance contract. The caller is responsible for      validating parameters.",
+        "params": {
+          "_authorizationDecreaseChangePeriod": "New authorization decrease        change period in seconds",
+          "_authorizationDecreaseDelay": "New authorization decrease delay in        seconds",
+          "_minimumAuthorization": "New minimum authorization amount"
+        }
+      },
+      "updateGasParameters(uint256,uint256,uint256,uint256)": {
+        "details": "Can be called only by the contract guvnor, which should be the      random beacon governance contract. The caller is responsible for      validating parameters.",
+        "params": {
+          "dkgResultApprovalGasOffset": "New DKG result approval gas offset",
+          "dkgResultSubmissionGas": "New DKG result submission gas",
+          "notifyOperatorInactivityGasOffset": "New operator inactivity        notification gas offset",
+          "relayEntrySubmissionGasOffset": "New relay entry submission gas        offset"
+        }
+      },
+      "updateGroupCreationParameters(uint256,uint256,uint256,uint256,uint256,uint256)": {
+        "details": "Can be called only by the contract guvnor, which should be the      random beacon governance contract. The caller is responsible for      validating parameters.",
+        "params": {
+          "dkgResultChallengeExtraGas": "New DKG result challenge extra gas",
+          "dkgResultChallengePeriodLength": "New DKG result challenge period        length",
+          "dkgResultSubmissionTimeout": "New DKG result submission timeout",
+          "dkgSubmitterPrecedencePeriodLength": "New DKG result submitter        precedence period length",
+          "groupCreationFrequency": "New group creation frequency",
+          "groupLifetime": "New group lifetime in blocks"
+        }
+      },
+      "updateRelayEntryParameters(uint256,uint256,uint256)": {
+        "details": "Can be called only by the contract guvnor, which should be the      random beacon governance contract. The caller is responsible for      validating parameters.",
+        "params": {
+          "callbackGasLimit": "New callback gas limit",
+          "relayEntryHardTimeout": "New relay entry hard timeout",
+          "relayEntrySoftTimeout": "New relay entry submission soft timeout"
+        }
+      },
+      "updateRewardParameters(uint256,uint256,uint256,uint256)": {
+        "details": "Can be called only by the contract guvnor, which should be the      random beacon governance contract. The caller is responsible for      validating parameters.",
+        "params": {
+          "dkgMaliciousResultNotificationRewardMultiplier": "New value of the        DKG malicious result notification reward multiplier",
+          "relayEntryTimeoutNotificationRewardMultiplier": "New value of the        relay entry timeout notification reward multiplier",
+          "sortitionPoolRewardsBanDuration": "New sortition pool rewards        ban duration in seconds.",
+          "unauthorizedSigningNotificationRewardMultiplier": "New value of the        unauthorized signing notification reward multiplier"
+        }
+      },
+      "updateSlashingParameters(uint96,uint96,uint96)": {
+        "details": "Can be called only by the contract guvnor, which should be the      random beacon governance contract. The caller is responsible for      validating parameters.",
+        "params": {
+          "maliciousDkgResultSlashingAmount": "New malicious DKG result        slashing amount",
+          "relayEntrySubmissionFailureSlashingAmount": "New relay entry        submission failure amount",
+          "unauthorizedSigningSlashingAmount": "New unauthorized signing        slashing amount"
+        }
+      },
+      "withdrawIneligibleRewards(address)": {
+        "details": "Can be called only by the contract guvnor, which should be the      random beacon governance contract.",
+        "params": {
+          "recipient": "Recipient of withdrawn rewards."
+        }
+      },
+      "withdrawRewards(address)": {
+        "details": "Emits `RewardsWithdrawn` event."
+      }
+    },
+    "title": "Keep Random Beacon",
+    "version": 1
+  },
+  "userdoc": {
+    "kind": "user",
+    "methods": {
+      "approveAuthorizationDecrease(address)": {
+        "notice": "Approves the previously registered authorization decrease         request. Reverts if authorization decrease delay has not passed         yet or if the authorization decrease was not requested for the         given staking provider."
+      },
+      "approveDkgResult((uint256,bytes,uint8[],bytes,uint256[],uint32[],bytes32))": {
+        "notice": "Approves DKG result. Can be called when the challenge period for         the submitted result is finished. Considers the submitted result         as valid, bans misbehaved group members from the sortition pool         rewards, and completes the group creation by activating the         candidate group. For the first `submitterPrecedencePeriodLength`         blocks after the end of the challenge period can be called only         by the DKG result submitter. After that time, can be called by         anyone."
+      },
+      "authorizationDecreaseRequested(address,uint96,uint96)": {
+        "notice": "Used by T staking contract to inform the beacon that the         authorization decrease for the given staking provider has been         requested.         Reverts if the amount after deauthorization would be non-zero         and lower than the minimum authorization.         Reverts if another authorization decrease request is pending for         the staking provider and not enough time passed since the         original request (see `authorizationDecreaseChangePeriod`).         If the operator is not known (`registerOperator` was not called)         it lets to `approveAuthorizationDecrease` immediately. If the         operator is known (`registerOperator` was called), the operator         needs to update state of the sortition pool with a call to         `joinSortitionPool` or `updateOperatorStatus`. After the         sortition pool state is in sync, authorization decrease delay         starts.         After authorization decrease delay passes, authorization         decrease request needs to be approved with a call to         `approveAuthorizationDecrease` function.         If there is a pending authorization decrease request, it is         overwritten, but only if enough time passed since the original         request. Otherwise, the function reverts."
+      },
+      "authorizationIncreased(address,uint96,uint96)": {
+        "notice": "Used by T staking contract to inform the beacon that the         authorized stake amount for the given staking provider increased.         Reverts if the authorization amount is below the minimum.         The function is not updating the sortition pool. Sortition pool         state needs to be updated by the operator with a call to         `joinSortitionPool` or `updateOperatorStatus`."
+      },
+      "authorizationParameters()": {
+        "notice": "Returns authorization-related parameters of the beacon."
+      },
+      "authorizedRequesters(address)": {
+        "notice": "Authorized addresses that can request a relay entry."
+      },
+      "availableRewards(address)": {
+        "notice": "Returns the amount of rewards available for withdrawal for the         given staking provider. Reverts if staking provider has not         registered the operator address."
+      },
+      "challengeDkgResult((uint256,bytes,uint8[],bytes,uint256[],uint32[],bytes32))": {
+        "notice": "Challenges DKG result. If the submitted result is proved to be         invalid it reverts the DKG back to the result submission phase.         It removes a candidate group that was previously registered with         the DKG result submission."
+      },
+      "eligibleStake(address)": {
+        "notice": "Returns the current value of the staking provider's eligible         stake. Eligible stake is defined as the currently authorized         stake minus the pending authorization decrease. Eligible stake         is what is used for operator's weight in the sortition pool.         If the authorized stake minus the pending authorization decrease         is below the minimum authorization, eligible stake is 0."
+      },
+      "gasParameters()": {
+        "notice": "Returns gas-related parameters of the beacon."
+      },
+      "genesis()": {
+        "notice": "Triggers group selection if there are no active groups."
+      },
+      "getGroupCreationState()": {
+        "notice": "Check current group creation state."
+      },
+      "groupCreationParameters()": {
+        "notice": "Returns group-creation-related parameters of the beacon."
+      },
+      "hasDkgTimedOut()": {
+        "notice": "Checks if DKG timed out. The DKG timeout period includes time required         for off-chain protocol execution and time for the result publication         for all group members. After this time result cannot be submitted         and DKG can be notified about the timeout."
+      },
+      "inactivityClaimNonce(uint64)": {
+        "notice": "Stores current operator inactivity claim nonce for given group.         Each claim is made with an unique nonce which protects         against claim replay."
+      },
+      "involuntaryAuthorizationDecrease(address,uint96,uint96)": {
+        "notice": "Used by T staking contract to inform the beacon the         authorization has been decreased for the given staking provider         involuntarily, as a result of slashing.         If the operator is not known (`registerOperator` was not called)         the function does nothing. The operator was never in a sortition         pool so there is nothing to update.         If the operator is known, sortition pool is unlocked, and the         operator is in the sortition pool, the sortition pool state is         updated. If the sortition pool is locked, update needs to be         postponed. Every other staker is incentivized to call         `updateOperatorStatus` for the problematic operator to increase         their own rewards in the pool."
+      },
+      "isOperatorInPool(address)": {
+        "notice": "Returns true if the given operator is in the sortition pool.         Otherwise, returns false."
+      },
+      "isOperatorUpToDate(address)": {
+        "notice": "Checks if the operator's authorized stake is in sync with         operator's weight in the sortition pool.         If the operator is not in the sortition pool and their         authorized stake is non-zero, function returns false."
+      },
+      "joinSortitionPool()": {
+        "notice": "Lets the operator join the sortition pool. The operator address         must be known - before calling this function, it has to be         appointed by the staking provider by calling `registerOperator`.         Also, the operator must have the minimum authorization required         by the beacon. Function reverts if there is no minimum stake         authorized or if the operator is not known. If there was an         authorization decrease requested, it is activated by starting         the authorization decrease delay."
+      },
+      "minimumAuthorization()": {
+        "notice": "The minimum authorization amount required so that operator can         participate in the random beacon. This amount is required to         execute slashing for providing a malicious DKG result or when         a relay entry times out."
+      },
+      "notifyDkgTimeout()": {
+        "notice": "Notifies about DKG timeout."
+      },
+      "notifyOperatorInactivity((uint64,uint256[],bytes,uint256[]),uint256,uint32[])": {
+        "notice": "Notifies about operators who are inactive. Using this function,         a majority of the group can decide about punishing specific         group members who constantly fail doing their job. If the provided         claim is proved to be valid and signed by sufficient number         of group members, operators of members deemed as inactive are         banned for sortition pool rewards for duration specified by         `_sortitionPoolRewardsBanDuration` parameter. The sender of         the claim must be one of the claim signers. This function can be         called only for active and non-terminated groups."
+      },
+      "operatorToStakingProvider(address)": {
+        "notice": "Returns staking provider of the given operator."
+      },
+      "pendingAuthorizationDecrease(address)": {
+        "notice": "Returns the amount of stake that is pending authorization         decrease for the given staking provider. If no authorization         decrease has been requested, returns zero."
+      },
+      "registerOperator(address)": {
+        "notice": "Used by staking provider to set operator address that will         operate a node. The given staking provider can set operator         address only one time. The operator address can not be changed         and must be unique. Reverts if the operator is already set for         the staking provider or if the operator address is already in         use. Reverts if there is a pending authorization decrease for         the staking provider."
+      },
+      "relayEntryParameters()": {
+        "notice": "Returns relay-entry-related parameters of the beacon."
+      },
+      "remainingAuthorizationDecreaseDelay(address)": {
+        "notice": "Returns the remaining time in seconds that needs to pass before         the requested authorization decrease can be approved.         If the sortition pool state was not updated yet by the operator         after requesting the authorization decrease, returns         `type(uint64).max`."
+      },
+      "reportRelayEntryTimeout(uint32[])": {
+        "notice": "Reports a relay entry timeout."
+      },
+      "reportUnauthorizedSigning(bytes,uint64,uint32[])": {
+        "notice": "Reports unauthorized groups signing. Must provide a valid signature         of the sender's address as a message. Successful signature         verification means the private key has been leaked and all group         members should be punished by slashing their tokens. Group has         to be active or expired. Unauthorized signing cannot be reported         for a terminated group. In case of reporting unauthorized         signing for a terminated group, or when the signature is invalid,         function reverts."
+      },
+      "requestRelayEntry(address)": {
+        "notice": "Creates a request to generate a new relay entry, which will         include a random number (by signing the previous entry's         random number). Requester must be previously authorized by the         governance."
+      },
+      "rewardParameters()": {
+        "notice": "Returns reward-related parameters of the beacon."
+      },
+      "selectGroup()": {
+        "notice": "Selects a new group of operators. Can only be called when DKG         is in progress and the pool is locked.         At least one operator has to be registered in the pool,         otherwise the function fails reverting the transaction."
+      },
+      "setRequesterAuthorization(address,bool)": {
+        "notice": "Set authorization for requesters that can request a relay         entry."
+      },
+      "slashingParameters()": {
+        "notice": "Returns slashing-related parameters of the beacon."
+      },
+      "stakingProviderToOperator(address)": {
+        "notice": "Returns operator registered for the given staking provider."
+      },
+      "submitDkgResult((uint256,bytes,uint8[],bytes,uint256[],uint32[],bytes32))": {
+        "notice": "`\\x19Ethereum signed message:\\n` before signing, so the message to      sign is:      `\\x19Ethereum signed message:\\n${keccak256(chainID,groupPubKey,misbehaved,startBlock)}`"
+      },
+      "submitRelayEntry(bytes)": {
+        "notice": "Creates a new relay entry. Gas-optimized version that can be         called only before the soft timeout. This should be the majority         of cases."
+      },
+      "submitRelayEntry(bytes,uint32[])": {
+        "notice": "Creates a new relay entry."
+      },
+      "transferGovernance(address)": {
+        "notice": "Transfers governance of the contract to `newGovernance`."
+      },
+      "updateAuthorizationParameters(uint96,uint64,uint64)": {
+        "notice": "Updates the values of authorization parameters."
+      },
+      "updateGasParameters(uint256,uint256,uint256,uint256)": {
+        "notice": "Updates the values of gas parameters."
+      },
+      "updateGroupCreationParameters(uint256,uint256,uint256,uint256,uint256,uint256)": {
+        "notice": "Updates the values of group creation parameters."
+      },
+      "updateOperatorStatus(address)": {
+        "notice": "Updates status of the operator in the sortition pool. If there         was an authorization decrease requested, it is activated by         starting the authorization decrease delay.         Function reverts if the operator is not known."
+      },
+      "updateRelayEntryParameters(uint256,uint256,uint256)": {
+        "notice": "Updates the values of relay entry parameters."
+      },
+      "updateRewardParameters(uint256,uint256,uint256,uint256)": {
+        "notice": "Updates the values of reward parameters."
+      },
+      "updateSlashingParameters(uint96,uint96,uint96)": {
+        "notice": "Updates the values of slashing parameters."
+      },
+      "withdrawIneligibleRewards(address)": {
+        "notice": "Withdraws rewards belonging to operators marked as ineligible         for sortition pool rewards."
+      },
+      "withdrawRewards(address)": {
+        "notice": "Withdraws application rewards for the given staking provider.         Rewards are withdrawn to the staking provider's beneficiary         address set in the staking contract. Reverts if staking provider         has not registered the operator address."
+      }
+    },
+    "notice": "Keep Random Beacon contract. It lets to request a new         relay entry and validates the new relay entry provided by the         network. This contract is in charge of all other Random Beacon         activities such as group lifecycle or slashing.",
+    "version": 1
+  },
+  "storageLayout": {
+    "storage": [
+      {
+        "astId": 9746,
+        "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+        "label": "governance",
+        "offset": 0,
+        "slot": "0",
+        "type": "t_address"
+      },
+      {
+        "astId": 9750,
+        "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+        "label": "__gap",
+        "offset": 0,
+        "slot": "1",
+        "type": "t_array(t_uint256)49_storage"
+      },
+      {
+        "astId": 14627,
+        "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+        "label": "reimbursementPool",
+        "offset": 0,
+        "slot": "50",
+        "type": "t_contract(ReimbursementPool)14957"
+      },
+      {
+        "astId": 14631,
+        "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+        "label": "__gap",
+        "offset": 0,
+        "slot": "51",
+        "type": "t_array(t_uint256)49_storage"
+      },
+      {
+        "astId": 9874,
+        "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+        "label": "_callbackGasLimit",
+        "offset": 0,
+        "slot": "100",
+        "type": "t_uint256"
+      },
+      {
+        "astId": 9877,
+        "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+        "label": "_groupCreationFrequency",
+        "offset": 0,
+        "slot": "101",
+        "type": "t_uint256"
+      },
+      {
+        "astId": 9880,
+        "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+        "label": "_maliciousDkgResultSlashingAmount",
+        "offset": 0,
+        "slot": "102",
+        "type": "t_uint96"
+      },
+      {
+        "astId": 9883,
+        "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+        "label": "_unauthorizedSigningSlashingAmount",
+        "offset": 12,
+        "slot": "102",
+        "type": "t_uint96"
+      },
+      {
+        "astId": 9886,
+        "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+        "label": "_sortitionPoolRewardsBanDuration",
+        "offset": 0,
+        "slot": "103",
+        "type": "t_uint256"
+      },
+      {
+        "astId": 9889,
+        "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+        "label": "_relayEntryTimeoutNotificationRewardMultiplier",
+        "offset": 0,
+        "slot": "104",
+        "type": "t_uint256"
+      },
+      {
+        "astId": 9892,
+        "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+        "label": "_unauthorizedSigningNotificationRewardMultiplier",
+        "offset": 0,
+        "slot": "105",
+        "type": "t_uint256"
+      },
+      {
+        "astId": 9895,
+        "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+        "label": "_dkgMaliciousResultNotificationRewardMultiplier",
+        "offset": 0,
+        "slot": "106",
+        "type": "t_uint256"
+      },
+      {
+        "astId": 9898,
+        "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+        "label": "_dkgResultSubmissionGas",
+        "offset": 0,
+        "slot": "107",
+        "type": "t_uint256"
+      },
+      {
+        "astId": 9901,
+        "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+        "label": "_dkgResultApprovalGasOffset",
+        "offset": 0,
+        "slot": "108",
+        "type": "t_uint256"
+      },
+      {
+        "astId": 9904,
+        "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+        "label": "_notifyOperatorInactivityGasOffset",
+        "offset": 0,
+        "slot": "109",
+        "type": "t_uint256"
+      },
+      {
+        "astId": 9907,
+        "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+        "label": "_relayEntrySubmissionGasOffset",
+        "offset": 0,
+        "slot": "110",
+        "type": "t_uint256"
+      },
+      {
+        "astId": 9912,
+        "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+        "label": "inactivityClaimNonce",
+        "offset": 0,
+        "slot": "111",
+        "type": "t_mapping(t_uint64,t_uint256)"
+      },
+      {
+        "astId": 9917,
+        "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+        "label": "authorizedRequesters",
+        "offset": 0,
+        "slot": "112",
+        "type": "t_mapping(t_address,t_bool)"
+      },
+      {
+        "astId": 9920,
+        "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+        "label": "sortitionPool",
+        "offset": 0,
+        "slot": "113",
+        "type": "t_contract(SortitionPool)1980"
+      },
+      {
+        "astId": 9923,
+        "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+        "label": "tToken",
+        "offset": 0,
+        "slot": "114",
+        "type": "t_contract(IERC20)4111"
+      },
+      {
+        "astId": 9926,
+        "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+        "label": "staking",
+        "offset": 0,
+        "slot": "115",
+        "type": "t_contract(IStaking)9081"
+      },
+      {
+        "astId": 9929,
+        "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+        "label": "authorization",
+        "offset": 0,
+        "slot": "116",
+        "type": "t_struct(Data)16552_storage"
+      },
+      {
+        "astId": 9932,
+        "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+        "label": "dkg",
+        "offset": 0,
+        "slot": "120",
+        "type": "t_struct(Data)17482_storage"
+      },
+      {
+        "astId": 9935,
+        "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+        "label": "groups",
+        "offset": 0,
+        "slot": "131",
+        "type": "t_struct(Data)18985_storage"
+      },
+      {
+        "astId": 9938,
+        "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+        "label": "relay",
+        "offset": 0,
+        "slot": "136",
+        "type": "t_struct(Data)19879_storage"
+      },
+      {
+        "astId": 9941,
+        "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+        "label": "callback",
+        "offset": 0,
+        "slot": "140",
+        "type": "t_struct(Data)18889_storage"
+      }
+    ],
+    "types": {
+      "t_address": {
+        "encoding": "inplace",
+        "label": "address",
+        "numberOfBytes": "20"
+      },
+      "t_array(t_bytes32)dyn_storage": {
+        "base": "t_bytes32",
+        "encoding": "dynamic_array",
+        "label": "bytes32[]",
+        "numberOfBytes": "32"
+      },
+      "t_array(t_uint256)49_storage": {
+        "base": "t_uint256",
+        "encoding": "inplace",
+        "label": "uint256[49]",
+        "numberOfBytes": "1568"
+      },
+      "t_array(t_uint64)dyn_storage": {
+        "base": "t_uint64",
+        "encoding": "dynamic_array",
+        "label": "uint64[]",
+        "numberOfBytes": "32"
+      },
+      "t_bool": {
+        "encoding": "inplace",
+        "label": "bool",
+        "numberOfBytes": "1"
+      },
+      "t_bytes32": {
+        "encoding": "inplace",
+        "label": "bytes32",
+        "numberOfBytes": "32"
+      },
+      "t_bytes_storage": {
+        "encoding": "bytes",
+        "label": "bytes",
+        "numberOfBytes": "32"
+      },
+      "t_contract(BeaconDkgValidator)9741": {
+        "encoding": "inplace",
+        "label": "contract BeaconDkgValidator",
+        "numberOfBytes": "20"
+      },
+      "t_contract(IERC20)4111": {
+        "encoding": "inplace",
+        "label": "contract IERC20",
+        "numberOfBytes": "20"
+      },
+      "t_contract(IRandomBeaconConsumer)14980": {
+        "encoding": "inplace",
+        "label": "contract IRandomBeaconConsumer",
+        "numberOfBytes": "20"
+      },
+      "t_contract(IStaking)9081": {
+        "encoding": "inplace",
+        "label": "contract IStaking",
+        "numberOfBytes": "20"
+      },
+      "t_contract(ReimbursementPool)14957": {
+        "encoding": "inplace",
+        "label": "contract ReimbursementPool",
+        "numberOfBytes": "20"
+      },
+      "t_contract(SortitionPool)1980": {
+        "encoding": "inplace",
+        "label": "contract SortitionPool",
+        "numberOfBytes": "20"
+      },
+      "t_mapping(t_address,t_address)": {
+        "encoding": "mapping",
+        "key": "t_address",
+        "label": "mapping(address => address)",
+        "numberOfBytes": "32",
+        "value": "t_address"
+      },
+      "t_mapping(t_address,t_bool)": {
+        "encoding": "mapping",
+        "key": "t_address",
+        "label": "mapping(address => bool)",
+        "numberOfBytes": "32",
+        "value": "t_bool"
+      },
+      "t_mapping(t_address,t_struct(AuthorizationDecrease)16535_storage)": {
+        "encoding": "mapping",
+        "key": "t_address",
+        "label": "mapping(address => struct BeaconAuthorization.AuthorizationDecrease)",
+        "numberOfBytes": "32",
+        "value": "t_struct(AuthorizationDecrease)16535_storage"
+      },
+      "t_mapping(t_bytes32,t_struct(Group)18969_storage)": {
+        "encoding": "mapping",
+        "key": "t_bytes32",
+        "label": "mapping(bytes32 => struct Groups.Group)",
+        "numberOfBytes": "32",
+        "value": "t_struct(Group)18969_storage"
+      },
+      "t_mapping(t_uint64,t_uint256)": {
+        "encoding": "mapping",
+        "key": "t_uint64",
+        "label": "mapping(uint64 => uint256)",
+        "numberOfBytes": "32",
+        "value": "t_uint256"
+      },
+      "t_struct(AuthorizationDecrease)16535_storage": {
+        "encoding": "inplace",
+        "label": "struct BeaconAuthorization.AuthorizationDecrease",
+        "members": [
+          {
+            "astId": 16532,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "decreasingBy",
+            "offset": 0,
+            "slot": "0",
+            "type": "t_uint96"
+          },
+          {
+            "astId": 16534,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "decreasingAt",
+            "offset": 12,
+            "slot": "0",
+            "type": "t_uint64"
+          }
+        ],
+        "numberOfBytes": "32"
+      },
+      "t_struct(Data)16552_storage": {
+        "encoding": "inplace",
+        "label": "struct BeaconAuthorization.Data",
+        "members": [
+          {
+            "astId": 16538,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "parameters",
+            "offset": 0,
+            "slot": "0",
+            "type": "t_struct(Parameters)16530_storage"
+          },
+          {
+            "astId": 16542,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "stakingProviderToOperator",
+            "offset": 0,
+            "slot": "1",
+            "type": "t_mapping(t_address,t_address)"
+          },
+          {
+            "astId": 16546,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "operatorToStakingProvider",
+            "offset": 0,
+            "slot": "2",
+            "type": "t_mapping(t_address,t_address)"
+          },
+          {
+            "astId": 16551,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "pendingDecreases",
+            "offset": 0,
+            "slot": "3",
+            "type": "t_mapping(t_address,t_struct(AuthorizationDecrease)16535_storage)"
+          }
+        ],
+        "numberOfBytes": "128"
+      },
+      "t_struct(Data)17482_storage": {
+        "encoding": "inplace",
+        "label": "struct BeaconDkg.Data",
+        "members": [
+          {
+            "astId": 17465,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "sortitionPool",
+            "offset": 0,
+            "slot": "0",
+            "type": "t_contract(SortitionPool)1980"
+          },
+          {
+            "astId": 17468,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "dkgValidator",
+            "offset": 0,
+            "slot": "1",
+            "type": "t_contract(BeaconDkgValidator)9741"
+          },
+          {
+            "astId": 17471,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "parameters",
+            "offset": 0,
+            "slot": "2",
+            "type": "t_struct(Parameters)17462_storage"
+          },
+          {
+            "astId": 17473,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "startBlock",
+            "offset": 0,
+            "slot": "6",
+            "type": "t_uint256"
+          },
+          {
+            "astId": 17475,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "seed",
+            "offset": 0,
+            "slot": "7",
+            "type": "t_uint256"
+          },
+          {
+            "astId": 17477,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "resultSubmissionStartBlockOffset",
+            "offset": 0,
+            "slot": "8",
+            "type": "t_uint256"
+          },
+          {
+            "astId": 17479,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "submittedResultHash",
+            "offset": 0,
+            "slot": "9",
+            "type": "t_bytes32"
+          },
+          {
+            "astId": 17481,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "submittedResultBlock",
+            "offset": 0,
+            "slot": "10",
+            "type": "t_uint256"
+          }
+        ],
+        "numberOfBytes": "352"
+      },
+      "t_struct(Data)18889_storage": {
+        "encoding": "inplace",
+        "label": "struct Callback.Data",
+        "members": [
+          {
+            "astId": 18888,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "callbackContract",
+            "offset": 0,
+            "slot": "0",
+            "type": "t_contract(IRandomBeaconConsumer)14980"
+          }
+        ],
+        "numberOfBytes": "32"
+      },
+      "t_struct(Data)18985_storage": {
+        "encoding": "inplace",
+        "label": "struct Groups.Data",
+        "members": [
+          {
+            "astId": 18974,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "groupsData",
+            "offset": 0,
+            "slot": "0",
+            "type": "t_mapping(t_bytes32,t_struct(Group)18969_storage)"
+          },
+          {
+            "astId": 18977,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "groupsRegistry",
+            "offset": 0,
+            "slot": "1",
+            "type": "t_array(t_bytes32)dyn_storage"
+          },
+          {
+            "astId": 18980,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "activeTerminatedGroups",
+            "offset": 0,
+            "slot": "2",
+            "type": "t_array(t_uint64)dyn_storage"
+          },
+          {
+            "astId": 18982,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "expiredGroupOffset",
+            "offset": 0,
+            "slot": "3",
+            "type": "t_uint64"
+          },
+          {
+            "astId": 18984,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "groupLifetime",
+            "offset": 0,
+            "slot": "4",
+            "type": "t_uint256"
+          }
+        ],
+        "numberOfBytes": "160"
+      },
+      "t_struct(Data)19879_storage": {
+        "encoding": "inplace",
+        "label": "struct Relay.Data",
+        "members": [
+          {
+            "astId": 19863,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "requestCount",
+            "offset": 0,
+            "slot": "0",
+            "type": "t_uint64"
+          },
+          {
+            "astId": 19865,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "currentRequestID",
+            "offset": 8,
+            "slot": "0",
+            "type": "t_uint64"
+          },
+          {
+            "astId": 19867,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "currentRequestGroupID",
+            "offset": 16,
+            "slot": "0",
+            "type": "t_uint64"
+          },
+          {
+            "astId": 19869,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "currentRequestStartBlock",
+            "offset": 24,
+            "slot": "0",
+            "type": "t_uint64"
+          },
+          {
+            "astId": 19872,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "previousEntry",
+            "offset": 0,
+            "slot": "1",
+            "type": "t_struct(G1Point)14992_storage"
+          },
+          {
+            "astId": 19874,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "relayEntrySoftTimeout",
+            "offset": 0,
+            "slot": "3",
+            "type": "t_uint32"
+          },
+          {
+            "astId": 19876,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "relayEntryHardTimeout",
+            "offset": 4,
+            "slot": "3",
+            "type": "t_uint32"
+          },
+          {
+            "astId": 19878,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "relayEntrySubmissionFailureSlashingAmount",
+            "offset": 8,
+            "slot": "3",
+            "type": "t_uint96"
+          }
+        ],
+        "numberOfBytes": "128"
+      },
+      "t_struct(G1Point)14992_storage": {
+        "encoding": "inplace",
+        "label": "struct AltBn128.G1Point",
+        "members": [
+          {
+            "astId": 14989,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "x",
+            "offset": 0,
+            "slot": "0",
+            "type": "t_uint256"
+          },
+          {
+            "astId": 14991,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "y",
+            "offset": 0,
+            "slot": "1",
+            "type": "t_uint256"
+          }
+        ],
+        "numberOfBytes": "64"
+      },
+      "t_struct(Group)18969_storage": {
+        "encoding": "inplace",
+        "label": "struct Groups.Group",
+        "members": [
+          {
+            "astId": 18962,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "groupPubKey",
+            "offset": 0,
+            "slot": "0",
+            "type": "t_bytes_storage"
+          },
+          {
+            "astId": 18964,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "registrationBlockNumber",
+            "offset": 0,
+            "slot": "1",
+            "type": "t_uint256"
+          },
+          {
+            "astId": 18966,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "membersHash",
+            "offset": 0,
+            "slot": "2",
+            "type": "t_bytes32"
+          },
+          {
+            "astId": 18968,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "terminated",
+            "offset": 0,
+            "slot": "3",
+            "type": "t_bool"
+          }
+        ],
+        "numberOfBytes": "128"
+      },
+      "t_struct(Parameters)16530_storage": {
+        "encoding": "inplace",
+        "label": "struct BeaconAuthorization.Parameters",
+        "members": [
+          {
+            "astId": 16525,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "minimumAuthorization",
+            "offset": 0,
+            "slot": "0",
+            "type": "t_uint96"
+          },
+          {
+            "astId": 16527,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "authorizationDecreaseDelay",
+            "offset": 12,
+            "slot": "0",
+            "type": "t_uint64"
+          },
+          {
+            "astId": 16529,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "authorizationDecreaseChangePeriod",
+            "offset": 20,
+            "slot": "0",
+            "type": "t_uint64"
+          }
+        ],
+        "numberOfBytes": "32"
+      },
+      "t_struct(Parameters)17462_storage": {
+        "encoding": "inplace",
+        "label": "struct BeaconDkg.Parameters",
+        "members": [
+          {
+            "astId": 17455,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "resultChallengePeriodLength",
+            "offset": 0,
+            "slot": "0",
+            "type": "t_uint256"
+          },
+          {
+            "astId": 17457,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "resultChallengeExtraGas",
+            "offset": 0,
+            "slot": "1",
+            "type": "t_uint256"
+          },
+          {
+            "astId": 17459,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "resultSubmissionTimeout",
+            "offset": 0,
+            "slot": "2",
+            "type": "t_uint256"
+          },
+          {
+            "astId": 17461,
+            "contract": "contracts/RandomBeacon.sol:RandomBeacon",
+            "label": "submitterPrecedencePeriodLength",
+            "offset": 0,
+            "slot": "3",
+            "type": "t_uint256"
+          }
+        ],
+        "numberOfBytes": "128"
+      },
+      "t_uint256": {
+        "encoding": "inplace",
+        "label": "uint256",
+        "numberOfBytes": "32"
+      },
+      "t_uint32": {
+        "encoding": "inplace",
+        "label": "uint32",
+        "numberOfBytes": "4"
+      },
+      "t_uint64": {
+        "encoding": "inplace",
+        "label": "uint64",
+        "numberOfBytes": "8"
+      },
+      "t_uint96": {
+        "encoding": "inplace",
+        "label": "uint96",
+        "numberOfBytes": "12"
+      }
+    }
+  }
+}
diff --git a/src/threshold-ts/utils/contract.ts b/src/threshold-ts/utils/contract.ts
index 36c3b3a3e..ced42a34c 100644
--- a/src/threshold-ts/utils/contract.ts
+++ b/src/threshold-ts/utils/contract.ts
@@ -8,7 +8,8 @@ import {
 } from "@keep-network/tbtc-v2.ts"
 import { Contract, ContractInterface, Event, providers, Signer } from "ethers"
 import { AddressZero, getAddress, isAddressZero } from "./address"
-import { LedgerLiveEthereumSigner } from "@keep-network/tbtc-v2.ts"
+import { LedgerLiveSigner } from "../../utils/ledger"
+import { SupportedChainIds } from "../../networks/enums/networks"
 
 import BridgeArtifactMainnet from "@keep-network/tbtc-v2.ts/src/lib/ethereum/artifacts/mainnet/Bridge.json"
 import NuCypherStakingEscrowMainnet from "../staking/mainnet-artifacts/NuCypherStakingEscrow.json"
@@ -18,6 +19,10 @@ import TbtcVaultArtifactMainnet from "@keep-network/tbtc-v2.ts/src/lib/ethereum/
 import VendingMachineKeepMainnet from "../vending-machine/mainnet-artifacts/VendingMachineKeep.json"
 import VendingMachineNuCypherMainnet from "../vending-machine/mainnet-artifacts/VendingMachineNuCypher.json"
 import WalletRegistryArtifactMainnet from "@keep-network/tbtc-v2.ts/src/lib/ethereum/artifacts/mainnet/WalletRegistry.json"
+import StakingArtifactMainnet from "../staking/mainnet-artifacts/TokenStaking.json"
+import RandomBeaconArtifactMainnet from "../tbtc/mainnet-artifacts/RandomBeacon.json"
+import LegacyKeepStakingArtifactMainnet from "../staking/mainnet-artifacts/LegacyKeepStaking.json"
+import TacoRegistryArtifactMainnet from "../mas/mainnet-artifacts/TacoRegistry.json"
 
 import BridgeArtifactSepolia from "@keep-network/tbtc-v2.ts/src/lib/ethereum/artifacts/sepolia/Bridge.json"
 import NuCypherStakingEscrowSepolia from "../staking/sepolia-artifacts/NuCypherStakingEscrow.json"
@@ -27,6 +32,10 @@ import TbtcVaultArtifactSepolia from "@keep-network/tbtc-v2.ts/src/lib/ethereum/
 import VendingMachineKeepSepolia from "../vending-machine/sepolia-artifacts/VendingMachineKeep.json"
 import VendingMachineNuCypherSepolia from "../vending-machine/sepolia-artifacts/VendingMachineNuCypher.json"
 import WalletRegistryArtifactSepolia from "@keep-network/tbtc-v2.ts/src/lib/ethereum/artifacts/sepolia/WalletRegistry.json"
+import StakingArtifactSepolia from "../staking/sepolia-artifacts/TokenStaking.json"
+import RandomBeaconArtifactSepolia from "../tbtc/sepolia-artifacts/RandomBeacon.json"
+import LegacyKeepStakingArtifactSepolia from "../staking/sepolia-artifacts/LegacyKeepStaking.json"
+import TacoRegistryArtifactSepolia from "../mas/sepolia-artifacts/TacoRegistry.json"
 
 import BridgeArtifactDappDevelopmentSepolia from "../tbtc/dapp-development-sepolia-artifacts/Bridge.json"
 import NuCypherStakingEscrowDappDevelopmentSepolia from "../staking/dapp-development-sepolia-artifacts/NuCypherStakingEscrow.json"
@@ -36,8 +45,16 @@ import TbtcVaultArtifactDappDevelopmentSepolia from "../tbtc/dapp-development-se
 import VendingMachineKeepDappDevelopmentSepolia from "../vending-machine/dapp-development-sepolia-artifacts/VendingMachineKeep.json"
 import VendingMachineNuCypherDappDevelopmentSepolia from "../vending-machine/dapp-development-sepolia-artifacts/VendingMachineNuCypher.json"
 import WalletRegistryArtifactDappDevelopmentSepolia from "../tbtc/dapp-development-sepolia-artifacts/WalletRegistry.json"
+import StakingArtifactDappDevelopmentSepolia from "../staking/dapp-development-sepolia-artifacts/TokenStaking.json"
+import RandomBeaconArtifactDappDevelopmentSepolia from "../tbtc/dapp-development-sepolia-artifacts/RandomBeacon.json"
+import LegacyKeepStakingArtifactDappDevelopmentSepolia from "../staking/dapp-development-sepolia-artifacts/LegacyKeepStaking.json"
+import TacoRegistryArtifactDappDevelopmentSepolia from "../mas/dapp-development-sepolia-artifacts/TacoRegistry.json"
 
 type ArtifactNameType =
+  | "TacoRegistry"
+  | "LegacyKeepStaking"
+  | "RandomBeacon"
+  | "TokenStaking"
   | "Bridge"
   | "NuCypherStakingEscrow"
   | "NuCypherToken"
@@ -53,6 +70,10 @@ type ArtifactType = {
 }
 
 const mainnetArtifacts = new Map<ArtifactNameType, ArtifactType>([
+  ["TacoRegistry", TacoRegistryArtifactMainnet],
+  ["LegacyKeepStaking", LegacyKeepStakingArtifactMainnet],
+  ["RandomBeacon", RandomBeaconArtifactMainnet],
+  ["TokenStaking", StakingArtifactMainnet],
   ["Bridge", BridgeArtifactMainnet],
   ["NuCypherStakingEscrow", NuCypherStakingEscrowMainnet],
   ["NuCypherToken", NuCypherTokenMainnet],
@@ -63,6 +84,10 @@ const mainnetArtifacts = new Map<ArtifactNameType, ArtifactType>([
   ["VendingMachineNuCypher", VendingMachineNuCypherMainnet],
 ])
 const testnetArtifacts = new Map<ArtifactNameType, ArtifactType>([
+  ["TacoRegistry", TacoRegistryArtifactSepolia],
+  ["LegacyKeepStaking", LegacyKeepStakingArtifactSepolia],
+  ["RandomBeacon", RandomBeaconArtifactSepolia],
+  ["TokenStaking", StakingArtifactSepolia],
   ["Bridge", BridgeArtifactSepolia],
   ["NuCypherStakingEscrow", NuCypherStakingEscrowSepolia],
   ["NuCypherToken", NuCypherTokenSepolia],
@@ -73,6 +98,10 @@ const testnetArtifacts = new Map<ArtifactNameType, ArtifactType>([
   ["VendingMachineNuCypher", VendingMachineNuCypherSepolia],
 ])
 const testnetDevelopmentArtifacts = new Map<ArtifactNameType, ArtifactType>([
+  ["TacoRegistry", TacoRegistryArtifactDappDevelopmentSepolia],
+  ["LegacyKeepStaking", LegacyKeepStakingArtifactDappDevelopmentSepolia],
+  ["RandomBeacon", RandomBeaconArtifactDappDevelopmentSepolia],
+  ["TokenStaking", StakingArtifactDappDevelopmentSepolia],
   ["Bridge", BridgeArtifactDappDevelopmentSepolia],
   ["NuCypherStakingEscrow", NuCypherStakingEscrowDappDevelopmentSepolia],
   ["NuCypherToken", NuCypherTokenDappDevelopmentSepolia],
@@ -111,7 +140,7 @@ export const getContract = (
   // Sets the correct provider for ledger live app if the instance of
   // LedgerLiveEthereumSigner is passed as providerOrSigner.
   const _providerOrSigner =
-    providerOrSigner instanceof LedgerLiveEthereumSigner
+    providerOrSigner instanceof LedgerLiveSigner
       ? providerOrSigner
       : (getProviderOrSigner(providerOrSigner as any, account) as any)
   return new Contract(address, abi, _providerOrSigner)
@@ -155,12 +184,10 @@ export const getArtifact = (
   chainId: string | number,
   shouldUseTestnetDevelopmentContracts = false
 ): ArtifactType => {
-  switch (chainId.toString()) {
-    case "1":
-      // Ethereum mainnet.
+  switch (Number(chainId)) {
+    case SupportedChainIds.Ethereum:
       return mainnetArtifacts.get(artifactName)!
-    case "11155111":
-      // Ethereum Sepolia testnet.
+    case SupportedChainIds.Sepolia:
       const artifacts = shouldUseTestnetDevelopmentContracts
         ? testnetDevelopmentArtifacts
         : testnetArtifacts
diff --git a/src/threshold-ts/vending-machine/index.ts b/src/threshold-ts/vending-machine/index.ts
index 3729e46dc..f7bc51976 100644
--- a/src/threshold-ts/vending-machine/index.ts
+++ b/src/threshold-ts/vending-machine/index.ts
@@ -106,7 +106,7 @@ export class VendingMachine implements IVendingMachine {
 
     return {
       tAmount: convertibleAmount
-        .mul(BigNumber.from(await this.ratio()))
+        .mul(await this.ratio())
         .div(this.FLOATING_POINT_DIVISOR),
       wrappedRemainder,
     }
diff --git a/src/utils/getStakingAppLabel.ts b/src/utils/getStakingAppLabel.ts
index ec57b3c67..bbb1adf9a 100644
--- a/src/utils/getStakingAppLabel.ts
+++ b/src/utils/getStakingAppLabel.ts
@@ -1,4 +1,4 @@
-import { threshold } from "./getThresholdLib"
+import { useThreshold } from "../contexts/ThresholdContext"
 import { StakingAppName } from "../store/staking-applications"
 
 const stakingAppNameToAppLabel: Record<StakingAppName, string> = {
@@ -7,19 +7,28 @@ const stakingAppNameToAppLabel: Record<StakingAppName, string> = {
   taco: "TACo",
 }
 
-const stakingAppAddressToAppName: Record<string, StakingAppName> = {
-  [threshold.multiAppStaking.ecdsa.address]: "tbtc",
-  [threshold.multiAppStaking.randomBeacon.address]: "randomBeacon",
-  [threshold.multiAppStaking.taco.address]: "taco",
-}
-
 export const getStakingAppNameFromAppAddress = (stakingAppAddress: string) => {
+  const { multiAppStaking } = useThreshold()
+
+  if (!multiAppStaking) {
+    return null
+  }
+
+  const stakingAppAddressToAppName: Record<string, StakingAppName> = {
+    [multiAppStaking.ecdsa.address]: "tbtc",
+    [multiAppStaking.randomBeacon.address]: "randomBeacon",
+    [multiAppStaking.taco.address]: "taco",
+  }
+
   return stakingAppAddressToAppName[stakingAppAddress]
 }
 
 export const getStakingAppLabelFromAppName = (
-  stakingAppName: StakingAppName
+  stakingAppName: StakingAppName | null
 ) => {
+  if (!stakingAppName) {
+    return null
+  }
   return stakingAppNameToAppLabel[stakingAppName]
 }
 
diff --git a/src/web3/abi/TokenStaking.json b/src/web3/abi/TokenStaking.json
new file mode 100644
index 000000000..532469433
--- /dev/null
+++ b/src/web3/abi/TokenStaking.json
@@ -0,0 +1,1588 @@
+[
+  {
+    "inputs": [
+      {
+        "internalType": "contract T",
+        "name": "_token",
+        "type": "address"
+      },
+      {
+        "internalType": "contract IKeepTokenStaking",
+        "name": "_keepStakingContract",
+        "type": "address"
+      },
+      {
+        "internalType": "contract INuCypherStakingEscrow",
+        "name": "_nucypherStakingContract",
+        "type": "address"
+      },
+      {
+        "internalType": "contract VendingMachine",
+        "name": "_keepVendingMachine",
+        "type": "address"
+      },
+      {
+        "internalType": "contract VendingMachine",
+        "name": "_nucypherVendingMachine",
+        "type": "address"
+      },
+      {
+        "internalType": "contract KeepStake",
+        "name": "_keepStake",
+        "type": "address"
+      }
+    ],
+    "stateMutability": "nonpayable",
+    "type": "constructor"
+  },
+  {
+    "anonymous": false,
+    "inputs": [
+      {
+        "indexed": true,
+        "internalType": "address",
+        "name": "application",
+        "type": "address"
+      },
+      {
+        "indexed": true,
+        "internalType": "enum TokenStaking.ApplicationStatus",
+        "name": "newStatus",
+        "type": "uint8"
+      }
+    ],
+    "name": "ApplicationStatusChanged",
+    "type": "event"
+  },
+  {
+    "anonymous": false,
+    "inputs": [
+      {
+        "indexed": false,
+        "internalType": "uint256",
+        "name": "ceiling",
+        "type": "uint256"
+      }
+    ],
+    "name": "AuthorizationCeilingSet",
+    "type": "event"
+  },
+  {
+    "anonymous": false,
+    "inputs": [
+      {
+        "indexed": true,
+        "internalType": "address",
+        "name": "stakingProvider",
+        "type": "address"
+      },
+      {
+        "indexed": true,
+        "internalType": "address",
+        "name": "application",
+        "type": "address"
+      },
+      {
+        "indexed": false,
+        "internalType": "uint96",
+        "name": "fromAmount",
+        "type": "uint96"
+      },
+      {
+        "indexed": false,
+        "internalType": "uint96",
+        "name": "toAmount",
+        "type": "uint96"
+      }
+    ],
+    "name": "AuthorizationDecreaseApproved",
+    "type": "event"
+  },
+  {
+    "anonymous": false,
+    "inputs": [
+      {
+        "indexed": true,
+        "internalType": "address",
+        "name": "stakingProvider",
+        "type": "address"
+      },
+      {
+        "indexed": true,
+        "internalType": "address",
+        "name": "application",
+        "type": "address"
+      },
+      {
+        "indexed": false,
+        "internalType": "uint96",
+        "name": "fromAmount",
+        "type": "uint96"
+      },
+      {
+        "indexed": false,
+        "internalType": "uint96",
+        "name": "toAmount",
+        "type": "uint96"
+      }
+    ],
+    "name": "AuthorizationDecreaseRequested",
+    "type": "event"
+  },
+  {
+    "anonymous": false,
+    "inputs": [
+      {
+        "indexed": true,
+        "internalType": "address",
+        "name": "stakingProvider",
+        "type": "address"
+      },
+      {
+        "indexed": true,
+        "internalType": "address",
+        "name": "application",
+        "type": "address"
+      },
+      {
+        "indexed": false,
+        "internalType": "uint96",
+        "name": "fromAmount",
+        "type": "uint96"
+      },
+      {
+        "indexed": false,
+        "internalType": "uint96",
+        "name": "toAmount",
+        "type": "uint96"
+      }
+    ],
+    "name": "AuthorizationIncreased",
+    "type": "event"
+  },
+  {
+    "anonymous": false,
+    "inputs": [
+      {
+        "indexed": true,
+        "internalType": "address",
+        "name": "stakingProvider",
+        "type": "address"
+      },
+      {
+        "indexed": true,
+        "internalType": "address",
+        "name": "application",
+        "type": "address"
+      },
+      {
+        "indexed": false,
+        "internalType": "uint96",
+        "name": "fromAmount",
+        "type": "uint96"
+      },
+      {
+        "indexed": false,
+        "internalType": "uint96",
+        "name": "toAmount",
+        "type": "uint96"
+      },
+      {
+        "indexed": true,
+        "internalType": "bool",
+        "name": "successfulCall",
+        "type": "bool"
+      }
+    ],
+    "name": "AuthorizationInvoluntaryDecreased",
+    "type": "event"
+  },
+  {
+    "anonymous": false,
+    "inputs": [
+      {
+        "indexed": true,
+        "internalType": "address",
+        "name": "delegator",
+        "type": "address"
+      },
+      {
+        "indexed": true,
+        "internalType": "address",
+        "name": "fromDelegate",
+        "type": "address"
+      },
+      {
+        "indexed": true,
+        "internalType": "address",
+        "name": "toDelegate",
+        "type": "address"
+      }
+    ],
+    "name": "DelegateChanged",
+    "type": "event"
+  },
+  {
+    "anonymous": false,
+    "inputs": [
+      {
+        "indexed": true,
+        "internalType": "address",
+        "name": "delegate",
+        "type": "address"
+      },
+      {
+        "indexed": false,
+        "internalType": "uint256",
+        "name": "previousBalance",
+        "type": "uint256"
+      },
+      {
+        "indexed": false,
+        "internalType": "uint256",
+        "name": "newBalance",
+        "type": "uint256"
+      }
+    ],
+    "name": "DelegateVotesChanged",
+    "type": "event"
+  },
+  {
+    "anonymous": false,
+    "inputs": [
+      {
+        "indexed": false,
+        "internalType": "address",
+        "name": "oldGovernance",
+        "type": "address"
+      },
+      {
+        "indexed": false,
+        "internalType": "address",
+        "name": "newGovernance",
+        "type": "address"
+      }
+    ],
+    "name": "GovernanceTransferred",
+    "type": "event"
+  },
+  {
+    "anonymous": false,
+    "inputs": [
+      {
+        "indexed": false,
+        "internalType": "uint96",
+        "name": "amount",
+        "type": "uint96"
+      }
+    ],
+    "name": "MinimumStakeAmountSet",
+    "type": "event"
+  },
+  {
+    "anonymous": false,
+    "inputs": [
+      {
+        "indexed": false,
+        "internalType": "uint96",
+        "name": "reward",
+        "type": "uint96"
+      }
+    ],
+    "name": "NotificationRewardPushed",
+    "type": "event"
+  },
+  {
+    "anonymous": false,
+    "inputs": [
+      {
+        "indexed": false,
+        "internalType": "uint96",
+        "name": "reward",
+        "type": "uint96"
+      }
+    ],
+    "name": "NotificationRewardSet",
+    "type": "event"
+  },
+  {
+    "anonymous": false,
+    "inputs": [
+      {
+        "indexed": false,
+        "internalType": "address",
+        "name": "recipient",
+        "type": "address"
+      },
+      {
+        "indexed": false,
+        "internalType": "uint96",
+        "name": "amount",
+        "type": "uint96"
+      }
+    ],
+    "name": "NotificationRewardWithdrawn",
+    "type": "event"
+  },
+  {
+    "anonymous": false,
+    "inputs": [
+      {
+        "indexed": true,
+        "internalType": "address",
+        "name": "notifier",
+        "type": "address"
+      },
+      {
+        "indexed": false,
+        "internalType": "uint256",
+        "name": "amount",
+        "type": "uint256"
+      }
+    ],
+    "name": "NotifierRewarded",
+    "type": "event"
+  },
+  {
+    "anonymous": false,
+    "inputs": [
+      {
+        "indexed": true,
+        "internalType": "address",
+        "name": "stakingProvider",
+        "type": "address"
+      },
+      {
+        "indexed": true,
+        "internalType": "address",
+        "name": "oldOwner",
+        "type": "address"
+      },
+      {
+        "indexed": true,
+        "internalType": "address",
+        "name": "newOwner",
+        "type": "address"
+      }
+    ],
+    "name": "OwnerRefreshed",
+    "type": "event"
+  },
+  {
+    "anonymous": false,
+    "inputs": [
+      {
+        "indexed": true,
+        "internalType": "address",
+        "name": "application",
+        "type": "address"
+      },
+      {
+        "indexed": true,
+        "internalType": "address",
+        "name": "panicButton",
+        "type": "address"
+      }
+    ],
+    "name": "PanicButtonSet",
+    "type": "event"
+  },
+  {
+    "anonymous": false,
+    "inputs": [
+      {
+        "indexed": true,
+        "internalType": "address",
+        "name": "caller",
+        "type": "address"
+      },
+      {
+        "indexed": false,
+        "internalType": "uint256",
+        "name": "count",
+        "type": "uint256"
+      },
+      {
+        "indexed": false,
+        "internalType": "uint256",
+        "name": "tAmount",
+        "type": "uint256"
+      }
+    ],
+    "name": "SlashingProcessed",
+    "type": "event"
+  },
+  {
+    "anonymous": false,
+    "inputs": [
+      {
+        "indexed": false,
+        "internalType": "uint96",
+        "name": "penalty",
+        "type": "uint96"
+      },
+      {
+        "indexed": false,
+        "internalType": "uint256",
+        "name": "rewardMultiplier",
+        "type": "uint256"
+      }
+    ],
+    "name": "StakeDiscrepancyPenaltySet",
+    "type": "event"
+  },
+  {
+    "anonymous": false,
+    "inputs": [
+      {
+        "indexed": true,
+        "internalType": "enum IStaking.StakeType",
+        "name": "stakeType",
+        "type": "uint8"
+      },
+      {
+        "indexed": true,
+        "internalType": "address",
+        "name": "owner",
+        "type": "address"
+      },
+      {
+        "indexed": true,
+        "internalType": "address",
+        "name": "stakingProvider",
+        "type": "address"
+      },
+      {
+        "indexed": false,
+        "internalType": "address",
+        "name": "beneficiary",
+        "type": "address"
+      },
+      {
+        "indexed": false,
+        "internalType": "address",
+        "name": "authorizer",
+        "type": "address"
+      },
+      {
+        "indexed": false,
+        "internalType": "uint96",
+        "name": "amount",
+        "type": "uint96"
+      }
+    ],
+    "name": "Staked",
+    "type": "event"
+  },
+  {
+    "anonymous": false,
+    "inputs": [
+      {
+        "indexed": true,
+        "internalType": "address",
+        "name": "stakingProvider",
+        "type": "address"
+      },
+      {
+        "indexed": false,
+        "internalType": "uint96",
+        "name": "amount",
+        "type": "uint96"
+      },
+      {
+        "indexed": true,
+        "internalType": "bool",
+        "name": "discrepancy",
+        "type": "bool"
+      }
+    ],
+    "name": "TokensSeized",
+    "type": "event"
+  },
+  {
+    "anonymous": false,
+    "inputs": [
+      {
+        "indexed": true,
+        "internalType": "address",
+        "name": "stakingProvider",
+        "type": "address"
+      },
+      {
+        "indexed": false,
+        "internalType": "uint96",
+        "name": "amount",
+        "type": "uint96"
+      }
+    ],
+    "name": "ToppedUp",
+    "type": "event"
+  },
+  {
+    "anonymous": false,
+    "inputs": [
+      {
+        "indexed": true,
+        "internalType": "address",
+        "name": "stakingProvider",
+        "type": "address"
+      },
+      {
+        "indexed": false,
+        "internalType": "uint96",
+        "name": "amount",
+        "type": "uint96"
+      }
+    ],
+    "name": "Unstaked",
+    "type": "event"
+  },
+  {
+    "inputs": [
+      {
+        "internalType": "address",
+        "name": "",
+        "type": "address"
+      }
+    ],
+    "name": "applicationInfo",
+    "outputs": [
+      {
+        "internalType": "enum TokenStaking.ApplicationStatus",
+        "name": "status",
+        "type": "uint8"
+      },
+      {
+        "internalType": "address",
+        "name": "panicButton",
+        "type": "address"
+      }
+    ],
+    "stateMutability": "view",
+    "type": "function"
+  },
+  {
+    "inputs": [
+      {
+        "internalType": "uint256",
+        "name": "",
+        "type": "uint256"
+      }
+    ],
+    "name": "applications",
+    "outputs": [
+      {
+        "internalType": "address",
+        "name": "",
+        "type": "address"
+      }
+    ],
+    "stateMutability": "view",
+    "type": "function"
+  },
+  {
+    "inputs": [
+      {
+        "internalType": "address",
+        "name": "application",
+        "type": "address"
+      }
+    ],
+    "name": "approveApplication",
+    "outputs": [],
+    "stateMutability": "nonpayable",
+    "type": "function"
+  },
+  {
+    "inputs": [
+      {
+        "internalType": "address",
+        "name": "stakingProvider",
+        "type": "address"
+      }
+    ],
+    "name": "approveAuthorizationDecrease",
+    "outputs": [
+      {
+        "internalType": "uint96",
+        "name": "",
+        "type": "uint96"
+      }
+    ],
+    "stateMutability": "nonpayable",
+    "type": "function"
+  },
+  {
+    "inputs": [],
+    "name": "authorizationCeiling",
+    "outputs": [
+      {
+        "internalType": "uint256",
+        "name": "",
+        "type": "uint256"
+      }
+    ],
+    "stateMutability": "view",
+    "type": "function"
+  },
+  {
+    "inputs": [
+      {
+        "internalType": "address",
+        "name": "stakingProvider",
+        "type": "address"
+      },
+      {
+        "internalType": "address",
+        "name": "application",
+        "type": "address"
+      }
+    ],
+    "name": "authorizedStake",
+    "outputs": [
+      {
+        "internalType": "uint96",
+        "name": "",
+        "type": "uint96"
+      }
+    ],
+    "stateMutability": "view",
+    "type": "function"
+  },
+  {
+    "inputs": [
+      {
+        "internalType": "address",
+        "name": "account",
+        "type": "address"
+      },
+      {
+        "internalType": "uint32",
+        "name": "pos",
+        "type": "uint32"
+      }
+    ],
+    "name": "checkpoints",
+    "outputs": [
+      {
+        "components": [
+          {
+            "internalType": "uint32",
+            "name": "fromBlock",
+            "type": "uint32"
+          },
+          {
+            "internalType": "uint96",
+            "name": "votes",
+            "type": "uint96"
+          }
+        ],
+        "internalType": "struct Checkpoints.Checkpoint",
+        "name": "checkpoint",
+        "type": "tuple"
+      }
+    ],
+    "stateMutability": "view",
+    "type": "function"
+  },
+  {
+    "inputs": [
+      {
+        "internalType": "address",
+        "name": "stakingProvider",
+        "type": "address"
+      },
+      {
+        "internalType": "address",
+        "name": "delegatee",
+        "type": "address"
+      }
+    ],
+    "name": "delegateVoting",
+    "outputs": [],
+    "stateMutability": "nonpayable",
+    "type": "function"
+  },
+  {
+    "inputs": [
+      {
+        "internalType": "address",
+        "name": "account",
+        "type": "address"
+      }
+    ],
+    "name": "delegates",
+    "outputs": [
+      {
+        "internalType": "address",
+        "name": "",
+        "type": "address"
+      }
+    ],
+    "stateMutability": "view",
+    "type": "function"
+  },
+  {
+    "inputs": [
+      {
+        "internalType": "address",
+        "name": "application",
+        "type": "address"
+      }
+    ],
+    "name": "disableApplication",
+    "outputs": [],
+    "stateMutability": "nonpayable",
+    "type": "function"
+  },
+  {
+    "inputs": [
+      {
+        "internalType": "address",
+        "name": "stakingProvider",
+        "type": "address"
+      },
+      {
+        "internalType": "address",
+        "name": "application",
+        "type": "address"
+      }
+    ],
+    "name": "forceDecreaseAuthorization",
+    "outputs": [],
+    "stateMutability": "nonpayable",
+    "type": "function"
+  },
+  {
+    "inputs": [],
+    "name": "getApplicationsLength",
+    "outputs": [
+      {
+        "internalType": "uint256",
+        "name": "",
+        "type": "uint256"
+      }
+    ],
+    "stateMutability": "view",
+    "type": "function"
+  },
+  {
+    "inputs": [
+      {
+        "internalType": "address",
+        "name": "stakingProvider",
+        "type": "address"
+      },
+      {
+        "internalType": "address",
+        "name": "application",
+        "type": "address"
+      }
+    ],
+    "name": "getAvailableToAuthorize",
+    "outputs": [
+      {
+        "internalType": "uint96",
+        "name": "availableTValue",
+        "type": "uint96"
+      }
+    ],
+    "stateMutability": "view",
+    "type": "function"
+  },
+  {
+    "inputs": [
+      {
+        "internalType": "address",
+        "name": "stakingProvider",
+        "type": "address"
+      },
+      {
+        "internalType": "enum IStaking.StakeType",
+        "name": "stakeTypes",
+        "type": "uint8"
+      }
+    ],
+    "name": "getMinStaked",
+    "outputs": [
+      {
+        "internalType": "uint96",
+        "name": "",
+        "type": "uint96"
+      }
+    ],
+    "stateMutability": "view",
+    "type": "function"
+  },
+  {
+    "inputs": [
+      {
+        "internalType": "uint256",
+        "name": "blockNumber",
+        "type": "uint256"
+      }
+    ],
+    "name": "getPastTotalSupply",
+    "outputs": [
+      {
+        "internalType": "uint96",
+        "name": "",
+        "type": "uint96"
+      }
+    ],
+    "stateMutability": "view",
+    "type": "function"
+  },
+  {
+    "inputs": [
+      {
+        "internalType": "address",
+        "name": "account",
+        "type": "address"
+      },
+      {
+        "internalType": "uint256",
+        "name": "blockNumber",
+        "type": "uint256"
+      }
+    ],
+    "name": "getPastVotes",
+    "outputs": [
+      {
+        "internalType": "uint96",
+        "name": "",
+        "type": "uint96"
+      }
+    ],
+    "stateMutability": "view",
+    "type": "function"
+  },
+  {
+    "inputs": [],
+    "name": "getSlashingQueueLength",
+    "outputs": [
+      {
+        "internalType": "uint256",
+        "name": "",
+        "type": "uint256"
+      }
+    ],
+    "stateMutability": "view",
+    "type": "function"
+  },
+  {
+    "inputs": [
+      {
+        "internalType": "address",
+        "name": "stakingProvider",
+        "type": "address"
+      }
+    ],
+    "name": "getStartStakingTimestamp",
+    "outputs": [
+      {
+        "internalType": "uint256",
+        "name": "",
+        "type": "uint256"
+      }
+    ],
+    "stateMutability": "view",
+    "type": "function"
+  },
+  {
+    "inputs": [
+      {
+        "internalType": "address",
+        "name": "account",
+        "type": "address"
+      }
+    ],
+    "name": "getVotes",
+    "outputs": [
+      {
+        "internalType": "uint96",
+        "name": "",
+        "type": "uint96"
+      }
+    ],
+    "stateMutability": "view",
+    "type": "function"
+  },
+  {
+    "inputs": [],
+    "name": "governance",
+    "outputs": [
+      {
+        "internalType": "address",
+        "name": "",
+        "type": "address"
+      }
+    ],
+    "stateMutability": "view",
+    "type": "function"
+  },
+  {
+    "inputs": [
+      {
+        "internalType": "address",
+        "name": "stakingProvider",
+        "type": "address"
+      },
+      {
+        "internalType": "address",
+        "name": "application",
+        "type": "address"
+      },
+      {
+        "internalType": "uint96",
+        "name": "amount",
+        "type": "uint96"
+      }
+    ],
+    "name": "increaseAuthorization",
+    "outputs": [],
+    "stateMutability": "nonpayable",
+    "type": "function"
+  },
+  {
+    "inputs": [],
+    "name": "initialize",
+    "outputs": [],
+    "stateMutability": "nonpayable",
+    "type": "function"
+  },
+  {
+    "inputs": [],
+    "name": "minTStakeAmount",
+    "outputs": [
+      {
+        "internalType": "uint96",
+        "name": "",
+        "type": "uint96"
+      }
+    ],
+    "stateMutability": "view",
+    "type": "function"
+  },
+  {
+    "inputs": [],
+    "name": "notificationReward",
+    "outputs": [
+      {
+        "internalType": "uint256",
+        "name": "",
+        "type": "uint256"
+      }
+    ],
+    "stateMutability": "view",
+    "type": "function"
+  },
+  {
+    "inputs": [],
+    "name": "notifiersTreasury",
+    "outputs": [
+      {
+        "internalType": "uint256",
+        "name": "",
+        "type": "uint256"
+      }
+    ],
+    "stateMutability": "view",
+    "type": "function"
+  },
+  {
+    "inputs": [
+      {
+        "internalType": "address",
+        "name": "stakingProvider",
+        "type": "address"
+      }
+    ],
+    "name": "notifyKeepStakeDiscrepancy",
+    "outputs": [],
+    "stateMutability": "nonpayable",
+    "type": "function"
+  },
+  {
+    "inputs": [
+      {
+        "internalType": "address",
+        "name": "stakingProvider",
+        "type": "address"
+      }
+    ],
+    "name": "notifyNuStakeDiscrepancy",
+    "outputs": [],
+    "stateMutability": "nonpayable",
+    "type": "function"
+  },
+  {
+    "inputs": [
+      {
+        "internalType": "address",
+        "name": "account",
+        "type": "address"
+      }
+    ],
+    "name": "numCheckpoints",
+    "outputs": [
+      {
+        "internalType": "uint32",
+        "name": "",
+        "type": "uint32"
+      }
+    ],
+    "stateMutability": "view",
+    "type": "function"
+  },
+  {
+    "inputs": [
+      {
+        "internalType": "address",
+        "name": "application",
+        "type": "address"
+      }
+    ],
+    "name": "pauseApplication",
+    "outputs": [],
+    "stateMutability": "nonpayable",
+    "type": "function"
+  },
+  {
+    "inputs": [
+      {
+        "internalType": "uint256",
+        "name": "count",
+        "type": "uint256"
+      }
+    ],
+    "name": "processSlashing",
+    "outputs": [],
+    "stateMutability": "nonpayable",
+    "type": "function"
+  },
+  {
+    "inputs": [
+      {
+        "internalType": "uint96",
+        "name": "reward",
+        "type": "uint96"
+      }
+    ],
+    "name": "pushNotificationReward",
+    "outputs": [],
+    "stateMutability": "nonpayable",
+    "type": "function"
+  },
+  {
+    "inputs": [
+      {
+        "internalType": "address",
+        "name": "stakingProvider",
+        "type": "address"
+      }
+    ],
+    "name": "refreshKeepStakeOwner",
+    "outputs": [],
+    "stateMutability": "nonpayable",
+    "type": "function"
+  },
+  {
+    "inputs": [
+      {
+        "internalType": "address",
+        "name": "stakingProvider",
+        "type": "address"
+      },
+      {
+        "internalType": "address",
+        "name": "application",
+        "type": "address"
+      },
+      {
+        "internalType": "uint96",
+        "name": "amount",
+        "type": "uint96"
+      }
+    ],
+    "name": "requestAuthorizationDecrease",
+    "outputs": [],
+    "stateMutability": "nonpayable",
+    "type": "function"
+  },
+  {
+    "inputs": [
+      {
+        "internalType": "address",
+        "name": "stakingProvider",
+        "type": "address"
+      }
+    ],
+    "name": "requestAuthorizationDecrease",
+    "outputs": [],
+    "stateMutability": "nonpayable",
+    "type": "function"
+  },
+  {
+    "inputs": [
+      {
+        "internalType": "address",
+        "name": "stakingProvider",
+        "type": "address"
+      }
+    ],
+    "name": "rolesOf",
+    "outputs": [
+      {
+        "internalType": "address",
+        "name": "owner",
+        "type": "address"
+      },
+      {
+        "internalType": "address payable",
+        "name": "beneficiary",
+        "type": "address"
+      },
+      {
+        "internalType": "address",
+        "name": "authorizer",
+        "type": "address"
+      }
+    ],
+    "stateMutability": "view",
+    "type": "function"
+  },
+  {
+    "inputs": [
+      {
+        "internalType": "uint96",
+        "name": "amount",
+        "type": "uint96"
+      },
+      {
+        "internalType": "uint256",
+        "name": "rewardMultiplier",
+        "type": "uint256"
+      },
+      {
+        "internalType": "address",
+        "name": "notifier",
+        "type": "address"
+      },
+      {
+        "internalType": "address[]",
+        "name": "_stakingProviders",
+        "type": "address[]"
+      }
+    ],
+    "name": "seize",
+    "outputs": [],
+    "stateMutability": "nonpayable",
+    "type": "function"
+  },
+  {
+    "inputs": [
+      {
+        "internalType": "uint256",
+        "name": "ceiling",
+        "type": "uint256"
+      }
+    ],
+    "name": "setAuthorizationCeiling",
+    "outputs": [],
+    "stateMutability": "nonpayable",
+    "type": "function"
+  },
+  {
+    "inputs": [
+      {
+        "internalType": "uint96",
+        "name": "amount",
+        "type": "uint96"
+      }
+    ],
+    "name": "setMinimumStakeAmount",
+    "outputs": [],
+    "stateMutability": "nonpayable",
+    "type": "function"
+  },
+  {
+    "inputs": [
+      {
+        "internalType": "uint96",
+        "name": "reward",
+        "type": "uint96"
+      }
+    ],
+    "name": "setNotificationReward",
+    "outputs": [],
+    "stateMutability": "nonpayable",
+    "type": "function"
+  },
+  {
+    "inputs": [
+      {
+        "internalType": "address",
+        "name": "application",
+        "type": "address"
+      },
+      {
+        "internalType": "address",
+        "name": "panicButton",
+        "type": "address"
+      }
+    ],
+    "name": "setPanicButton",
+    "outputs": [],
+    "stateMutability": "nonpayable",
+    "type": "function"
+  },
+  {
+    "inputs": [
+      {
+        "internalType": "uint96",
+        "name": "penalty",
+        "type": "uint96"
+      },
+      {
+        "internalType": "uint256",
+        "name": "rewardMultiplier",
+        "type": "uint256"
+      }
+    ],
+    "name": "setStakeDiscrepancyPenalty",
+    "outputs": [],
+    "stateMutability": "nonpayable",
+    "type": "function"
+  },
+  {
+    "inputs": [
+      {
+        "internalType": "uint96",
+        "name": "amount",
+        "type": "uint96"
+      },
+      {
+        "internalType": "address[]",
+        "name": "_stakingProviders",
+        "type": "address[]"
+      }
+    ],
+    "name": "slash",
+    "outputs": [],
+    "stateMutability": "nonpayable",
+    "type": "function"
+  },
+  {
+    "inputs": [
+      {
+        "internalType": "uint256",
+        "name": "",
+        "type": "uint256"
+      }
+    ],
+    "name": "slashingQueue",
+    "outputs": [
+      {
+        "internalType": "address",
+        "name": "stakingProvider",
+        "type": "address"
+      },
+      {
+        "internalType": "uint96",
+        "name": "amount",
+        "type": "uint96"
+      }
+    ],
+    "stateMutability": "view",
+    "type": "function"
+  },
+  {
+    "inputs": [],
+    "name": "slashingQueueIndex",
+    "outputs": [
+      {
+        "internalType": "uint256",
+        "name": "",
+        "type": "uint256"
+      }
+    ],
+    "stateMutability": "view",
+    "type": "function"
+  },
+  {
+    "inputs": [
+      {
+        "internalType": "address",
+        "name": "stakingProvider",
+        "type": "address"
+      },
+      {
+        "internalType": "address payable",
+        "name": "beneficiary",
+        "type": "address"
+      },
+      {
+        "internalType": "address",
+        "name": "authorizer",
+        "type": "address"
+      },
+      {
+        "internalType": "uint96",
+        "name": "amount",
+        "type": "uint96"
+      }
+    ],
+    "name": "stake",
+    "outputs": [],
+    "stateMutability": "nonpayable",
+    "type": "function"
+  },
+  {
+    "inputs": [],
+    "name": "stakeDiscrepancyPenalty",
+    "outputs": [
+      {
+        "internalType": "uint96",
+        "name": "",
+        "type": "uint96"
+      }
+    ],
+    "stateMutability": "view",
+    "type": "function"
+  },
+  {
+    "inputs": [],
+    "name": "stakeDiscrepancyRewardMultiplier",
+    "outputs": [
+      {
+        "internalType": "uint256",
+        "name": "",
+        "type": "uint256"
+      }
+    ],
+    "stateMutability": "view",
+    "type": "function"
+  },
+  {
+    "inputs": [
+      {
+        "internalType": "address",
+        "name": "stakingProvider",
+        "type": "address"
+      }
+    ],
+    "name": "stakeKeep",
+    "outputs": [],
+    "stateMutability": "nonpayable",
+    "type": "function"
+  },
+  {
+    "inputs": [
+      {
+        "internalType": "address",
+        "name": "stakingProvider",
+        "type": "address"
+      },
+      {
+        "internalType": "address payable",
+        "name": "beneficiary",
+        "type": "address"
+      },
+      {
+        "internalType": "address",
+        "name": "authorizer",
+        "type": "address"
+      }
+    ],
+    "name": "stakeNu",
+    "outputs": [],
+    "stateMutability": "nonpayable",
+    "type": "function"
+  },
+  {
+    "inputs": [
+      {
+        "internalType": "address",
+        "name": "stakingProvider",
+        "type": "address"
+      }
+    ],
+    "name": "stakedNu",
+    "outputs": [
+      {
+        "internalType": "uint256",
+        "name": "nuAmount",
+        "type": "uint256"
+      }
+    ],
+    "stateMutability": "view",
+    "type": "function"
+  },
+  {
+    "inputs": [
+      {
+        "internalType": "address",
+        "name": "stakingProvider",
+        "type": "address"
+      }
+    ],
+    "name": "stakes",
+    "outputs": [
+      {
+        "internalType": "uint96",
+        "name": "tStake",
+        "type": "uint96"
+      },
+      {
+        "internalType": "uint96",
+        "name": "keepInTStake",
+        "type": "uint96"
+      },
+      {
+        "internalType": "uint96",
+        "name": "nuInTStake",
+        "type": "uint96"
+      }
+    ],
+    "stateMutability": "view",
+    "type": "function"
+  },
+  {
+    "inputs": [
+      {
+        "internalType": "address",
+        "name": "stakingProvider",
+        "type": "address"
+      },
+      {
+        "internalType": "uint96",
+        "name": "amount",
+        "type": "uint96"
+      }
+    ],
+    "name": "topUp",
+    "outputs": [],
+    "stateMutability": "nonpayable",
+    "type": "function"
+  },
+  {
+    "inputs": [
+      {
+        "internalType": "address",
+        "name": "stakingProvider",
+        "type": "address"
+      }
+    ],
+    "name": "topUpKeep",
+    "outputs": [],
+    "stateMutability": "nonpayable",
+    "type": "function"
+  },
+  {
+    "inputs": [
+      {
+        "internalType": "address",
+        "name": "stakingProvider",
+        "type": "address"
+      }
+    ],
+    "name": "topUpNu",
+    "outputs": [],
+    "stateMutability": "nonpayable",
+    "type": "function"
+  },
+  {
+    "inputs": [
+      {
+        "internalType": "address",
+        "name": "newGuvnor",
+        "type": "address"
+      }
+    ],
+    "name": "transferGovernance",
+    "outputs": [],
+    "stateMutability": "nonpayable",
+    "type": "function"
+  },
+  {
+    "inputs": [
+      {
+        "internalType": "address",
+        "name": "stakingProvider",
+        "type": "address"
+      }
+    ],
+    "name": "unstakeAll",
+    "outputs": [],
+    "stateMutability": "nonpayable",
+    "type": "function"
+  },
+  {
+    "inputs": [
+      {
+        "internalType": "address",
+        "name": "stakingProvider",
+        "type": "address"
+      }
+    ],
+    "name": "unstakeKeep",
+    "outputs": [],
+    "stateMutability": "nonpayable",
+    "type": "function"
+  },
+  {
+    "inputs": [
+      {
+        "internalType": "address",
+        "name": "stakingProvider",
+        "type": "address"
+      },
+      {
+        "internalType": "uint96",
+        "name": "amount",
+        "type": "uint96"
+      }
+    ],
+    "name": "unstakeNu",
+    "outputs": [],
+    "stateMutability": "nonpayable",
+    "type": "function"
+  },
+  {
+    "inputs": [
+      {
+        "internalType": "address",
+        "name": "stakingProvider",
+        "type": "address"
+      },
+      {
+        "internalType": "uint96",
+        "name": "amount",
+        "type": "uint96"
+      }
+    ],
+    "name": "unstakeT",
+    "outputs": [],
+    "stateMutability": "nonpayable",
+    "type": "function"
+  },
+  {
+    "inputs": [
+      {
+        "internalType": "address",
+        "name": "recipient",
+        "type": "address"
+      },
+      {
+        "internalType": "uint96",
+        "name": "amount",
+        "type": "uint96"
+      }
+    ],
+    "name": "withdrawNotificationReward",
+    "outputs": [],
+    "stateMutability": "nonpayable",
+    "type": "function"
+  }
+]
diff --git a/src/web3/hooks/useCheckDuplicateProviderAddress.ts b/src/web3/hooks/useCheckDuplicateProviderAddress.ts
index fa79883c7..a40d8a31d 100644
--- a/src/web3/hooks/useCheckDuplicateProviderAddress.ts
+++ b/src/web3/hooks/useCheckDuplicateProviderAddress.ts
@@ -17,13 +17,15 @@ const useCheckDuplicateProviderAddress = (): ((
 
   const checkIfProviderUsed = useCallback(
     async (stakingProvider) => {
-      if (!tStakingContract || !keepStakingContract) {
-        throw new Error(
-          "The request cannot be executed because the contract instances do not exist."
-        )
+      const multicall = threshold.multicall
+      if (!tStakingContract || !keepStakingContract || !multicall) {
+        return {
+          isProviderUsedForKeep: false,
+          isProviderUsedForT: false,
+        }
       }
 
-      const [{ owner }, [, createdAt]] = await threshold.multicall.aggregate([
+      const [{ owner }, [, createdAt]] = await multicall.aggregate([
         {
           interface: tStakingContract.interface,
           address: tStakingContract.address,
diff --git a/src/web3/hooks/useContract.ts b/src/web3/hooks/useContract.ts
index 2ce6015e9..60e1646ab 100644
--- a/src/web3/hooks/useContract.ts
+++ b/src/web3/hooks/useContract.ts
@@ -1,10 +1,8 @@
 import { useMemo } from "react"
 import { useWeb3React } from "@web3-react/core"
 import { Contract } from "@ethersproject/contracts"
-import { JsonRpcProvider } from "@ethersproject/providers"
-import { getEnvVariable } from "../../utils/getEnvVariable"
+import { getThresholdLibProvider } from "../../utils/getThresholdLib"
 import { getContract } from "../../utils/getContract"
-import { EnvVariable } from "../../enums"
 
 export function useContract<T extends Contract = Contract>(
   address: string,
@@ -21,9 +19,7 @@ export function useContract<T extends Contract = Contract>(
     return getContract(
       address,
       ABI,
-      active
-        ? library
-        : new JsonRpcProvider(getEnvVariable(EnvVariable.ETH_HOSTNAME_HTTP)),
+      active ? library : getThresholdLibProvider(),
       withSignerIfPossible && account ? account : undefined
     )
   }, [address, ABI, library, chainId, withSignerIfPossible, account]) as T
diff --git a/src/web3/hooks/useERC20.ts b/src/web3/hooks/useERC20.ts
index bfc300f02..b4e13b6b8 100644
--- a/src/web3/hooks/useERC20.ts
+++ b/src/web3/hooks/useERC20.ts
@@ -57,7 +57,7 @@ export const useErc20TokenContract: UseErc20Interface = (
 
   const balanceOf = useCallback(
     async (token: Token) => {
-      if (account) {
+      if (account && contract) {
         try {
           setTokenLoading(token, true)
           const balance = await contract?.balanceOf(account as string)
diff --git a/src/web3/hooks/useKeep.ts b/src/web3/hooks/useKeep.ts
index 91d093981..32156040f 100644
--- a/src/web3/hooks/useKeep.ts
+++ b/src/web3/hooks/useKeep.ts
@@ -3,7 +3,17 @@ import { useErc20TokenContract } from "./useERC20"
 import { Token } from "../../enums"
 import { TransactionType } from "../../enums/transactionType"
 import { Contract } from "@ethersproject/contracts"
-import { getContractAddressFromTruffleArtifact } from "../../utils/getContract"
+import { AddressZero } from "@ethersproject/constants"
+import { SupportedChainIds } from "../../networks/enums/networks"
+import { useDefaultOrConnectedChainId } from "../../networks/hooks/useDefaultOrConnectedChainId"
+
+export const KEEP_ADDRESSES = {
+  // https://etherscan.io/address/0x85Eee30c52B0b379b046Fb0F85F4f3Dc3009aFEC
+  [SupportedChainIds.Ethereum]: "0x85Eee30c52B0b379b046Fb0F85F4f3Dc3009aFEC",
+  // https://sepolia.etherscan.io/address/0xa07f4E37C2E7089Ea3AFffbe51A6A281833a4D14
+  [SupportedChainIds.Sepolia]: "0xa07f4E37C2E7089Ea3AFffbe51A6A281833a4D14",
+  [SupportedChainIds.Localhost]: AddressZero,
+} as Record<number | string, string>
 
 export interface UseKeep {
   (): {
@@ -14,8 +24,10 @@ export interface UseKeep {
 }
 
 export const useKeep: UseKeep = () => {
+  const defaultOrConnectedChainId = useDefaultOrConnectedChainId()
+
   const { balanceOf, approve, contract } = useErc20TokenContract(
-    getContractAddressFromTruffleArtifact(KeepToken),
+    KEEP_ADDRESSES[Number(defaultOrConnectedChainId)],
     undefined,
     KeepToken.abi
   )
diff --git a/src/web3/hooks/useKeepBondingContract.ts b/src/web3/hooks/useKeepBondingContract.ts
index 8dbfe5d46..9e96aec1b 100644
--- a/src/web3/hooks/useKeepBondingContract.ts
+++ b/src/web3/hooks/useKeepBondingContract.ts
@@ -1,14 +1,21 @@
+import { AddressZero } from "@ethersproject/constants"
+import { SupportedChainIds } from "../../networks/enums/networks"
 import { useContract } from "./useContract"
 import KeepBonding from "@keep-network/keep-ecdsa/artifacts/KeepBonding.json"
-import { supportedChainId } from "../../utils/getEnvVariable"
+import { useDefaultOrConnectedChainId } from "../../networks/hooks/useDefaultOrConnectedChainId"
+
+const KEEP_BONDING_ADDRESSES = {
+  // https://etherscan.io/address/0x27321f84704a599aB740281E285cc4463d89A3D5
+  [SupportedChainIds.Ethereum]: "0x27321f84704a599aB740281E285cc4463d89A3D5",
+  // TODO: Set local address- how to resolve it in local network?
+  [SupportedChainIds.Localhost]: AddressZero,
+} as Record<number, string>
 
 export const useKeepBondingContract = () => {
+  const defaultOrConnectedChainId = useDefaultOrConnectedChainId()
+
   return useContract(
-    (
-      KeepBonding.networks[
-        supportedChainId as keyof typeof KeepBonding.networks
-      ] as { address: string }
-    )?.address,
+    KEEP_BONDING_ADDRESSES[Number(defaultOrConnectedChainId)],
     KeepBonding.abi
   )
 }
diff --git a/src/web3/hooks/useKeepTokenStakingContract.ts b/src/web3/hooks/useKeepTokenStakingContract.ts
index 0ddff5e16..5a47f456f 100644
--- a/src/web3/hooks/useKeepTokenStakingContract.ts
+++ b/src/web3/hooks/useKeepTokenStakingContract.ts
@@ -1,10 +1,22 @@
 import KeepTokenStaking from "@keep-network/keep-core/artifacts/TokenStaking.json"
 import { useContract } from "./useContract"
-import { getContractAddressFromTruffleArtifact } from "../../utils/getContract"
+import { SupportedChainIds } from "../../networks/enums/networks"
+import { AddressZero } from "@ethersproject/constants"
+import { useDefaultOrConnectedChainId } from "../../networks/hooks/useDefaultOrConnectedChainId"
 
-const KEEP_TOKEN_STAKING_ADDRESS =
-  getContractAddressFromTruffleArtifact(KeepTokenStaking)
+const KEEP_STAKING_ADDRESSES = {
+  // https://etherscan.io/address/0x1293a54e160D1cd7075487898d65266081A15458
+  [SupportedChainIds.Ethereum]: "0x1293a54e160D1cd7075487898d65266081A15458",
+  // https://sepolia.etherscan.io/address/0xa07f4E37C2E7089Ea3AFffbe51A6A281833a4D14
+  [SupportedChainIds.Sepolia]: "0xa07f4E37C2E7089Ea3AFffbe51A6A281833a4D14",
+  [SupportedChainIds.Localhost]: AddressZero,
+} as Record<number, string>
 
 export const useKeepTokenStakingContract = () => {
-  return useContract(KEEP_TOKEN_STAKING_ADDRESS, KeepTokenStaking.abi)
+  const defaultOrConnectedChainId = useDefaultOrConnectedChainId()
+
+  return useContract(
+    KEEP_STAKING_ADDRESSES[Number(defaultOrConnectedChainId)],
+    KeepTokenStaking.abi
+  )
 }
diff --git a/src/web3/hooks/useMerkleDropContract.ts b/src/web3/hooks/useMerkleDropContract.ts
index abdf09f57..1ea386fcc 100644
--- a/src/web3/hooks/useMerkleDropContract.ts
+++ b/src/web3/hooks/useMerkleDropContract.ts
@@ -1,25 +1,32 @@
 import CumulativeMerkleDropABI from "../abi/CumulativeMerkleDrop.json"
 import { useContract } from "./useContract"
-import { supportedChainId } from "../../utils/getEnvVariable"
-import { ChainID } from "../../enums"
 import { AddressZero } from "../utils"
+import { SupportedChainIds } from "../../networks/enums/networks"
+import { useDefaultOrConnectedChainId } from "../../networks/hooks/useDefaultOrConnectedChainId"
 
-export const DEPLOYMENT_BLOCK = supportedChainId === "1" ? 15146501 : 0
+const DEPLOYMENT_BLOCKS: { [key: number]: number } = {
+  [SupportedChainIds.Ethereum]: 15146501,
+  [SupportedChainIds.Sepolia]: 4653467,
+}
 
-const CONTRACT_ADDRESSESS = {
+const MERKLE_DROP_ADDRESSES = {
   // https://etherscan.io/address/0xea7ca290c7811d1cc2e79f8d706bd05d8280bd37
-  [ChainID.Ethereum.valueOf().toString()]:
-    "0xeA7CA290c7811d1cC2e79f8d706bD05d8280BD37",
+  [SupportedChainIds.Ethereum]: "0xeA7CA290c7811d1cC2e79f8d706bD05d8280BD37",
   // https://sepolia.etherscan.io/address/0x4621a14bbB5a53f79Ea532bdc032b8ACc383B153
-  [ChainID.Sepolia.valueOf().toString()]:
-    "0x4621a14bbB5a53f79Ea532bdc032b8ACc383B153",
+  [SupportedChainIds.Sepolia]: "0x4621a14bbB5a53f79Ea532bdc032b8ACc383B153",
   // TODO: Set local address- how to resolve it in local network?
-  [ChainID.Localhost.valueOf().toString()]: AddressZero,
-} as Record<string, string>
+  [SupportedChainIds.Localhost]: AddressZero,
+} as Record<number, string>
+
+export const getMerkleDropDeploymentBlock = () => {
+  const defaultOrConnectedChainId = useDefaultOrConnectedChainId()
+  return DEPLOYMENT_BLOCKS[Number(defaultOrConnectedChainId)] || 0
+}
 
 export const useMerkleDropContract = () => {
+  const defaultOrConnectedChainId = useDefaultOrConnectedChainId()
   return useContract(
-    CONTRACT_ADDRESSESS[supportedChainId],
+    MERKLE_DROP_ADDRESSES[Number(defaultOrConnectedChainId)],
     CumulativeMerkleDropABI
   )
 }
diff --git a/src/web3/hooks/useMulticall.ts b/src/web3/hooks/useMulticall.ts
index 5d6df3f53..05b437215 100644
--- a/src/web3/hooks/useMulticall.ts
+++ b/src/web3/hooks/useMulticall.ts
@@ -1,11 +1,23 @@
 import { useCallback } from "react"
-import { useThreshold } from "../../contexts/ThresholdContext"
+import { useMulticallContract } from "./useMulticallContract"
 import { ContractCall } from "../../threshold-ts/multicall"
 
 export const useMulticall = (calls: ContractCall[]) => {
-  const threshold = useThreshold()
+  const multicall = useMulticallContract()
 
   return useCallback(async () => {
-    return await threshold.multicall.aggregate(calls)
-  }, [JSON.stringify(calls), threshold])
+    if (!multicall) return []
+
+    const callRequests = calls.map((_) => [
+      _.address,
+      _.interface.encodeFunctionData(_.method, _.args),
+    ])
+
+    const [, result] = await multicall.aggregate(callRequests)
+
+    return result.map((data: string, index: number) => {
+      const call = calls[index]
+      return call.interface.decodeFunctionResult(call.method, data)
+    })
+  }, [JSON.stringify(calls), multicall])
 }
diff --git a/src/web3/hooks/useMulticallContract.ts b/src/web3/hooks/useMulticallContract.ts
index 26e9ecddc..5315dc05d 100644
--- a/src/web3/hooks/useMulticallContract.ts
+++ b/src/web3/hooks/useMulticallContract.ts
@@ -1,28 +1,17 @@
-import { AddressZero } from "@ethersproject/constants"
-import { ChainID } from "../../enums"
-import { supportedChainId } from "../../utils/getEnvVariable"
 import { useContract } from "./useContract"
+import { MULTICALL_ADDRESSES } from "../../threshold-ts/multicall"
+import { useDefaultOrConnectedChainId } from "../../networks/hooks/useDefaultOrConnectedChainId"
 
 const MULTICALL_ABI = [
   "function aggregate(tuple(address target, bytes callData)[] calls) view returns (uint256 blockNumber, bytes[] returnData)",
   "function getEthBalance(address addr) view returns (uint256 balance)",
 ]
 
-// Addresses exported from:
-// https://github.com/makerdao/multicall#multicall-contract-addresses
-const MULTICALL_ADDRESSESS = {
-  [ChainID.Ethereum.valueOf()]: "0xeefba1e63905ef1d7acba5a8513c70307c1ce441",
-  // The `makerdao/multicall` repo is deprecated and there is a third-party
-  // fork that deployed Multicall3:
-  // https://github.com/mds1/multicall#existing-deployments.
-  [ChainID.Sepolia.valueOf()]: "0xcA11bde05977b3631167028862bE2a173976CA11",
-  [ChainID.Localhost.valueOf()]:
-    process.env.REACT_APP_MULTICALL_ADDRESS || AddressZero,
-} as Record<number, string>
-
 export const useMulticallContract = () => {
+  const defaultOrConnectedChainId = useDefaultOrConnectedChainId()
+
   return useContract(
-    MULTICALL_ADDRESSESS[Number(supportedChainId)],
+    MULTICALL_ADDRESSES[Number(defaultOrConnectedChainId)],
     MULTICALL_ABI
   )
 }
diff --git a/src/web3/hooks/useNu.ts b/src/web3/hooks/useNu.ts
index 4f9dcd9da..8038ceb20 100644
--- a/src/web3/hooks/useNu.ts
+++ b/src/web3/hooks/useNu.ts
@@ -3,16 +3,10 @@ import { useErc20TokenContract } from "./useERC20"
 import { Token } from "../../enums"
 import { TransactionType } from "../../enums/transactionType"
 import { getArtifact } from "../../threshold-ts/utils"
-import {
-  shouldUseTestnetDevelopmentContracts,
-  supportedChainId,
-} from "../../utils/getEnvVariable"
-
-const nuCupherTokenArtifact = getArtifact(
-  "NuCypherToken",
-  supportedChainId,
-  shouldUseTestnetDevelopmentContracts
-)
+import { shouldUseTestnetDevelopmentContracts } from "../../utils/getEnvVariable"
+import { useIsActive } from "../../hooks/useIsActive"
+import { isL1Network } from "../../networks/utils"
+import { SupportedChainIds } from "../../networks/enums/networks"
 export interface UseNu {
   (): {
     approveNu: () => void
@@ -22,6 +16,17 @@ export interface UseNu {
 }
 
 export const useNu: UseNu = () => {
+  const { chainId } = useIsActive()
+  const supportedChainId = isL1Network(chainId)
+    ? (chainId as number)
+    : SupportedChainIds.Ethereum
+
+  const nuCupherTokenArtifact = getArtifact(
+    "NuCypherToken",
+    supportedChainId,
+    shouldUseTestnetDevelopmentContracts
+  )
+
   const { balanceOf, approve, contract } = useErc20TokenContract(
     nuCupherTokenArtifact.address,
     undefined,
diff --git a/src/web3/hooks/useNuStakingEscrowContract.ts b/src/web3/hooks/useNuStakingEscrowContract.ts
index df0755000..976acadfe 100644
--- a/src/web3/hooks/useNuStakingEscrowContract.ts
+++ b/src/web3/hooks/useNuStakingEscrowContract.ts
@@ -3,5 +3,5 @@ import { useThreshold } from "../../contexts/ThresholdContext"
 export const useNuStakingEscrowContract = () => {
   const threshold = useThreshold()
 
-  return threshold.staking.legacyNuStakingContract
+  return threshold.staking!.legacyNuStakingContract
 }
diff --git a/src/web3/hooks/usePREContract.ts b/src/web3/hooks/usePREContract.ts
index c23e5bf5f..3f810f66d 100644
--- a/src/web3/hooks/usePREContract.ts
+++ b/src/web3/hooks/usePREContract.ts
@@ -1,28 +1,28 @@
 import SimplePREApplicationABI from "../abi/SimplePreApplication.json"
 import { useContract } from "./useContract"
-import { supportedChainId } from "../../utils/getEnvVariable"
-import { ChainID } from "../../enums"
+import { SupportedChainIds } from "../../networks/enums/networks"
 import { AddressZero } from "../utils"
+import { useIsActive } from "../../hooks/useIsActive"
 
-export const PRE_DEPLOYMENT_BLOCK = supportedChainId === "1" ? 14141140 : 0
-
-const PRE_ADDRESSESS = {
+const PRE_ADDRESSES = {
   // https://etherscan.io/address/0x7E01c9c03FD3737294dbD7630a34845B0F70E5Dd
-  [ChainID.Ethereum.valueOf().toString()]:
-    "0x7E01c9c03FD3737294dbD7630a34845B0F70E5Dd",
+  [SupportedChainIds.Ethereum]: "0x7E01c9c03FD3737294dbD7630a34845B0F70E5Dd",
   // https://sepolia.etherscan.io/address/0x471EA40981D278fb3Cb55587e94ac549aad1ACA9
   // As NuCypher hasn't depoyed the `SimplePreApplication` contract on Sepolia,
   // we're using a stub contract.
-  [ChainID.Sepolia.valueOf().toString()]:
-    "0x471EA40981D278fb3Cb55587e94ac549aad1ACA9",
+  [SupportedChainIds.Sepolia]: "0x471EA40981D278fb3Cb55587e94ac549aad1ACA9",
   // Set the correct `SimplePREApplication` contract address. If you deployed
   // the `@threshold-network/solidity-contracts` to your local chain and linked
   // package using `yarn link @threshold-network/solidity-contracts` you can
   // find the contract address at
   // `node_modules/@threshold-network/solidity-contracts/artifacts/SimplePREApplication.json`.
-  [ChainID.Localhost.valueOf().toString()]: AddressZero,
+  [SupportedChainIds.Localhost]: AddressZero,
 } as Record<string, string>
 
 export const usePREContract = () => {
-  return useContract(PRE_ADDRESSESS[supportedChainId], SimplePREApplicationABI)
+  const { chainId } = useIsActive()
+  return useContract(
+    PRE_ADDRESSES[Number(chainId)] || PRE_ADDRESSES[SupportedChainIds.Ethereum],
+    SimplePREApplicationABI
+  )
 }
diff --git a/src/web3/hooks/useT.ts b/src/web3/hooks/useT.ts
index 68907448d..6f6e33eb9 100644
--- a/src/web3/hooks/useT.ts
+++ b/src/web3/hooks/useT.ts
@@ -2,6 +2,17 @@ import T from "@threshold-network/solidity-contracts/artifacts/T.json"
 import { Contract } from "@ethersproject/contracts"
 import { useErc20TokenContract } from "./useERC20"
 import { Token, TransactionType } from "../../enums"
+import { AddressZero } from "@ethersproject/constants"
+import { SupportedChainIds } from "../../networks/enums/networks"
+import { useDefaultOrConnectedChainId } from "../../networks/hooks/useDefaultOrConnectedChainId"
+
+export const T_ADDRESSES = {
+  // https://etherscan.io/address/0xCdF7028ceAB81fA0C6971208e83fa7872994beE5
+  [SupportedChainIds.Ethereum]: "0xCdF7028ceAB81fA0C6971208e83fa7872994beE5",
+  // https://sepolia.etherscan.io/address/0x46abDF5aD1726ba700794539C3dB8fE591854729
+  [SupportedChainIds.Sepolia]: "0x46abDF5aD1726ba700794539C3dB8fE591854729",
+  [SupportedChainIds.Localhost]: AddressZero,
+} as Record<number | string, string>
 
 export interface UseT {
   (): {
@@ -12,8 +23,9 @@ export interface UseT {
 }
 
 export const useT: UseT = () => {
+  const defaultOrConnectedChainId = useDefaultOrConnectedChainId()
   const { balanceOf, approve, contract } = useErc20TokenContract(
-    T.address,
+    T_ADDRESSES[Number(defaultOrConnectedChainId)],
     undefined,
     T.abi
   )
diff --git a/src/web3/hooks/useTBTCTokenContract.ts b/src/web3/hooks/useTBTCTokenContract.ts
index 1900fd6c7..df2e7e2e1 100644
--- a/src/web3/hooks/useTBTCTokenContract.ts
+++ b/src/web3/hooks/useTBTCTokenContract.ts
@@ -1,7 +1,17 @@
-import TBTCToken from "@keep-network/tbtc/artifacts/TBTCToken.json"
 import { useErc20TokenContract } from "./useERC20"
-import { getContractAddressFromTruffleArtifact } from "../../utils/getContract"
+import { AddressZero } from "@ethersproject/constants"
+import { SupportedChainIds } from "../../networks/enums/networks"
+import { useDefaultOrConnectedChainId } from "../../networks/hooks/useDefaultOrConnectedChainId"
+
+export const TBTC_ADDRESSES = {
+  // https://etherscan.io/address/0x8dAEBADE922dF735c38C80C7eBD708Af50815fAa
+  [SupportedChainIds.Ethereum]: "0x8dAEBADE922dF735c38C80C7eBD708Af50815fAa",
+  [SupportedChainIds.Localhost]: AddressZero,
+} as Record<number | string, string>
 
 export const useTBTCTokenContract = () => {
-  return useErc20TokenContract(getContractAddressFromTruffleArtifact(TBTCToken))
+  const defaultOrConnectedChainId = useDefaultOrConnectedChainId()
+  return useErc20TokenContract(
+    TBTC_ADDRESSES[Number(defaultOrConnectedChainId)]
+  )
 }
diff --git a/src/web3/hooks/useTBTCv2TokenContract.ts b/src/web3/hooks/useTBTCv2TokenContract.ts
index dfe429ab0..b261d4419 100644
--- a/src/web3/hooks/useTBTCv2TokenContract.ts
+++ b/src/web3/hooks/useTBTCv2TokenContract.ts
@@ -1,6 +1,22 @@
-import { useThreshold } from "../../contexts/ThresholdContext"
+import { useErc20TokenContract } from "./useERC20"
+import { AddressZero } from "@ethersproject/constants"
+import { SupportedChainIds } from "../../networks/enums/networks"
+import { useDefaultOrConnectedChainId } from "../../networks/hooks/useDefaultOrConnectedChainId"
 
+export const TBTCV2_ADDRESSES = {
+  // https://etherscan.io/address/0x18084fbA666a33d37592fA2633fD49a74DD93a88
+  [SupportedChainIds.Ethereum]: "0x18084fbA666a33d37592fA2633fD49a74DD93a88",
+  // https://sepolia.etherscan.io/address/0x517f2982701695D4E52f1ECFBEf3ba31Df470161
+  [SupportedChainIds.Sepolia]: "0x517f2982701695D4E52f1ECFBEf3ba31Df470161",
+  [SupportedChainIds.Localhost]: AddressZero,
+} as Record<number | string, string>
+
+// Switching wallet networks triggers an ethers error as the app fetches balances from an outdated
+// Threshold class instance. A separate, independent instance for the TBTC v2 token is needed to
+// handle network changes smoothly within the app's lifecycle.
 export const useTBTCv2TokenContract = () => {
-  const threshold = useThreshold()
-  return threshold.tbtc.tokenContract
+  const defaultOrConnectedChainId = useDefaultOrConnectedChainId()
+  return useErc20TokenContract(
+    TBTCV2_ADDRESSES[Number(defaultOrConnectedChainId)]
+  )
 }
diff --git a/src/web3/hooks/useTStakingContract.ts b/src/web3/hooks/useTStakingContract.ts
index 07869937a..52e3b2550 100644
--- a/src/web3/hooks/useTStakingContract.ts
+++ b/src/web3/hooks/useTStakingContract.ts
@@ -1,10 +1,32 @@
-import TStakingContract from "@threshold-network/solidity-contracts/artifacts/TokenStaking.json"
-import { supportedChainId } from "../../utils/getEnvVariable"
+import TokenStakingABI from "../abi/TokenStaking.json"
 import { useContract } from "./useContract"
+import { SupportedChainIds } from "../../networks/enums/networks"
+import { AddressZero } from "@ethersproject/constants"
+import { useDefaultOrConnectedChainId } from "../../networks/hooks/useDefaultOrConnectedChainId"
 
-export const T_STAKING_CONTRACT_DEPLOYMENT_BLOCK =
-  supportedChainId === "1" ? 14113768 : 0
+const DEPLOYMENT_BLOCKS: { [key: number]: number } = {
+  [SupportedChainIds.Ethereum]: 14113768,
+  [SupportedChainIds.Sepolia]: 4653467,
+}
+
+const T_STAKING_ADDRESSES = {
+  // https://etherscan.io/address/0x01B67b1194C75264d06F808A921228a95C765dd7
+  [SupportedChainIds.Ethereum]: "0x01B67b1194C75264d06F808A921228a95C765dd7",
+  // https://sepolia.etherscan.io/address/0x3d4cb85c0e3c5bd1667B7E30f3E86B3FAB878Ff8
+  [SupportedChainIds.Sepolia]: "0x3d4cb85c0e3c5bd1667B7E30f3E86B3FAB878Ff8",
+  // TODO: Set local address- how to resolve it in local network?
+  [SupportedChainIds.Localhost]: AddressZero,
+} as Record<number, string>
+
+export const getTStakingDeploymentBlock = () => {
+  const defaultOrConnectedChainId = useDefaultOrConnectedChainId()
+  return DEPLOYMENT_BLOCKS[Number(defaultOrConnectedChainId)] || 0
+}
 
 export const useTStakingContract = () => {
-  return useContract(TStakingContract.address, TStakingContract.abi)
+  const defaultOrConnectedChainId = useDefaultOrConnectedChainId()
+  return useContract(
+    T_STAKING_ADDRESSES[Number(defaultOrConnectedChainId)],
+    TokenStakingABI
+  )
 }
diff --git a/src/web3/hooks/useVendingMachineContract.ts b/src/web3/hooks/useVendingMachineContract.ts
index 9390e9a79..7fdcc848a 100644
--- a/src/web3/hooks/useVendingMachineContract.ts
+++ b/src/web3/hooks/useVendingMachineContract.ts
@@ -5,6 +5,10 @@ import { useThreshold } from "../../contexts/ThresholdContext"
 export const useVendingMachineContract = (token: UpgredableToken) => {
   const threshold = useThreshold()
 
+  if (!threshold.vendingMachines) {
+    return null
+  }
+
   const TOKEN_TO_VENDING_MACHINE_CONTRACT = {
     [Token.Keep]: threshold.vendingMachines.keep.contract,
     [Token.Nu]: threshold.vendingMachines.nu.contract,
diff --git a/src/web3/hooks/useVendingMachineRatio.ts b/src/web3/hooks/useVendingMachineRatio.ts
index 5763b6b7d..ea02466a4 100644
--- a/src/web3/hooks/useVendingMachineRatio.ts
+++ b/src/web3/hooks/useVendingMachineRatio.ts
@@ -32,16 +32,21 @@ const TOKEN_TO_MUTEX = {
   [Token.Nu]: nuMutex,
 }
 
+const initialRatioValues = {
+  value: "0",
+  contractAddress: AddressZero,
+}
+
 // The `VendingMachine` ratio is constant and set at construction time so we can
 // cache this value in local storage.
 export const useVendingMachineRatio = (token: UpgredableToken) => {
   const vendingMachine = useVendingMachineContract(token)
   const contractAddress = vendingMachine?.address
 
-  const [ratio, setRatio] = useLocalStorage(`${token}-to-T-ratio`, {
-    value: "0",
-    contractAddress: AddressZero,
-  })
+  const [ratio, setRatio] = useLocalStorage(
+    `${token}-to-T-ratio`,
+    initialRatioValues
+  )
 
   const { value: ratioValue, contractAddress: localStorageContractAddress } =
     ratio
@@ -58,7 +63,11 @@ export const useVendingMachineRatio = (token: UpgredableToken) => {
         const unlock = await mutex.lock()
         try {
           const ratio = await vendingMachine?.ratio()
-          setRatio({ value: ratio.toString(), contractAddress })
+          if (!ratio) {
+            setRatio(initialRatioValues)
+          } else {
+            setRatio({ value: ratio.toString(), contractAddress })
+          }
         } catch (error) {
           unlock()
           console.error(`error fetching ${token} VendingMachine ratio`, error)
diff --git a/src/web3/utils/index.ts b/src/web3/utils/index.ts
index f4ddd771c..e18ec8561 100644
--- a/src/web3/utils/index.ts
+++ b/src/web3/utils/index.ts
@@ -2,4 +2,3 @@ export * from "./multicall"
 export * from "./events"
 export * from "./address"
 export * from "./files"
-export * from "./network"

From 770ffbd69fddcfeb84633e17fc206302c70b9341 Mon Sep 17 00:00:00 2001
From: evandrosaturnino <evandro.saturnino@gmail.com>
Date: Tue, 12 Nov 2024 10:38:26 -0300
Subject: [PATCH 07/46] Refactor connector logic to handle multi network

---
 src/App.tsx                                   | 11 +---
 .../useRequestBitcoinAccount.ts               | 13 ++++-
 .../useRequestEthereumAccount.ts              | 10 +++-
 src/hooks/useIsActive.ts                      | 58 ++++++++++++++++++-
 src/web3/connectors/coinbaseWallet.ts         | 14 ++---
 src/web3/connectors/walletConnect.ts          | 41 ++++++-------
 6 files changed, 100 insertions(+), 47 deletions(-)

diff --git a/src/App.tsx b/src/App.tsx
index a28b23132..47e269af7 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -38,7 +38,7 @@ import { useSubscribeToToppedUpEvent } from "./hooks/useSubscribeToToppedUpEvent
 import { pages } from "./pages"
 import { useCheckBonusEligibility } from "./hooks/useCheckBonusEligibility"
 import { useFetchStakingRewards } from "./hooks/useFetchStakingRewards"
-import { isSameChainId, isSameETHAddress } from "./web3/utils"
+import { isSameETHAddress } from "./web3/utils"
 import { ThresholdProvider } from "./contexts/ThresholdContext"
 import { LedgerLiveAppProvider } from "./contexts/LedgerLiveAppContext"
 import {
@@ -133,16 +133,11 @@ const useSubscribeToVendingMachineContractEvents = () => {
 
 const AppBody = () => {
   const dispatch = useDispatch()
-  const { connector, account, chainId, deactivate } = useWeb3React()
+  const { connector, account } = useWeb3React()
 
   useEffect(() => {
     const updateHandler = (update: ConnectorUpdate) => {
-      // if chain is changed then just deactivate the current provider and reset
-      // store
-      if (update.chainId && !isSameChainId(update.chainId, chainId as number)) {
-        dispatch(resetStoreAction())
-        deactivate()
-      } else if (
+      if (
         update.account &&
         !isSameETHAddress(update.account, account as string)
       ) {
diff --git a/src/hooks/ledger-live-app/useRequestBitcoinAccount.ts b/src/hooks/ledger-live-app/useRequestBitcoinAccount.ts
index e6b60a3f1..8e8dec2bb 100644
--- a/src/hooks/ledger-live-app/useRequestBitcoinAccount.ts
+++ b/src/hooks/ledger-live-app/useRequestBitcoinAccount.ts
@@ -3,7 +3,9 @@ import { useRequestAccount as useWalletApiRequestAccount } from "@ledgerhq/walle
 import { useCallback, useEffect } from "react"
 import { useLedgerLiveApp } from "../../contexts/LedgerLiveAppContext"
 import { useWalletApiReactTransport } from "../../contexts/TransportProvider"
-import { supportedChainId } from "../../utils/getEnvVariable"
+import { useWeb3React } from "@web3-react/core"
+import { isTestnetNetwork } from "../../networks/utils"
+import { useDefaultOrConnectedChainId } from "../../networks/hooks/useDefaultOrConnectedChainId"
 import { useIsEmbed } from "../useIsEmbed"
 
 type UseRequestAccountState = {
@@ -23,6 +25,7 @@ export function useRequestBitcoinAccount(): UseRequestAccountReturn {
   const { walletApiReactTransport } = useWalletApiReactTransport()
   const useRequestAccountReturn = useWalletApiRequestAccount()
   const { account, requestAccount } = useRequestAccountReturn
+  const { chainId } = useWeb3React()
   const { isEmbed } = useIsEmbed()
 
   useEffect(() => {
@@ -30,11 +33,15 @@ export function useRequestBitcoinAccount(): UseRequestAccountReturn {
   }, [account, isEmbed])
 
   const requestBitcoinAccount = useCallback(async () => {
-    const currencyId = supportedChainId === "1" ? "bitcoin" : "bitcoin_testnet"
+    const defaultOrConnectedChainId = useDefaultOrConnectedChainId()
+    const currencyId = isTestnetNetwork(defaultOrConnectedChainId)
+      ? "bitcoin_testnet"
+      : "bitcoin"
+
     walletApiReactTransport.connect()
     await requestAccount({ currencyIds: [currencyId] })
     walletApiReactTransport.disconnect()
-  }, [requestAccount, walletApiReactTransport, supportedChainId])
+  }, [requestAccount, walletApiReactTransport, chainId])
 
   return { ...useRequestAccountReturn, requestAccount: requestBitcoinAccount }
 }
diff --git a/src/hooks/ledger-live-app/useRequestEthereumAccount.ts b/src/hooks/ledger-live-app/useRequestEthereumAccount.ts
index 016799ad1..130cce76c 100644
--- a/src/hooks/ledger-live-app/useRequestEthereumAccount.ts
+++ b/src/hooks/ledger-live-app/useRequestEthereumAccount.ts
@@ -4,7 +4,8 @@ import { useCallback, useEffect } from "react"
 import { useLedgerLiveApp } from "../../contexts/LedgerLiveAppContext"
 import { useWalletApiReactTransport } from "../../contexts/TransportProvider"
 import { walletConnected } from "../../store/account"
-import { supportedChainId } from "../../utils/getEnvVariable"
+import { isTestnetNetwork } from "../../networks/utils"
+import { useDefaultOrConnectedChainId } from "../../networks/hooks/useDefaultOrConnectedChainId"
 import { useAppDispatch } from "../store/useAppDispatch"
 import { useIsEmbed } from "../useIsEmbed"
 import { useWeb3React } from "@web3-react/core"
@@ -43,14 +44,17 @@ export function useRequestEthereumAccount(): UseRequestAccountReturn {
   }, [account, isEmbed])
 
   const requestEthereumAccount = useCallback(async () => {
+    const defaultOrConnectedChainId = useDefaultOrConnectedChainId()
     // The Goerli testnet become deprecated. However, we did not test Ledger
     // Live on Sepolia yet, so we're leaving the Goerli config for now in the
     // code.
-    const currencyId = supportedChainId === "1" ? "ethereum" : "ethereum_goerli"
+    const currencyId = isTestnetNetwork(defaultOrConnectedChainId)
+      ? "ethereum_goerli"
+      : "ethereum"
     walletApiReactTransport.connect()
     await requestAccount({ currencyIds: [currencyId] })
     walletApiReactTransport.disconnect()
-  }, [requestAccount, walletApiReactTransport, supportedChainId])
+  }, [requestAccount, walletApiReactTransport, chainId])
 
   return { ...useRequestAccountReturn, requestAccount: requestEthereumAccount }
 }
diff --git a/src/hooks/useIsActive.ts b/src/hooks/useIsActive.ts
index 7f79e0f4e..22aa90ae4 100644
--- a/src/hooks/useIsActive.ts
+++ b/src/hooks/useIsActive.ts
@@ -1,14 +1,17 @@
 import { useWeb3React } from "@web3-react/core"
 import { useCallback, useMemo } from "react"
 import { useLedgerLiveApp } from "../contexts/LedgerLiveAppContext"
-import { supportedChainId } from "../utils/getEnvVariable"
+import { networks, toHex } from "../networks/utils"
 import { useIsEmbed } from "./useIsEmbed"
+import { AbstractConnector } from "../web3/connectors"
 
 type UseIsActiveResult = {
   account: string | undefined
   chainId: number | undefined
   isActive: boolean
+  connector: AbstractConnector | undefined
   deactivate: () => void
+  switchNetwork: (chainId: number) => Promise<void>
 }
 
 /**
@@ -21,12 +24,59 @@ export const useIsActive = (): UseIsActiveResult => {
     active: _active,
     account: _account,
     chainId: _chainId,
+    connector: _connector,
     deactivate: _deactivate,
+    activate: _activate,
   } = useWeb3React()
-  const { ethAccount, setEthAccount } = useLedgerLiveApp()
+  const { ethAccount, ethAccountChainId, setEthAccount } = useLedgerLiveApp()
   const ledgerLiveAppEthAddress = ethAccount?.address || undefined
+  const ledgerLiveAppEthChaindId = ethAccountChainId
   const { isEmbed } = useIsEmbed()
 
+  const switchNetwork = useCallback(async (chainId: number): Promise<void> => {
+    if (_connector) {
+      const provider = await _connector.getProvider()
+      const desiredChainIdHex = toHex(chainId)
+
+      await provider
+        .request({
+          method: "wallet_switchEthereumChain",
+          params: [{ chainId: desiredChainIdHex }],
+        })
+        .catch(async (error: any) => {
+          const errorCode =
+            (error?.data as any)?.originalError?.code || error.code
+
+          if (errorCode === 4902) {
+            if (!provider) throw new Error("No provider")
+
+            const network = networks.find((net) => net.chainId === chainId)
+            if (!network || !network.chainParameters) {
+              throw new Error("Network parameters not found")
+            }
+
+            // Add the chain to MetaMask
+            await provider.request({
+              method: "wallet_addEthereumChain",
+              params: [
+                {
+                  ...network.chainParameters,
+                  chainId: desiredChainIdHex,
+                },
+              ],
+            })
+
+            // After adding, switch to the new chain
+            await provider.request({
+              method: "wallet_switchEthereumChain",
+              params: [{ chainId: desiredChainIdHex }],
+            })
+          }
+          throw error
+        })
+    }
+  }, [])
+
   const isActive = useMemo(() => {
     if (isEmbed) {
       return !!ledgerLiveAppEthAddress
@@ -40,8 +90,10 @@ export const useIsActive = (): UseIsActiveResult => {
 
   return {
     account: (isEmbed ? ledgerLiveAppEthAddress : _account) || undefined,
-    chainId: isEmbed ? Number(supportedChainId) : _chainId,
+    chainId: isEmbed ? ledgerLiveAppEthChaindId : _chainId,
     isActive,
+    connector: _connector,
     deactivate: isEmbed ? deactivateLedgerLiveApp : _deactivate,
+    switchNetwork,
   }
 }
diff --git a/src/web3/connectors/coinbaseWallet.ts b/src/web3/connectors/coinbaseWallet.ts
index 1ec6838be..012669b98 100644
--- a/src/web3/connectors/coinbaseWallet.ts
+++ b/src/web3/connectors/coinbaseWallet.ts
@@ -1,17 +1,15 @@
 import { WalletLinkConnector } from "@web3-react/walletlink-connector"
 import { ConnectorUpdate } from "@web3-react/types"
-import { supportedChainId, getEnvVariable } from "../../utils/getEnvVariable"
-import { EnvVariable } from "../../enums"
+import { getRpcUrl, supportedNetworksMap } from "../../networks/utils"
 
 interface CoinbaseWalletProvider {
   isCoinbaseWallet: boolean
   overrideIsMetaMask: boolean
   updateProviderInfo(rpcUrl: string, chainId: number, fromRelay: boolean): void
   providers: CoinbaseWalletProvider[]
+  chainId?: number
 }
 
-const rpcUrl = getEnvVariable(EnvVariable.ETH_HOSTNAME_HTTP)
-
 export class CoinbaseWalletConnector extends WalletLinkConnector {
   activate = async (): Promise<ConnectorUpdate<string | number>> => {
     // Handle the case when MetaMask and Coinbase Wallet are both installed.
@@ -20,6 +18,8 @@ export class CoinbaseWalletConnector extends WalletLinkConnector {
         (p) => p.isCoinbaseWallet
       ) ?? (window.ethereum as CoinbaseWalletProvider)
 
+    const chainId = provider.chainId || (await this.getChainId())
+
     if (provider.isCoinbaseWallet) {
       // Force the Coinbase Wallet provider to use our RPC url. We can't fetch
       // past events from block range greater than `1000` when using the default
@@ -30,7 +30,7 @@ export class CoinbaseWalletConnector extends WalletLinkConnector {
       // only enforced during type checking. This means that JavaScript runtime
       // constructs like `in` or simple property lookup can still access a
       // `private` or `protected` member.
-      provider.updateProviderInfo(rpcUrl, +supportedChainId, true)
+      provider.updateProviderInfo(getRpcUrl(chainId), chainId, true)
     }
 
     return await super.activate()
@@ -38,7 +38,7 @@ export class CoinbaseWalletConnector extends WalletLinkConnector {
 }
 
 export const coinbaseConnector = new CoinbaseWalletConnector({
-  url: rpcUrl,
+  url: getRpcUrl(),
   appName: "threshold-token-dashboard",
-  supportedChainIds: [+supportedChainId],
+  supportedChainIds: Object.keys(supportedNetworksMap).map(Number),
 })
diff --git a/src/web3/connectors/walletConnect.ts b/src/web3/connectors/walletConnect.ts
index 4ecf19ae4..581577bb9 100644
--- a/src/web3/connectors/walletConnect.ts
+++ b/src/web3/connectors/walletConnect.ts
@@ -3,11 +3,12 @@ import { AbstractConnector } from "@web3-react/abstract-connector"
 import { ConnectorUpdate } from "@web3-react/types"
 import { EnvVariable } from "../../enums"
 import { ArrayOneOrMore } from "../../types"
-import { getEnvVariable, supportedChainId } from "../../utils/getEnvVariable"
+import { getEnvVariable } from "../../utils/getEnvVariable"
+import { getRpcUrl, networks, supportedNetworksMap } from "../../networks/utils"
+import { toHex } from "../../networks/utils/chainId"
+import { EthereumRpcMap } from "../../networks/types/networks"
 
-export interface EthereumRpcMap {
-  [chainId: string]: string
-}
+const supportedNetworks = Object.keys(supportedNetworksMap).map(Number)
 
 export type WalletConnectOptions = Omit<
   Parameters<typeof WalletConnectProvider.init>[0],
@@ -24,14 +25,6 @@ export class UserRejectedRequestError extends Error {
   }
 }
 
-function getSupportedChains({ chains, rpc }: WalletConnectOptions): number[] {
-  if (chains) {
-    return chains
-  }
-
-  return rpc ? Object.keys(rpc).map((k) => Number(k)) : []
-}
-
 /**
  * Connector for WalletConnect V2
  */
@@ -41,7 +34,7 @@ export class WalletConnectConnector extends AbstractConnector {
   private rpcMap: EthereumRpcMap
 
   constructor(config: WalletConnectOptions) {
-    super({ supportedChainIds: getSupportedChains(config) })
+    super({ supportedChainIds: config.chains })
     this.config = config
     this.rpcMap = config.rpc
 
@@ -59,7 +52,9 @@ export class WalletConnectConnector extends AbstractConnector {
 
   private handleChainChanged(newChainId: number | string): void {
     this.emitUpdate({ chainId: newChainId })
-    if (newChainId !== `0x${chainId}`) this.deactivate()
+    const newChainIdInHex = toHex(newChainId)
+    if (!supportedNetworks.map(toHex).includes(newChainIdInHex))
+      this.deactivate()
   }
 
   private handleAccountsChanged(accounts: string[]): void {
@@ -89,8 +84,8 @@ export class WalletConnectConnector extends AbstractConnector {
       .filter((x) => x.startsWith("wc@2"))
       .forEach((x) => localStorage.removeItem(x))
     if (!this.provider) {
-      const chains = getSupportedChains(this.config)
-      if (chains.length === 0) throw new Error("Chains not specified!")
+      const chains = this.config.chains
+      if (chains?.length === 0) throw new Error("Chains not specified!")
       this.provider = await WalletConnectProvider.init({
         projectId: this.config.projectId,
         chains: chains as ArrayOneOrMore<number>,
@@ -99,7 +94,8 @@ export class WalletConnectConnector extends AbstractConnector {
       })
     }
 
-    if (chainId !== this.provider.chainId) {
+    const providerChainIdInHex = toHex(this.provider.chainId)
+    if (!supportedNetworks.map(toHex).includes(providerChainIdInHex)) {
       this.deactivate()
     }
 
@@ -179,17 +175,16 @@ export class WalletConnectConnector extends AbstractConnector {
   }
 }
 
-const rpcUrl = getEnvVariable(EnvVariable.ETH_HOSTNAME_HTTP)
-const chainId = +supportedChainId
 const walletConnectProjectId = getEnvVariable(
   EnvVariable.WALLET_CONNECT_PROJECT_ID
 )
 
 export const walletConnect = new WalletConnectConnector({
-  chains: [chainId],
-  rpc: {
-    [Number(supportedChainId)]: rpcUrl as string,
-  },
+  chains: supportedNetworks,
+  rpc: networks.reduce((acc, network) => {
+    acc[network.chainId] = getRpcUrl(network.chainId)
+    return acc
+  }, {} as EthereumRpcMap),
   projectId: walletConnectProjectId,
   showQrModal: true,
 })

From cf6e80883f73355b6c8d7db978e4bce952f840c7 Mon Sep 17 00:00:00 2001
From: evandrosaturnino <evandro.saturnino@gmail.com>
Date: Tue, 12 Nov 2024 10:41:19 -0300
Subject: [PATCH 08/46] Add switch support to multiple networks

---
 src/components/Navbar/NavbarComponent.tsx |   2 +-
 src/components/Navbar/NetworkButton.tsx   | 178 ++++++++++++++--------
 src/static/icons/Arbitrum.tsx             |  63 ++++++++
 src/static/icons/Base.tsx                 |  15 ++
 4 files changed, 196 insertions(+), 62 deletions(-)
 create mode 100644 src/static/icons/Arbitrum.tsx
 create mode 100644 src/static/icons/Base.tsx

diff --git a/src/components/Navbar/NavbarComponent.tsx b/src/components/Navbar/NavbarComponent.tsx
index f3aa28b79..f93bfad54 100644
--- a/src/components/Navbar/NavbarComponent.tsx
+++ b/src/components/Navbar/NavbarComponent.tsx
@@ -64,7 +64,7 @@ const NavbarComponent: FC<NavbarComponentProps> = ({
         </Flex>
         <Stack spacing={4} direction="row" ml="auto">
           <DarkModeSwitcher />
-          {chainId && <NetworkButton chainId={chainId} />}
+          {chainId && <NetworkButton />}
           <AccountButton {...{ openWalletModal, deactivate, account }} />
         </Stack>
         <VStack
diff --git a/src/components/Navbar/NetworkButton.tsx b/src/components/Navbar/NetworkButton.tsx
index bbdedb85b..492b66091 100644
--- a/src/components/Navbar/NetworkButton.tsx
+++ b/src/components/Navbar/NetworkButton.tsx
@@ -5,87 +5,143 @@ import {
   IconButton,
   useColorMode,
   useColorModeValue,
+  Menu,
+  MenuButton,
+  MenuItem,
+  MenuList,
 } from "@chakra-ui/react"
-import { BsQuestionCircleFill, MdOutlineTrain } from "react-icons/all"
-import { ChainID } from "../../enums"
+import { BsQuestionCircleFill } from "react-icons/all"
+import { ChevronDownIcon, ChevronUpIcon } from "@chakra-ui/icons"
 import { EthereumLight } from "../../static/icons/EthereumLight"
 import { EthereumDark } from "../../static/icons/EthereumDark"
-import chainIdToNetworkName from "../../utils/chainIdToNetworkName"
+import { Arbitrum } from "../../static/icons/Arbitrum"
+import { Base } from "../../static/icons/Base"
+import { chainIdToChainParameterName, networks } from "../../networks/utils"
+import { useIsActive } from "../../hooks/useIsActive"
+import { SupportedChainIds } from "../../networks/enums/networks"
 
 interface NetworkIconMap {
-  [chainId: number]: { icon: ReactElement; bg: string }
+  icon: ReactElement
+  bg: string
 }
 
-const NetworkButton: FC<{ chainId?: number }> = ({ chainId }) => {
-  const { colorMode } = useColorMode()
-  const ethereumLogo = useMemo(
-    () => (colorMode === "light" ? EthereumDark : EthereumLight),
-    [colorMode]
-  )
+const getNetworkIcon = (chainId: number, colorMode: string): NetworkIconMap => {
+  const ethereumLogo = colorMode === "light" ? EthereumDark : EthereumLight
+  const grayBackground = "gray.700"
 
-  const networkIconMap: NetworkIconMap = {
-    [ChainID.Ethereum]: {
-      icon: <Icon as={ethereumLogo} />,
-      bg: "gray.700",
+  const iconMap: Record<number, NetworkIconMap> = {
+    [SupportedChainIds.Ethereum]: {
+      icon: <Icon as={ethereumLogo} boxSize="5" />,
+      bg: grayBackground,
+    },
+    [SupportedChainIds.Sepolia]: {
+      icon: <Icon as={ethereumLogo} boxSize="5" />,
+      bg: grayBackground,
+    },
+    [SupportedChainIds.Arbitrum]: {
+      icon: <Icon as={Arbitrum} boxSize="5" />,
+      bg: grayBackground,
+    },
+    [SupportedChainIds.ArbitrumSepolia]: {
+      icon: <Icon as={Arbitrum} boxSize="5" />,
+      bg: grayBackground,
     },
-    [ChainID.Sepolia]: {
+    [SupportedChainIds.Base]: { icon: <Icon as={Base} />, bg: grayBackground },
+    [SupportedChainIds.BaseSepolia]: {
+      icon: <Icon as={Base} boxSize="5" />,
+      bg: "blue.500",
+    },
+  }
+
+  return (
+    iconMap[chainId] || {
       icon: (
         <Icon
-          as={MdOutlineTrain}
-          color={useColorModeValue("yellow.500", "white")}
+          as={BsQuestionCircleFill}
+          color={useColorModeValue("red.500", "white")}
+          boxSize="5"
         />
       ),
-      bg: "yellow.500",
-    },
-  }
+      bg: "red.500",
+    }
+  )
+}
 
-  const networkIcon = networkIconMap[chainId || 0] || {
-    icon: (
-      <Icon
-        as={BsQuestionCircleFill}
-        color={useColorModeValue("red.500", "white")}
-      />
-    ),
-    bg: "red.500",
-  }
+const NetworkButton: FC = () => {
+  const { colorMode } = useColorMode()
+  const { chainId, switchNetwork } = useIsActive()
+
+  const networkIcon = useMemo(
+    () => getNetworkIcon(chainId || 0, colorMode),
+    [chainId, colorMode]
+  )
+
+  const renderMenuItems = () =>
+    networks
+      .filter((network) => network.chainParameters.chainName !== "Localhost")
+      .map((network) => {
+        const { icon } = getNetworkIcon(network.chainId, colorMode)
+        return (
+          <MenuItem
+            key={network.chainId}
+            onClick={() => switchNetwork(network.chainId)}
+            iconSpacing="4"
+            display="flex"
+            gap="3"
+          >
+            {icon}
+            {network.chainParameters?.chainName}
+          </MenuItem>
+        )
+      })
 
   return (
     <>
       {/* Mobile */}
-      <IconButton
-        variant="unstyled"
-        as={Button}
-        display={{
-          base: "inherit",
-          md: "none",
-        }}
-        _hover={{
-          bg: useColorModeValue("transparent", networkIcon.bg),
-        }}
-        _active={{
-          bg: useColorModeValue("transparent", networkIcon.bg),
-        }}
-        bg={useColorModeValue("transparent", networkIcon.bg)}
-        border="1px solid"
-        borderColor={useColorModeValue("gray.300", "transparent")}
-        icon={networkIcon.icon}
-        aria-label="network"
-      />
+      <Menu>
+        {({ isOpen }) => (
+          <>
+            <MenuButton
+              as={IconButton}
+              variant="unstyled"
+              display={{ base: "inherit", md: "none" }}
+              _hover={{ bg: useColorModeValue("transparent", networkIcon.bg) }}
+              _active={{ bg: useColorModeValue("transparent", networkIcon.bg) }}
+              bg={useColorModeValue("transparent", networkIcon.bg)}
+              border="1px solid"
+              borderColor={useColorModeValue("gray.300", "transparent")}
+              icon={
+                <>
+                  {networkIcon.icon}
+                  {isOpen ? <ChevronUpIcon /> : <ChevronDownIcon />}
+                </>
+              }
+              aria-label="network"
+            />
+            <MenuList>{renderMenuItems()}</MenuList>
+          </>
+        )}
+      </Menu>
 
       {/* Desktop */}
-      <Button
-        variant="outline"
-        _hover={{
-          bg: "transparent",
-        }}
-        _active={{
-          bg: "transparent",
-        }}
-        leftIcon={networkIcon.icon}
-        display={{ base: "none", md: "inherit" }}
-      >
-        {chainIdToNetworkName(chainId)}
-      </Button>
+      <Menu>
+        {({ isOpen }) => (
+          <>
+            <MenuButton
+              as={Button}
+              variant="outline"
+              _hover={{ bg: "transparent" }}
+              _active={{ bg: "transparent" }}
+              leftIcon={networkIcon.icon}
+              rightIcon={isOpen ? <ChevronUpIcon /> : <ChevronDownIcon />}
+              display={{ base: "none", md: "inherit" }}
+            >
+              {chainIdToChainParameterName(chainId)}
+            </MenuButton>
+            <MenuList>{renderMenuItems()}</MenuList>
+          </>
+        )}
+      </Menu>
     </>
   )
 }
diff --git a/src/static/icons/Arbitrum.tsx b/src/static/icons/Arbitrum.tsx
new file mode 100644
index 000000000..4274f6b45
--- /dev/null
+++ b/src/static/icons/Arbitrum.tsx
@@ -0,0 +1,63 @@
+import { createIcon } from "@chakra-ui/icons"
+
+export const Arbitrum = createIcon({
+  displayName: "Arbitrum",
+  viewBox: "0 0 1080 1080",
+  path: (
+    <svg
+      width="1080"
+      height="1080"
+      fill="none"
+      xmlns="http://www.w3.org/2000/svg"
+    >
+      <path
+        fill="#213147"
+        d="M171.5,363.6v352.8c0,22.5,12,43.4,31.5,54.6l305.5,176.4c19.5,11.2,43.5,11.2,63,0L877.1,771
+          c19.5-11.2,31.5-32.1,31.5-54.6V363.6c0-22.5-12-43.4-31.5-54.6L571.6,132.6c-19.5-11.2-43.5-11.2-63,0L203,309
+          C183.5,320.3,171.5,341.1,171.5,363.6z"
+      />
+      <g>
+        <g>
+          <g>
+            <path
+              fill="#12AAFF"
+              d="M606.7,608.4l-43.6,119.5c-1.2,3.3-1.2,6.9,0,10.3l75,205.6l86.7-50.1L620.7,608.4
+                C618.4,601.9,609.1,601.9,606.7,608.4z"
+            />
+          </g>
+          <g>
+            <path
+              fill="#12AAFF"
+              d="M694.1,407.5c-2.4-6.6-11.7-6.6-14,0L636.5,527c-1.2,3.3-1.2,6.9,0,10.3l122.8,336.6l86.7-50.1L694.1,407.5
+                z"
+            />
+          </g>
+        </g>
+      </g>
+      <path
+        fill="#9DCCED"
+        d="M540,145.8c2.1,0,4.3,0.6,6.2,1.6l330.6,190.9c3.8,2.2,6.2,6.4,6.2,10.7v381.8c0,4.4-2.4,8.5-6.2,10.7
+          L546.2,932.4c-1.8,1.1-4.1,1.6-6.2,1.6c-2.1,0-4.3-0.6-6.2-1.6L203.2,741.7c-3.8-2.2-6.2-6.4-6.2-10.7V349.1
+          c0-4.4,2.4-8.5,6.2-10.7l330.6-190.9C535.7,146.4,537.9,145.8,540,145.8 M540,90c-11.7,0-23.6,3-34.1,9.2L175.3,290
+          c-21.1,12.2-34.1,34.7-34.1,59.1v381.8c0,24.4,13,46.9,34.1,59.1L506,980.9c10.6,6.1,22.3,9.2,34.1,9.2c11.7,0,23.6-3,34.1-9.2
+          L904.9,790c21.1-12.2,34.1-34.7,34.1-59.1V349.1c0-24.4-13-46.9-34.1-59.1L574.1,99.2C563.6,93.1,551.8,90,540,90L540,90z"
+      />
+      <polygon
+        fill="#213147"
+        points="321.3,874.3 351.8,791 413,841.9 355.8,894.2"
+      />
+      <g>
+        <path
+          fill="#FFFFFF"
+          d="M512.2,321.8h-83.8c-6.3,0-11.9,3.9-14,9.8L234.6,824.2l86.7,50.1l197.9-542.5
+            C521,327,517.4,321.8,512.2,321.8z"
+        />
+        <path
+          fill="#FFFFFF"
+          d="M658.9,321.8H575c-6.3,0-11.9,3.9-14,9.8L355.8,894.1l86.7,50.1l223.3-612.3C667.6,327,664,321.8,658.9,321.8
+            z"
+        />
+      </g>
+    </svg>
+  ),
+})
diff --git a/src/static/icons/Base.tsx b/src/static/icons/Base.tsx
new file mode 100644
index 000000000..dd3229b63
--- /dev/null
+++ b/src/static/icons/Base.tsx
@@ -0,0 +1,15 @@
+import { createIcon } from "@chakra-ui/icons"
+
+export const Base = createIcon({
+  displayName: "Base",
+  viewBox: "0 0 146 146", // Ensure viewBox matches the desired dimensions
+  path: (
+    <>
+      <circle cx="73" cy="73" r="73" fill="#0052FF" />
+      <path
+        fill="#fff"
+        d="M73.323 123.729c28.294 0 51.23-22.897 51.23-51.141 0-28.245-22.936-51.142-51.23-51.142-26.843 0-48.865 20.61-51.052 46.843h67.715v8.597H22.27c2.187 26.233 24.209 46.843 51.052 46.843Z"
+      />
+    </>
+  ),
+})

From 8daf9bc8c20676e94a9cebdac20c65c22ef416ae Mon Sep 17 00:00:00 2001
From: evandrosaturnino <evandro.saturnino@gmail.com>
Date: Tue, 12 Nov 2024 10:42:19 -0300
Subject: [PATCH 09/46] Fix subgraph issue by migrating to studio services

---
 src/utils/subgraphAPI.ts | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/src/utils/subgraphAPI.ts b/src/utils/subgraphAPI.ts
index 34d3caf2d..68672c885 100644
--- a/src/utils/subgraphAPI.ts
+++ b/src/utils/subgraphAPI.ts
@@ -1,7 +1,10 @@
 import axios from "axios"
+import { EnvVariable } from "../enums"
+import { getEnvVariable } from "./getEnvVariable"
 
-const TBTC_SUBGRAPH_URL =
-  "https://api.thegraph.com/subgraphs/name/suntzu93/threshold-tbtc"
+const tbtcSubgraphApi = getEnvVariable(EnvVariable.TBTC_SUBGRAPH_API)
+export const TBTC_SUBGRAPH_ID = "DETCX5Xm6tJfctRcZAxhQB9q3aK8P4BXLbujHmzEBXYV"
+export const TBTC_SUBGRAPH_URL = `https://gateway.thegraph.com/api/${tbtcSubgraphApi}/subgraphs/id/${TBTC_SUBGRAPH_ID}`
 
 const LIMIT_FOR_ONE_QUERY = 1000
 

From ac14cd3cafe348d2df2d6a755a6ce5393eb470d8 Mon Sep 17 00:00:00 2001
From: evandrosaturnino <evandro.saturnino@gmail.com>
Date: Tue, 12 Nov 2024 10:43:23 -0300
Subject: [PATCH 10/46] Fix cooldown period for different apps

---
 .../DeauthorizationInitiated.tsx              | 19 +++++++++++++------
 .../Modal/TACoCommitmentModal/index.tsx       |  2 +-
 .../AuthorizingApplicationsCard.tsx           |  6 +++---
 3 files changed, 17 insertions(+), 10 deletions(-)

diff --git a/src/components/Modal/StakingApplications/DeauthorizationInitiated.tsx b/src/components/Modal/StakingApplications/DeauthorizationInitiated.tsx
index 537dd5152..95f884018 100644
--- a/src/components/Modal/StakingApplications/DeauthorizationInitiated.tsx
+++ b/src/components/Modal/StakingApplications/DeauthorizationInitiated.tsx
@@ -20,14 +20,16 @@ import ViewInBlockExplorer from "../../ViewInBlockExplorer"
 import withBaseModal from "../withBaseModal"
 import shortenAddress from "../../../utils/shortenAddress"
 import { formatTokenAmount } from "../../../utils/formatAmount"
-import { ExplorerDataType } from "../../../utils/createEtherscanLink"
+import { ExplorerDataType } from "../../../networks/enums/networks"
 import { BaseModalProps } from "../../../types"
 import ModalCloseButton from "../ModalCloseButton"
+import { StakingAppName } from "../../../store/staking-applications"
 
 export type DeauthorizationInitiatedProps = BaseModalProps & {
   stakingProvider: string
   txHash: string
   decreaseAmount: string
+  stakingAppName: StakingAppName
 }
 
 // TODO: revisit because we have the same layout for `AuthorizationIncreased`
@@ -36,6 +38,7 @@ const DeauthorizationInitiatedBase: FC<DeauthorizationInitiatedProps> = ({
   stakingProvider,
   txHash,
   decreaseAmount,
+  stakingAppName,
   closeModal,
 }) => {
   return (
@@ -45,8 +48,10 @@ const DeauthorizationInitiatedBase: FC<DeauthorizationInitiatedProps> = ({
       <ModalBody>
         <Alert status="success" mb={4}>
           <AlertIcon />
-          Your deauthorization was initiated. Your 45 day cooldown period has
-          started.
+          {`Your deauthorization was initiated. Your ${
+            stakingAppName === "taco" ? "6 month" : "45 day"
+          } cooldown period has
+          started.`}
         </Alert>
         <List spacing="2.5" my="6">
           <ListItem>
@@ -76,12 +81,14 @@ const DeauthorizationInitiatedBase: FC<DeauthorizationInitiatedProps> = ({
           </FlowStep>
           <FlowStep
             preTitle="Step 2"
-            title="45 day cooldown"
+            title={`${
+              stakingAppName === "taco" ? "6 month" : "45 day"
+            } cooldown`}
             status={FlowStepStatus.active}
             size="sm"
           >
-            You must wait a 45 day cooldown to then confirm the deauthorization.
-            This is 1 transaction.
+            You must wait a {stakingAppName === "taco" ? "6 month" : "45 day"}{" "}
+            cooldown to then confirm the deauthorization. This is 1 transaction.
           </FlowStep>
         </Stack>
         <Alert status="warning" mb="12">
diff --git a/src/components/Modal/TACoCommitmentModal/index.tsx b/src/components/Modal/TACoCommitmentModal/index.tsx
index c9248f798..c71342dbd 100644
--- a/src/components/Modal/TACoCommitmentModal/index.tsx
+++ b/src/components/Modal/TACoCommitmentModal/index.tsx
@@ -63,7 +63,7 @@ const TACoCommitmentModal: FC<TACoCommitProps> = ({
     [authorizedAmount]
   )
   const { sendTransaction } = useSendTransactionFromFn(
-    threshold.multiAppStaking[stakingAppNameToThresholdAppService["taco"]]
+    threshold.multiAppStaking![stakingAppNameToThresholdAppService["taco"]]
       .makeCommitment,
     onSuccess
   )
diff --git a/src/pages/Staking/HowItWorks/StakingOverview/AuthorizingApplicationsCard.tsx b/src/pages/Staking/HowItWorks/StakingOverview/AuthorizingApplicationsCard.tsx
index be6609a53..84897e385 100644
--- a/src/pages/Staking/HowItWorks/StakingOverview/AuthorizingApplicationsCard.tsx
+++ b/src/pages/Staking/HowItWorks/StakingOverview/AuthorizingApplicationsCard.tsx
@@ -58,11 +58,11 @@ export const AuthorizingApplicationsCard: FC<ComponentProps<typeof Card>> = (
         <FlowStep
           status={FlowStepStatus.active}
           preTitle="Step 2"
-          title="45 day cooldown"
+          title="period of cooldown"
           size="sm"
         >
-          You must wait a 45 day cooldown to then confirm the deauthorization.
-          This is 1 transaction.
+          There is a deauthorization cooldown period of 45 days for tBTC and
+          Random Beacon apps and 6 months for TACo.
         </FlowStep>
       </Stack>
     </Card>

From d63a20808cc3ba22200e414535c2575a4f2080f9 Mon Sep 17 00:00:00 2001
From: evandrosaturnino <evandro.saturnino@gmail.com>
Date: Tue, 12 Nov 2024 10:45:18 -0300
Subject: [PATCH 11/46] Update threshold class to accommodate multiple networks

---
 src/contexts/ThresholdContext.tsx |  27 +--
 src/threshold-ts/index.ts         |  43 +++--
 src/threshold-ts/tbtc/index.ts    | 287 ++++++++++++++++++++++++------
 3 files changed, 272 insertions(+), 85 deletions(-)

diff --git a/src/contexts/ThresholdContext.tsx b/src/contexts/ThresholdContext.tsx
index 897755e82..9bd60cbfe 100644
--- a/src/contexts/ThresholdContext.tsx
+++ b/src/contexts/ThresholdContext.tsx
@@ -1,12 +1,12 @@
-import { useWeb3React } from "@web3-react/core"
 import { createContext, FC, useContext, useEffect, useRef } from "react"
-import {
-  getDefaultThresholdLibProvider,
-  threshold,
-} from "../utils/getThresholdLib"
+import { getThresholdLibProvider, threshold } from "../utils/getThresholdLib"
 import { useLedgerLiveApp } from "./LedgerLiveAppContext"
 import { useIsActive } from "../hooks/useIsActive"
 import { useIsEmbed } from "../hooks/useIsEmbed"
+import { isTestnetNetwork } from "../networks/utils/connectedNetwork"
+import { BitcoinNetwork } from "@keep-network/tbtc-v2.ts"
+import { getDefaultProviderChainId } from "../utils/getEnvVariable"
+import { useWeb3React } from "@web3-react/core"
 
 const ThresholdContext = createContext(threshold)
 
@@ -18,18 +18,24 @@ export const ThresholdProvider: FC = ({ children }) => {
   const { library } = useWeb3React()
   const hasThresholdLibConfigBeenUpdated = useRef(false)
   const { ledgerLiveAppEthereumSigner } = useLedgerLiveApp()
-  const { account, isActive } = useIsActive()
+  const { account, isActive, chainId } = useIsActive()
   const { isEmbed } = useIsEmbed()
 
   useEffect(() => {
-    if (isActive) {
+    if (isActive && chainId) {
       threshold.updateConfig({
         ethereum: {
           ...threshold.config.ethereum,
           providerOrSigner: isEmbed ? ledgerLiveAppEthereumSigner : library,
           account,
+          chainId,
+        },
+        bitcoin: {
+          ...threshold.config.bitcoin,
+          network: isTestnetNetwork(chainId)
+            ? BitcoinNetwork.Testnet
+            : BitcoinNetwork.Mainnet,
         },
-        bitcoin: threshold.config.bitcoin,
       })
       hasThresholdLibConfigBeenUpdated.current = true
     }
@@ -38,14 +44,15 @@ export const ThresholdProvider: FC = ({ children }) => {
       threshold.updateConfig({
         ethereum: {
           ...threshold.config.ethereum,
-          providerOrSigner: getDefaultThresholdLibProvider(),
+          providerOrSigner: getThresholdLibProvider(),
           account: undefined,
+          chainId: getDefaultProviderChainId(),
         },
         bitcoin: threshold.config.bitcoin,
       })
       hasThresholdLibConfigBeenUpdated.current = false
     }
-  }, [library, isActive, account, isEmbed])
+  }, [isActive, account, isEmbed, chainId, library])
 
   return (
     <ThresholdContext.Provider value={threshold}>
diff --git a/src/threshold-ts/index.ts b/src/threshold-ts/index.ts
index 09e9019c1..3a44db39c 100644
--- a/src/threshold-ts/index.ts
+++ b/src/threshold-ts/index.ts
@@ -4,13 +4,14 @@ import { IStaking, Staking } from "./staking"
 import { ITBTC, TBTC } from "./tbtc"
 import { ThresholdConfig } from "./types"
 import { IVendingMachines, VendingMachines } from "./vending-machine"
+import { isL1Network } from "../networks/utils"
 
 export class Threshold {
   config!: ThresholdConfig
-  multicall!: IMulticall
-  staking!: IStaking
-  multiAppStaking!: MultiAppStaking
-  vendingMachines!: IVendingMachines
+  multicall!: IMulticall | null
+  staking!: IStaking | null
+  multiAppStaking!: MultiAppStaking | null
+  vendingMachines!: IVendingMachines | null
   tbtc!: ITBTC
 
   constructor(config: ThresholdConfig) {
@@ -19,19 +20,27 @@ export class Threshold {
 
   private _initialize = (config: ThresholdConfig) => {
     this.config = config
-    this.multicall = new Multicall(config.ethereum)
-    this.vendingMachines = new VendingMachines(config.ethereum)
-    this.staking = new Staking(
-      config.ethereum,
-      this.multicall,
-      this.vendingMachines
-    )
-    this.multiAppStaking = new MultiAppStaking(
-      this.staking,
-      this.multicall,
-      config.ethereum
-    )
-    this.tbtc = new TBTC(config.ethereum, config.bitcoin, this.multicall)
+    const { ethereum, bitcoin } = config
+
+    if (isL1Network(ethereum.chainId)) {
+      this.multicall = new Multicall(ethereum)
+      this.vendingMachines = new VendingMachines(ethereum)
+      this.staking = new Staking(ethereum, this.multicall, this.vendingMachines)
+      this.multiAppStaking = new MultiAppStaking(
+        this.staking,
+        this.multicall,
+        ethereum
+      )
+    } else {
+      this.staking = null
+      this.multiAppStaking = null
+      this.vendingMachines = null
+      this.multicall = null
+      console.warn(
+        `Contracts like VendingMachines, Multicall and Staking are not available on chain ID ${ethereum.chainId}.`
+      )
+    }
+    this.tbtc = new TBTC(ethereum, bitcoin)
   }
 
   updateConfig = (config: ThresholdConfig) => {
diff --git a/src/threshold-ts/tbtc/index.ts b/src/threshold-ts/tbtc/index.ts
index d8c2d178f..d91f03267 100644
--- a/src/threshold-ts/tbtc/index.ts
+++ b/src/threshold-ts/tbtc/index.ts
@@ -6,6 +6,7 @@ import {
   BitcoinTxHash,
   BitcoinUtxo,
   ChainIdentifier,
+  CrossChainDepositor,
   Deposit,
   DepositRequest,
   ElectrumClient,
@@ -16,6 +17,7 @@ import {
   loadEthereumCoreContracts,
   TBTC as SDK,
   Chains,
+  L2Chain,
 } from "@keep-network/tbtc-v2.ts"
 import {
   BigNumber,
@@ -26,7 +28,7 @@ import {
   utils,
 } from "ethers"
 import { LogDescription } from "ethers/lib/utils"
-import { ContractCall, IMulticall } from "../multicall"
+import { ContractCall, IMulticall, Multicall } from "../multicall"
 import { BitcoinConfig, BitcoinNetwork, EthereumConfig } from "../types"
 import {
   AddressZero,
@@ -42,6 +44,15 @@ import {
   isValidBtcAddress,
   ZERO,
 } from "../utils"
+import {
+  isL1Network,
+  isL2Network,
+  getChainIdToNetworkName,
+  getMainnetOrTestnetChainId,
+} from "../../networks/utils"
+import { SupportedChainIds } from "../../networks/enums/networks"
+import { getDefaultProviderChainId } from "../../utils/getEnvVariable"
+import { getThresholdLibProvider } from "../../utils/getThresholdLib"
 
 export enum BridgeActivityStatus {
   PENDING = "PENDING",
@@ -156,6 +167,7 @@ export type DepositScriptParameters = {
   walletPublicKeyHash: string
   refundPublicKeyHash: string
   refundLocktime: string
+  extraData?: string
 }
 
 class EmptySdkObjectError extends Error {
@@ -184,14 +196,16 @@ export interface ITBTC {
    */
   readonly bitcoinNetwork: BitcoinNetwork
 
-  readonly bridgeContract: Contract
+  readonly bridgeContract: Contract | null
 
-  readonly vaultContract: Contract
+  readonly vaultContract: Contract | null
 
-  readonly tokenContract: Contract
+  readonly tokenContract: Contract | null
 
   readonly deposit: Deposit | undefined
 
+  readonly isCrossChain: boolean
+
   /**
    * Initializes tbtc-v2 SDK
    * @param providerOrSigner Ethers instance of Provider (if wallet is not
@@ -211,6 +225,17 @@ export interface ITBTC {
    */
   initiateDeposit(btcRecoveryAddress: string): Promise<Deposit>
 
+  /**
+   * Initiates a Deposit object from bitcoin recovery address.
+   * @param btcRecoveryAddress The bitcoin address in which the user will
+   * receive the bitcoin back in case something goes wrong.
+   * @returns Deposit object
+   */
+  initiateCrossChainDeposit(
+    btcRecoveryAddress: string,
+    chainId: number
+  ): Promise<Deposit>
+
   /**
    * Removes the deposit data assigned to `this._deposit` property.
    */
@@ -228,6 +253,19 @@ export interface ITBTC {
     depositScriptParameters: DepositScriptParameters
   ): Promise<Deposit>
 
+  /**
+   * Initiates a deposit object from DepositScriptParameters object. Most of the
+   * parameters are passed as strings and converted to hexes inside the
+   * function.
+   * @param depositScriptParameters DepositScriptParameters object that contains
+   * all the data related to the deposit we want to re-initiate.
+   * @returns Deposit object
+   */
+  initiateCrossChainDepositFromScriptParameters(
+    depositScriptParameters: DepositScriptParameters,
+    chainId: number
+  ): Promise<Deposit>
+
   /**
    * Calculates the deposit address from the deposit object stored in
    * this._deposit. Throws error if deposit object is not initiated.
@@ -416,8 +454,8 @@ export class TBTC implements ITBTC {
   private _bridgeContract: Contract
   private _tbtcVaultContract: Contract
   private _tokenContract: Contract
-  private _bitcoinClient: BitcoinClient
   private _multicall: IMulticall
+  private _bitcoinClient: BitcoinClient
   private _ethereumConfig: EthereumConfig
   private _bitcoinConfig: BitcoinConfig
   private readonly _satoshiMultiplier = BigNumber.from(10).pow(10)
@@ -443,12 +481,9 @@ export class TBTC implements ITBTC {
 
   private _sdkPromise: Promise<SDK | undefined>
   private _deposit: Deposit | undefined
+  private _isCrossChain: boolean = false
 
-  constructor(
-    ethereumConfig: EthereumConfig,
-    bitcoinConfig: BitcoinConfig,
-    multicall: IMulticall
-  ) {
+  constructor(ethereumConfig: EthereumConfig, bitcoinConfig: BitcoinConfig) {
     if (!bitcoinConfig.client && !bitcoinConfig.credentials) {
       throw new Error(
         "Neither bitcoin client nor bitcoin credentials are specified"
@@ -460,41 +495,55 @@ export class TBTC implements ITBTC {
       providerOrSigner,
       account,
     } = ethereumConfig
+    this._isCrossChain = isL2Network(chainId)
+
+    const defaultOrConnectedChainId = this._isCrossChain
+      ? getDefaultProviderChainId()
+      : chainId
+    const defaultOrConnectedProvider = this._isCrossChain
+      ? getThresholdLibProvider(defaultOrConnectedChainId)
+      : providerOrSigner
 
     const tbtcVaultArtifact = getArtifact(
       "TBTCVault",
-      chainId,
+      defaultOrConnectedChainId,
       shouldUseTestnetDevelopmentContracts
     )
     const bridgeArtifact = getArtifact(
       "Bridge",
-      chainId,
+      defaultOrConnectedChainId,
       shouldUseTestnetDevelopmentContracts
     )
     const tbtcTokenArtifact = getArtifact(
       "TBTC",
-      chainId,
+      defaultOrConnectedChainId,
       shouldUseTestnetDevelopmentContracts
     )
 
     this._bridgeContract = getContract(
       bridgeArtifact.address,
       bridgeArtifact.abi,
-      providerOrSigner,
+      defaultOrConnectedProvider,
       account
     )
     this._tbtcVaultContract = getContract(
       tbtcVaultArtifact.address,
       tbtcVaultArtifact.abi,
-      providerOrSigner,
+      defaultOrConnectedProvider,
       account
     )
     this._tokenContract = getContract(
       tbtcTokenArtifact.address,
       tbtcTokenArtifact.abi,
-      providerOrSigner,
+      defaultOrConnectedProvider,
       account
     )
+    this._multicall = new Multicall({
+      ...ethereumConfig,
+      providerOrSigner: defaultOrConnectedProvider,
+      chainId: defaultOrConnectedChainId,
+    })
+
     // @ts-ignore
     this._bitcoinClient =
       bitcoinConfig.client ??
@@ -503,7 +552,6 @@ export class TBTC implements ITBTC {
         bitcoinConfig.clientOptions
       )
 
-    this._multicall = multicall
     this._ethereumConfig = ethereumConfig
     this._bitcoinConfig = bitcoinConfig
     this._sdkPromise = new Promise((resolve) => resolve(undefined))
@@ -515,22 +563,34 @@ export class TBTC implements ITBTC {
     providerOrSigner: providers.Provider | Signer,
     account?: string
   ): Promise<SDK> {
+    const isMainnet = this.bitcoinNetwork === BitcoinNetwork.Mainnet
+    const defaultProvider = isMainnet
+      ? getThresholdLibProvider(SupportedChainIds.Ethereum)
+      : getThresholdLibProvider(SupportedChainIds.Sepolia)
+
     const signer =
       !!account && providerOrSigner instanceof Web3Provider
         ? getSigner(providerOrSigner as Web3Provider, account)
         : providerOrSigner
 
+    const connectedChainId = await chainIdFromSigner(signer)
+
+    const initializerProviderOrSigner = isL1Network(connectedChainId)
+      ? signer
+      : defaultProvider
+
     const { shouldUseTestnetDevelopmentContracts } = this._ethereumConfig
     const { client: clientFromConfig } = this._bitcoinConfig
 
     // For both of these cases we will use SDK.initializeCustom() method
     if (clientFromConfig || shouldUseTestnetDevelopmentContracts) {
       const depositorAddress = await ethereumAddressFromSigner(signer)
-      const chainId = await chainIdFromSigner(signer)
-
       const tbtcContracts = shouldUseTestnetDevelopmentContracts
         ? getSepoliaDevelopmentContracts(signer)
-        : await loadEthereumCoreContracts(signer, chainId as Chains.Ethereum)
+        : await loadEthereumCoreContracts(
+            defaultProvider,
+            SupportedChainIds.Ethereum.valueOf().toString() as Chains.Ethereum
+          )
 
       const sdk = await SDK.initializeCustom(tbtcContracts, this._bitcoinClient)
 
@@ -539,12 +599,15 @@ export class TBTC implements ITBTC {
       return sdk
     }
 
-    const initializeFunction =
-      this.bitcoinNetwork === BitcoinNetwork.Mainnet
-        ? SDK.initializeMainnet
-        : SDK.initializeSepolia
+    const initializeFunction = isMainnet
+      ? SDK.initializeMainnet
+      : SDK.initializeSepolia
 
-    const sdk = await initializeFunction(signer)
+    // We need to use a mainnet default provider to initialize the SDK
+    const sdk = await initializeFunction(
+      initializerProviderOrSigner,
+      isL2Network(connectedChainId)
+    )
 
     return sdk
   }
@@ -555,6 +618,13 @@ export class TBTC implements ITBTC {
   ): Promise<void> {
     try {
       this._sdkPromise = this._initializeSdk(providerOrSigner, account)
+
+      if (this.isCrossChain) {
+        await this._initiateCrossChain(
+          providerOrSigner as Web3Provider,
+          account as string
+        )
+      }
     } catch (err) {
       throw new Error(`Something went wrong when initializing tbtc sdk: ${err}`)
     }
@@ -584,6 +654,10 @@ export class TBTC implements ITBTC {
     return this._tokenContract
   }
 
+  get isCrossChain(): boolean {
+    return this._isCrossChain
+  }
+
   private _getSdk = async (): Promise<SDK> => {
     const sdk = await this._sdkPromise
     if (!sdk) throw new EmptySdkObjectError()
@@ -591,12 +665,42 @@ export class TBTC implements ITBTC {
     return sdk
   }
 
+  private _initiateCrossChain = async (
+    providerOrSigner: Web3Provider,
+    account: string
+  ): Promise<void> => {
+    const sdk = await this._getSdk()
+    const signer = getSigner(providerOrSigner as Web3Provider, account)
+
+    const connectedChainId = await chainIdFromSigner(signer)
+    const l2NetworkName = getChainIdToNetworkName(connectedChainId)
+
+    await sdk.initializeCrossChain(l2NetworkName as L2Chain, signer)
+  }
+
   initiateDeposit = async (btcRecoveryAddress: string): Promise<Deposit> => {
     const sdk = await this._getSdk()
     this._deposit = await sdk.deposits.initiateDeposit(btcRecoveryAddress)
     return this._deposit
   }
 
+  initiateCrossChainDeposit = async (
+    btcRecoveryAddress: string,
+    chainId: number
+  ): Promise<Deposit> => {
+    if (!this._isCrossChain) {
+      throw new Error("Unsupported chain ID")
+    }
+
+    const sdk = await this._getSdk()
+    const l2NetworkName = getChainIdToNetworkName(chainId)
+    this._deposit = await sdk.deposits.initiateCrossChainDeposit(
+      btcRecoveryAddress,
+      l2NetworkName as Exclude<keyof typeof Chains, "Ethereum">
+    )
+    return this._deposit
+  }
+
   removeDepositData = (): void => {
     this._deposit = undefined
   }
@@ -606,19 +710,19 @@ export class TBTC implements ITBTC {
   ): Promise<Deposit> => {
     const sdk = await this._getSdk()
     const {
+      depositor,
       blindingFactor,
       walletPublicKeyHash,
       refundPublicKeyHash,
       refundLocktime,
-      ...restDepositScriptParameters
     } = depositScriptParameters
 
     const depositReceipt = {
+      depositor,
       blindingFactor: Hex.from(blindingFactor),
       walletPublicKeyHash: Hex.from(walletPublicKeyHash),
       refundLocktime: Hex.from(refundLocktime),
       refundPublicKeyHash: Hex.from(refundPublicKeyHash),
-      ...restDepositScriptParameters,
     }
 
     this._deposit = await Deposit.fromReceipt(
@@ -629,6 +733,67 @@ export class TBTC implements ITBTC {
     return this._deposit
   }
 
+  initiateCrossChainDepositFromScriptParameters = async (
+    depositScriptParameters: DepositScriptParameters,
+    chainId: number
+  ): Promise<Deposit> => {
+    if (!this._isCrossChain) {
+      throw new Error("Unsupported chain ID")
+    }
+    const l2NetworkName = getChainIdToNetworkName(chainId)
+    const sdk = await this._getSdk()
+
+    const {
+      depositor,
+      blindingFactor,
+      walletPublicKeyHash,
+      refundPublicKeyHash,
+      refundLocktime,
+      extraData,
+    } = depositScriptParameters
+
+    if (!extraData) {
+      throw new Error("Extra data is required for cross-chain deposit")
+    }
+
+    const depositReceipt = {
+      depositor: {
+        identifierHex: depositor.identifierHex,
+        equals: (identifier: ChainIdentifier) => {
+          return depositor.identifierHex === identifier.identifierHex
+        },
+      },
+      blindingFactor: Hex.from(blindingFactor),
+      walletPublicKeyHash: Hex.from(walletPublicKeyHash),
+      refundLocktime: Hex.from(refundLocktime),
+      refundPublicKeyHash: Hex.from(refundPublicKeyHash),
+      extraData: Hex.from(extraData),
+    }
+
+    await this._initiateCrossChain(
+      this._ethereumConfig.providerOrSigner as Web3Provider,
+      this._ethereumConfig.account as string
+    )
+
+    const crossChainContracts = sdk.crossChainContracts(
+      l2NetworkName as Exclude<keyof typeof Chains, "Ethereum">
+    )
+
+    if (!crossChainContracts) {
+      throw new Error("Cross-chain contracts are not initialized")
+    }
+    const depositorProxy = new CrossChainDepositor(crossChainContracts)
+
+    this._deposit = await Deposit.fromReceipt(
+      depositReceipt,
+      sdk.tbtcContracts,
+      sdk.bitcoinClient,
+      depositorProxy
+    )
+
+    return this._deposit
+  }
+
   calculateDepositAddress = async (): Promise<string> => {
     if (!this._deposit) throw new EmptyDepositObjectError()
     return await this._deposit.getBitcoinAddress()
@@ -669,21 +834,21 @@ export class TBTC implements ITBTC {
   }> => {
     const calls: ContractCall[] = [
       {
-        interface: this._bridgeContract.interface,
-        address: this._bridgeContract.address,
+        interface: this._bridgeContract!.interface,
+        address: this._bridgeContract!.address,
         method: "depositParameters",
         args: [],
       },
       {
-        interface: this._tbtcVaultContract.interface,
-        address: this._tbtcVaultContract.address,
+        interface: this._tbtcVaultContract!.interface,
+        address: this._tbtcVaultContract!.address,
         method: "optimisticMintingFeeDivisor",
         args: [],
       },
     ]
 
     const [depositParams, _optimisticMintingFeeDivisor] =
-      await this._multicall.aggregate(calls)
+      await this._multicall!.aggregate(calls)
 
     const depositTreasuryFeeDivisor = BigNumber.from(
       depositParams.depositTreasuryFeeDivisor
@@ -834,12 +999,14 @@ export class TBTC implements ITBTC {
   findAllRevealedDeposits = async (
     depositor: string
   ): Promise<RevealedDepositEvent[]> => {
+    const chainId = getMainnetOrTestnetChainId(this.ethereumChainId)
+
     const bridgeArtifact = getArtifact(
       "Bridge",
-      this.ethereumChainId,
+      chainId,
       this._ethereumConfig.shouldUseTestnetDevelopmentContracts
     )
-    const deposits = await getContractPastEvents(this._bridgeContract, {
+    const deposits = await getContractPastEvents(this._bridgeContract!, {
       fromBlock: bridgeArtifact.receipt.blockNumber,
       filterParams: [null, null, depositor],
       eventName: "DepositRevealed",
@@ -874,10 +1041,10 @@ export class TBTC implements ITBTC {
     const { optimisticMintingFeeDivisor } = await this._getDepositFees()
 
     const deposits = (
-      await this._multicall.aggregate(
+      await this._multicall!.aggregate(
         depositKeys.map((depositKey) => ({
-          interface: this.bridgeContract.interface,
-          address: this.bridgeContract.address,
+          interface: this.bridgeContract!.interface,
+          address: this.bridgeContract!.address,
           method: "deposits",
           args: [depositKey],
         }))
@@ -906,16 +1073,16 @@ export class TBTC implements ITBTC {
     optimisticMintingFinalizedTxHash: string,
     depositor: string
   ): Promise<[string, BigNumber]> => {
-    const receipt = await this.tokenContract.provider.getTransactionReceipt(
+    const receipt = await this.tokenContract!.provider.getTransactionReceipt(
       optimisticMintingFinalizedTxHash
     )
 
     // There is only one transfer to depositor account.
     const transferEvent = receipt.logs
       .filter((log) =>
-        isSameETHAddress(log.address, this._tokenContract.address)
+        isSameETHAddress(log.address, this._tokenContract!.address)
       )
-      .map((log) => this._tokenContract.interface.parseLog(log))
+      .map((log) => this._tokenContract!.interface.parseLog(log))
       .filter((log) => log.name === "Transfer")
       .find((log) => isSameETHAddress(log.args.to, depositor))
 
@@ -929,12 +1096,14 @@ export class TBTC implements ITBTC {
     depositor: string,
     depositKeys: string[] = []
   ): Promise<ReturnType<typeof getContractPastEvents>> => {
+    const chainId = getMainnetOrTestnetChainId(this.ethereumChainId)
+
     const tbtcVaultArtifact = getArtifact(
       "TBTCVault",
-      this.ethereumChainId,
+      chainId,
       this._ethereumConfig.shouldUseTestnetDevelopmentContracts
     )
-    return await getContractPastEvents(this._tbtcVaultContract, {
+    return await getContractPastEvents(this._tbtcVaultContract!, {
       fromBlock: tbtcVaultArtifact.receipt.blockNumber,
       filterParams: [null, depositKeys, depositor],
       eventName: "OptimisticMintingFinalized",
@@ -944,12 +1113,14 @@ export class TBTC implements ITBTC {
   private _findAllCancelledDeposits = async (
     depositKeys: string[]
   ): Promise<ReturnType<typeof getContractPastEvents>> => {
+    const chainId = getMainnetOrTestnetChainId(this.ethereumChainId)
+
     const tbtcVaultArtifact = getArtifact(
       "TBTCVault",
-      this.ethereumChainId,
+      chainId,
       this._ethereumConfig.shouldUseTestnetDevelopmentContracts
     )
-    return getContractPastEvents(this._tbtcVaultContract, {
+    return getContractPastEvents(this._tbtcVaultContract!, {
       fromBlock: tbtcVaultArtifact.receipt.blockNumber,
       filterParams: [null, depositKeys],
       eventName: "OptimisticMintingCancelled",
@@ -967,7 +1138,7 @@ export class TBTC implements ITBTC {
 
     for (const event of requestedRedemptions) {
       const { timestamp: eventTimestamp } =
-        await this._bridgeContract.provider.getBlock(event.blockNumber)
+        await this._bridgeContract!.provider.getBlock(event.blockNumber)
       const redemptionKey = this.buildRedemptionKey(
         event.walletPublicKeyHash,
         event.redeemerOutputScript
@@ -1162,9 +1333,9 @@ export class TBTC implements ITBTC {
         : encodeAddress(redeemer ?? AddressZero),
     ]
 
-    const logs = await this.bridgeContract.queryFilter(
+    const logs = await this.bridgeContract!.queryFilter(
       {
-        address: this.bridgeContract.address,
+        address: this.bridgeContract!.address,
         // @ts-ignore
         topics: filterTopics,
       },
@@ -1174,7 +1345,7 @@ export class TBTC implements ITBTC {
 
     return logs
       .map((log) => ({
-        ...this.bridgeContract.interface.parseLog(log),
+        ...this.bridgeContract!.interface.parseLog(log),
         blockNumber: log.blockNumber,
         transactionHash: log.transactionHash,
       }))
@@ -1215,16 +1386,16 @@ export class TBTC implements ITBTC {
   getRedemptionRequest = async (
     redemptionKey: string
   ): Promise<RedemptionRequest> => {
-    const [[pending], [timedOut]] = await this._multicall.aggregate([
+    const [[pending], [timedOut]] = await this._multicall!.aggregate([
       {
-        interface: this._bridgeContract.interface,
-        address: this._bridgeContract.address,
+        interface: this._bridgeContract!.interface,
+        address: this._bridgeContract!.address,
         method: "pendingRedemptions",
         args: [redemptionKey],
       },
       {
-        interface: this._bridgeContract.interface,
-        address: this._bridgeContract.address,
+        interface: this._bridgeContract!.interface,
+        address: this._bridgeContract!.address,
         method: "timedOutRedemptions",
         args: [redemptionKey],
       },
@@ -1271,9 +1442,9 @@ export class TBTC implements ITBTC {
       this._encodeWalletPublicKeyHash(walletPublicKeyHash),
     ]
 
-    const logs = await this.bridgeContract.queryFilter(
+    const logs = await this.bridgeContract!.queryFilter(
       {
-        address: this.bridgeContract.address,
+        address: this.bridgeContract!.address,
         // @ts-ignore
         topics: filterTopics,
       },
@@ -1303,9 +1474,9 @@ export class TBTC implements ITBTC {
       this._encodeWalletPublicKeyHash(walletPublicKeyHash),
     ]
 
-    const logs = await this.bridgeContract.queryFilter(
+    const logs = await this.bridgeContract!.queryFilter(
       {
-        address: this.bridgeContract.address,
+        address: this.bridgeContract!.address,
         // @ts-ignore
         topics: filterTopics,
       },
@@ -1359,7 +1530,7 @@ export class TBTC implements ITBTC {
   private getRedemptionTreasuryFeeDivisor = async () => {
     if (!this._redemptionTreasuryFeeDivisor) {
       const { redemptionTreasuryFeeDivisor } =
-        await this.bridgeContract.redemptionParameters()
+        await this.bridgeContract!.redemptionParameters()
       this._redemptionTreasuryFeeDivisor = redemptionTreasuryFeeDivisor
     }
 

From d2293529b183f35aada4f638a4fec1b95c8ff1a6 Mon Sep 17 00:00:00 2001
From: evandrosaturnino <evandro.saturnino@gmail.com>
Date: Tue, 12 Nov 2024 10:46:49 -0300
Subject: [PATCH 12/46] Update local storage logic handling

---
 src/hooks/tbtc/useRemoveDepositData.ts        |  4 +-
 .../useTBTCDepositDataFromLocalStorage.ts     | 50 +++++++++++++------
 src/utils/tbtcLocalStorageData.ts             | 18 +++++--
 3 files changed, 53 insertions(+), 19 deletions(-)

diff --git a/src/hooks/tbtc/useRemoveDepositData.ts b/src/hooks/tbtc/useRemoveDepositData.ts
index 9c041f306..74c92270f 100644
--- a/src/hooks/tbtc/useRemoveDepositData.ts
+++ b/src/hooks/tbtc/useRemoveDepositData.ts
@@ -2,15 +2,17 @@ import { useCallback } from "react"
 import { useThreshold } from "../../contexts/ThresholdContext"
 import { useTbtcState } from "../useTbtcState"
 import { useTBTCDepositDataFromLocalStorage } from "./useTBTCDepositDataFromLocalStorage"
+import { useIsActive } from "../useIsActive"
 
 export const useRemoveDepositData = () => {
+  const { chainId } = useIsActive()
   const { resetDepositData } = useTbtcState()
   const { removeDepositDataFromLocalStorage } =
     useTBTCDepositDataFromLocalStorage()
   const threshold = useThreshold()
 
   return useCallback(() => {
-    removeDepositDataFromLocalStorage()
+    removeDepositDataFromLocalStorage(chainId)
     resetDepositData()
     threshold.tbtc.removeDepositData()
   }, [resetDepositData, removeDepositDataFromLocalStorage, threshold])
diff --git a/src/hooks/tbtc/useTBTCDepositDataFromLocalStorage.ts b/src/hooks/tbtc/useTBTCDepositDataFromLocalStorage.ts
index 25ba8ea27..008b960b4 100644
--- a/src/hooks/tbtc/useTBTCDepositDataFromLocalStorage.ts
+++ b/src/hooks/tbtc/useTBTCDepositDataFromLocalStorage.ts
@@ -1,5 +1,4 @@
-import { useCallback } from "react"
-import { useLocalStorage } from "../useLocalStorage"
+import { useState, useEffect, useCallback } from "react"
 import {
   key,
   write,
@@ -10,27 +9,50 @@ import {
 import { useIsActive } from "../useIsActive"
 
 export const useTBTCDepositDataFromLocalStorage = () => {
-  const { account } = useIsActive()
+  const { account, chainId } = useIsActive()
 
-  const [tBTCDepositData] = useLocalStorage<TBTCLocalStorageDepositData>(
-    key,
-    {}
-  )
+  const [tBTCDepositData, setTBTCLocalStorageData] =
+    useState<TBTCLocalStorageDepositData>({})
+
+  useEffect(() => {
+    const storageKey = `${key}-${chainId?.toString()}`
+    const storedData = localStorage.getItem(storageKey)
+    const parsedData = storedData ? JSON.parse(storedData) : {}
+
+    setTBTCLocalStorageData(parsedData)
+  }, [chainId])
 
   const setDepositDataInLocalStorage = useCallback(
-    (depositData: TBTCDepositData) => {
+    (depositData: TBTCDepositData, chainId?: number | string) => {
       if (!account) return
 
-      write(account, depositData, tBTCDepositData)
+      const storageKey = `${key}-${chainId?.toString()}`
+      write(account, depositData, tBTCDepositData, chainId)
+
+      const updatedData = {
+        ...tBTCDepositData,
+        [account]: depositData,
+      }
+      localStorage.setItem(storageKey, JSON.stringify(updatedData))
+      setTBTCLocalStorageData(updatedData)
     },
-    [account, JSON.stringify(tBTCDepositData)]
+    [account, tBTCDepositData, chainId]
   )
 
-  const removeDepositDataFromLocalStorage = useCallback(() => {
-    if (!account) return
+  const removeDepositDataFromLocalStorage = useCallback(
+    (chainId?: number | string) => {
+      if (!account) return
+
+      const storageKey = `${key}-${chainId?.toString()}`
+      removeDataForAccount(account, tBTCDepositData, chainId)
 
-    removeDataForAccount(account, tBTCDepositData)
-  }, [account, JSON.stringify(tBTCDepositData)])
+      const updatedData = { ...tBTCDepositData }
+      delete updatedData[account]
+      localStorage.setItem(storageKey, JSON.stringify(updatedData))
+      setTBTCLocalStorageData(updatedData)
+    },
+    [account, tBTCDepositData, chainId]
+  )
 
   return {
     tBTCDepositData,
diff --git a/src/utils/tbtcLocalStorageData.ts b/src/utils/tbtcLocalStorageData.ts
index b3742ff14..c9ea5d60a 100644
--- a/src/utils/tbtcLocalStorageData.ts
+++ b/src/utils/tbtcLocalStorageData.ts
@@ -1,12 +1,14 @@
 import { writeStorage } from "@rehooks/local-storage"
 
 export type TBTCDepositData = {
+  chainName: string
   ethAddress: string
   blindingFactor: string
   btcRecoveryAddress: string
   walletPublicKeyHash: string
   refundLocktime: string
   btcDepositAddress: string
+  extraData?: string
 }
 
 export type TBTCLocalStorageDepositData = {
@@ -18,7 +20,8 @@ export const key = "tBTCDepositData"
 export function write(
   account: string,
   newDepositData: TBTCDepositData,
-  prevData: TBTCLocalStorageDepositData
+  prevData: TBTCLocalStorageDepositData,
+  chainId?: number | string
 ) {
   if (!account) return
 
@@ -27,17 +30,24 @@ export function write(
     [account]: newDepositData,
   }
 
-  writeStorage<TBTCLocalStorageDepositData>(key, newLocalStorageData)
+  writeStorage<TBTCLocalStorageDepositData>(
+    `${key}-${chainId?.toString()}`,
+    newLocalStorageData
+  )
 }
 
 export function removeDataForAccount(
   account: string,
-  prevData: TBTCLocalStorageDepositData
+  prevData: TBTCLocalStorageDepositData,
+  chainId?: number | string
 ) {
   const newLocalStorageData = {
     ...prevData,
   }
   delete newLocalStorageData[`${account}`]
 
-  writeStorage<TBTCLocalStorageDepositData>(key, newLocalStorageData)
+  writeStorage<TBTCLocalStorageDepositData>(
+    `${key}-${chainId?.toString()}`,
+    newLocalStorageData
+  )
 }

From d6e5a0c72e0547324d2404cf266131ea50970def Mon Sep 17 00:00:00 2001
From: evandrosaturnino <evandro.saturnino@gmail.com>
Date: Tue, 12 Nov 2024 10:47:13 -0300
Subject: [PATCH 13/46] Update minting flow to accommodate multiple networks

---
 .../MintDurationTiers/MintDurationTiers.tsx   |   6 +-
 src/components/SubmitTxButton.tsx             |  12 +-
 src/components/Toast/Toast.tsx                |   3 +
 .../tbtc/useCheckDepositExpirationTime.ts     |  39 ++++
 src/hooks/tbtc/useDepositTelemetry.ts         |   2 +
 src/hooks/useTbtcState.ts                     |   2 +
 src/pages/tBTC/Bridge/Mint.tsx                |  80 +++++---
 src/pages/tBTC/Bridge/MintUnmintNav.tsx       |  24 ++-
 .../tBTC/Bridge/Minting/InitiateMinting.tsx   |   2 +
 src/pages/tBTC/Bridge/Minting/MakeDeposit.tsx |  12 ++
 .../tBTC/Bridge/Minting/MintingFlowRouter.tsx |  12 +-
 src/pages/tBTC/Bridge/Minting/ProvideData.tsx |  83 ++++++--
 src/pages/tBTC/Bridge/ResumeDeposit.tsx       | 183 ++++++++++++------
 src/store/tbtc/effects.ts                     |  45 +++--
 src/store/tbtc/tbtcSlice.ts                   |   1 +
 src/types/tbtc.ts                             |   3 +
 16 files changed, 377 insertions(+), 132 deletions(-)
 create mode 100644 src/hooks/tbtc/useCheckDepositExpirationTime.ts

diff --git a/src/components/MintDurationTiers/MintDurationTiers.tsx b/src/components/MintDurationTiers/MintDurationTiers.tsx
index 7fdbb671a..c7a36f534 100644
--- a/src/components/MintDurationTiers/MintDurationTiers.tsx
+++ b/src/components/MintDurationTiers/MintDurationTiers.tsx
@@ -55,9 +55,9 @@ const MintDurationTiers: FC<MintDurationTiersProps> = ({
         // is returned as is.
         const confirmations = getNumberOfConfirmationsByAmount(safeAmount)
         const durationInMinutes =
-          getDurationByNumberOfConfirmations(confirmations)
-        // Round up the minutes to the nearest half-hour
-        const hours = (Math.round(durationInMinutes / 30) * 30) / 60
+          getDurationByNumberOfConfirmations(confirmations) * 1.5
+        // Round down the minutes to the nearest half-hour
+        const hours = (Math.floor(durationInMinutes / 30) * 30) / 60
         const formattedAmount = amount.toFixed(2)
 
         const hoursSuffix = hours === 1 ? "hour" : "hours"
diff --git a/src/components/SubmitTxButton.tsx b/src/components/SubmitTxButton.tsx
index 8fbfe60eb..ded3ac841 100644
--- a/src/components/SubmitTxButton.tsx
+++ b/src/components/SubmitTxButton.tsx
@@ -4,12 +4,16 @@ import { useIsActive } from "../hooks/useIsActive"
 import { useConnectWallet } from "../hooks/useConnectWallet"
 import { RootState } from "../store"
 import { useSelector } from "react-redux"
+import { isL2Network, isValidL2Transaction } from "../networks/utils/"
+import { AllowedL2TransactionTypes } from "../networks/enums/networks"
 
 interface SubmitTxButtonProps extends ButtonProps {
+  l2TransactionType?: AllowedL2TransactionTypes
   onSubmit?: () => void
 }
 
 const SubmitTxButton: FC<SubmitTxButtonProps> = ({
+  l2TransactionType,
   onSubmit,
   isLoading,
   isDisabled,
@@ -21,8 +25,12 @@ const SubmitTxButton: FC<SubmitTxButtonProps> = ({
     trm: { isFetching },
   } = useSelector((state: RootState) => state.account)
 
-  const { isActive } = useIsActive()
+  const { isActive, chainId } = useIsActive()
   const connectWallet = useConnectWallet()
+  const isButtonDisabled =
+    isBlocked ||
+    isDisabled ||
+    (isL2Network(chainId) && !isValidL2Transaction(l2TransactionType))
 
   const onConnectWalletClick = () => {
     connectWallet()
@@ -32,7 +40,7 @@ const SubmitTxButton: FC<SubmitTxButtonProps> = ({
     return (
       <Button
         isLoading={isFetching || isLoading}
-        isDisabled={isBlocked || isDisabled}
+        isDisabled={isButtonDisabled}
         onClick={onSubmit}
         {...buttonProps}
       >
diff --git a/src/components/Toast/Toast.tsx b/src/components/Toast/Toast.tsx
index 2ebd9d45e..c06f46541 100644
--- a/src/components/Toast/Toast.tsx
+++ b/src/components/Toast/Toast.tsx
@@ -7,6 +7,7 @@ import {
   AlertDescription,
   AlertProps as AlertPropsBase,
   CloseButton,
+  useColorModeValue,
 } from "@threshold-network/components"
 import { useEffect, useState } from "react"
 import { setTimeout, clearTimeout } from "../../utils/setTimeout"
@@ -34,6 +35,7 @@ const Toast = (props: AlertProps) => {
   } = props
 
   const [isMounted, setIsMounted] = useState(true)
+  const backgroundColor = useColorModeValue("white", "gray.600")
 
   useEffect(() => {
     const timeout = setTimeout(() => {
@@ -54,6 +56,7 @@ const Toast = (props: AlertProps) => {
       alignItems="baseline"
       border="none"
       whiteSpace="nowrap"
+      backgroundColor={backgroundColor}
       {...restProps}
     >
       <AlertIcon minH="8" />
diff --git a/src/hooks/tbtc/useCheckDepositExpirationTime.ts b/src/hooks/tbtc/useCheckDepositExpirationTime.ts
new file mode 100644
index 000000000..fd8acd6f8
--- /dev/null
+++ b/src/hooks/tbtc/useCheckDepositExpirationTime.ts
@@ -0,0 +1,39 @@
+import { Hex } from "@keep-network/tbtc-v2.ts"
+import { useCallback } from "react"
+import { useThreshold } from "../../contexts/ThresholdContext"
+
+export const useCheckDepositExpirationTime = () => {
+  const threshold = useThreshold()
+
+  return useCallback(
+    async (refundLocktime: string) => {
+      try {
+        const refundLockTimestamp = parseInt(
+          Hex.from(refundLocktime).reverse().toString(),
+          16
+        )
+
+        const { depositRevealAheadPeriod } =
+          (await threshold.tbtc.bridgeContract?.depositParameters()) ?? {}
+
+        if (!depositRevealAheadPeriod) {
+          throw new Error("Failed to retrieve deposit reveal ahead period.")
+        }
+
+        const currentTimestampInSeconds = Math.floor(Date.now() / 1000)
+        const expirationTimestamp =
+          currentTimestampInSeconds + depositRevealAheadPeriod
+
+        return {
+          expirationTimestamp,
+          refundLockTimestamp,
+          isExpired: currentTimestampInSeconds >= expirationTimestamp,
+        }
+      } catch (error) {
+        console.error("Error checking deposit expiration time:", error)
+        throw error
+      }
+    },
+    [threshold]
+  )
+}
diff --git a/src/hooks/tbtc/useDepositTelemetry.ts b/src/hooks/tbtc/useDepositTelemetry.ts
index 755af9572..c4734ea85 100644
--- a/src/hooks/tbtc/useDepositTelemetry.ts
+++ b/src/hooks/tbtc/useDepositTelemetry.ts
@@ -21,6 +21,7 @@ export const useDepositTelemetry = (network: BitcoinNetwork) => {
         walletPublicKeyHash,
         refundPublicKeyHash,
         refundLocktime,
+        extraData,
       } = deposit
 
       captureMessage(
@@ -31,6 +32,7 @@ export const useDepositTelemetry = (network: BitcoinNetwork) => {
           walletPublicKeyHash: walletPublicKeyHash.toString(),
           refundPublicKeyHash: refundPublicKeyHash.toString(),
           refundLocktime: refundLocktime.toString(),
+          extraData: extraData?.toString(),
           verificationStatus: status,
           verificationResponse: response,
         },
diff --git a/src/hooks/useTbtcState.ts b/src/hooks/useTbtcState.ts
index c3d018a21..2e9711136 100644
--- a/src/hooks/useTbtcState.ts
+++ b/src/hooks/useTbtcState.ts
@@ -30,6 +30,8 @@ export const useTbtcState: UseTbtcState = () => {
     updateState("depositRevealedTxHash", undefined)
     updateState("optimisticMintingRequestedTxHash", undefined)
     updateState("optimisticMintingFinalizedTxHash", undefined)
+    updateState("extraData", undefined)
+    updateState("chainName", undefined)
   }, [updateState])
 
   return {
diff --git a/src/pages/tBTC/Bridge/Mint.tsx b/src/pages/tBTC/Bridge/Mint.tsx
index 97c29e2cd..5c20969d4 100644
--- a/src/pages/tBTC/Bridge/Mint.tsx
+++ b/src/pages/tBTC/Bridge/Mint.tsx
@@ -18,6 +18,8 @@ import {
 import { BridgeProcessEmptyState } from "./components/BridgeProcessEmptyState"
 import { MintDurationWidget } from "../../../components/MintDurationWidget"
 import { useThreshold } from "../../../contexts/ThresholdContext"
+import { useCheckDepositExpirationTime } from "../../../hooks/tbtc/useCheckDepositExpirationTime"
+import { useRemoveDepositData } from "../../../hooks/tbtc/useRemoveDepositData"
 
 export const MintPage: PageComponent = ({}) => {
   return <Outlet />
@@ -25,40 +27,60 @@ export const MintPage: PageComponent = ({}) => {
 
 export const MintingFormPage: PageComponent = ({ ...props }) => {
   const { tBTCDepositData } = useTBTCDepositDataFromLocalStorage()
-  const { btcDepositAddress, updateState } = useTbtcState()
-  const { account } = useIsActive()
+  const { btcDepositAddress, updateState, resetDepositData } = useTbtcState()
+  const { account, chainId } = useIsActive()
+  const checkDepositExpiration = useCheckDepositExpirationTime()
+  const removeDepositData = useRemoveDepositData()
 
   useEffect(() => {
+    const updateDepositData = async () => {
+      if (
+        tBTCDepositData &&
+        account &&
+        chainId &&
+        tBTCDepositData[account] &&
+        isSameETHAddress(tBTCDepositData[account].ethAddress, account) &&
+        tBTCDepositData[account].btcDepositAddress !== btcDepositAddress
+      ) {
+        const {
+          btcDepositAddress,
+          ethAddress,
+          blindingFactor,
+          btcRecoveryAddress,
+          walletPublicKeyHash,
+          refundLocktime,
+          extraData,
+          chainName,
+        } = tBTCDepositData[account]
+        const { isExpired } = await checkDepositExpiration(refundLocktime)
+        if (isExpired) {
+          resetDepositData()
+          removeDepositData()
+          return
+        }
+
+        updateState("ethAddress", ethAddress)
+        updateState("blindingFactor", blindingFactor)
+        updateState("btcRecoveryAddress", btcRecoveryAddress)
+        updateState("walletPublicKeyHash", walletPublicKeyHash)
+        updateState("refundLocktime", refundLocktime)
+        updateState("extraData", extraData)
+        updateState("chainName", chainName)
+        // We reset the minting step to undefined to show skeleton and the
+        // useEffect in MintingFlowRouter will update and set the proper minting
+        // step when it recognizes the "btcDepositAddress" change.
+        updateState("mintingStep", undefined)
+        updateState("btcDepositAddress", btcDepositAddress)
+      } else {
+        resetDepositData()
+      }
+    }
+
     // Update the store with the deposit data if the account is placed in tbtc
     // local storage.
-    if (
-      tBTCDepositData &&
-      account &&
-      tBTCDepositData[account] &&
-      isSameETHAddress(tBTCDepositData[account].ethAddress, account) &&
-      tBTCDepositData[account].btcDepositAddress !== btcDepositAddress
-    ) {
-      const {
-        btcDepositAddress,
-        ethAddress,
-        blindingFactor,
-        btcRecoveryAddress,
-        walletPublicKeyHash,
-        refundLocktime,
-      } = tBTCDepositData[account]
 
-      updateState("ethAddress", ethAddress)
-      updateState("blindingFactor", blindingFactor)
-      updateState("btcRecoveryAddress", btcRecoveryAddress)
-      updateState("walletPublicKeyHash", walletPublicKeyHash)
-      updateState("refundLocktime", refundLocktime)
-      // We reset the minting step to undefined to show skeleton and the
-      // useEffect in MintingFlowRouter will update and set the proper minting
-      // step when it recognizes the "btcDepositAddress" change.
-      updateState("mintingStep", undefined)
-      updateState("btcDepositAddress", btcDepositAddress)
-    }
-  }, [account])
+    updateDepositData()
+  }, [account, tBTCDepositData])
 
   return <MintingFlowRouter />
 }
diff --git a/src/pages/tBTC/Bridge/MintUnmintNav.tsx b/src/pages/tBTC/Bridge/MintUnmintNav.tsx
index e8d365c69..ef2835aa7 100644
--- a/src/pages/tBTC/Bridge/MintUnmintNav.tsx
+++ b/src/pages/tBTC/Bridge/MintUnmintNav.tsx
@@ -8,8 +8,15 @@ import {
 import { Box, Card, FilterTabs, FilterTab } from "@threshold-network/components"
 import Link from "../../../components/Link"
 import { PageComponent } from "../../../types"
+import { isL2Network } from "../../../networks/utils"
+import { isValidL2Transaction } from "../../../networks/utils/validateL2TransactionType"
+import { useIsActive } from "../../../hooks/useIsActive"
 
-const renderNavItem = (page: PageComponent, index: number) => (
+const renderNavItem = (
+  page: PageComponent,
+  index: number,
+  chainId?: number | string
+) => (
   <FilterTab
     key={page.route.path}
     as={Link}
@@ -25,6 +32,7 @@ const renderNavItem = (page: PageComponent, index: number) => (
 export const MintUnmintNav: FC<
   ComponentProps<typeof Card> & { pages: PageComponent[] }
 > = ({ pages, ...props }) => {
+  const { chainId } = useIsActive()
   const resolved = useResolvedPath("")
   const location = useLocation()
 
@@ -41,7 +49,19 @@ export const MintUnmintNav: FC<
   return (
     <Box as="nav" {...props}>
       <FilterTabs selectedTabId={activeTabId}>
-        {pages.filter((page) => !!page.route.title).map(renderNavItem)}
+        {isL2Network(chainId)
+          ? pages
+              .filter(
+                (page) =>
+                  !!page.route.title &&
+                  isValidL2Transaction(page.route.title?.toUpperCase())
+              )
+              .map((filteredPage, index) =>
+                renderNavItem(filteredPage, index, chainId)
+              )
+          : pages
+              .filter((page) => !!page.route.title)
+              .map((filteredPage, index) => renderNavItem(filteredPage, index))}
       </FilterTabs>
     </Box>
   )
diff --git a/src/pages/tBTC/Bridge/Minting/InitiateMinting.tsx b/src/pages/tBTC/Bridge/Minting/InitiateMinting.tsx
index 0939b6d23..6d8b13753 100644
--- a/src/pages/tBTC/Bridge/Minting/InitiateMinting.tsx
+++ b/src/pages/tBTC/Bridge/Minting/InitiateMinting.tsx
@@ -16,6 +16,7 @@ import { Toast } from "../../../../components/Toast"
 import { useModal } from "../../../../hooks/useModal"
 import { PosthogButtonId } from "../../../../types/posthog"
 import SubmitTxButton from "../../../../components/SubmitTxButton"
+import { AllowedL2TransactionTypes } from "../../../../networks/enums/networks"
 
 const InitiateMintingComponent: FC<{
   utxo: BitcoinUtxo
@@ -97,6 +98,7 @@ const InitiateMintingComponent: FC<{
       </InfoBox>
       <MintingTransactionDetails />
       <SubmitTxButton
+        l2TransactionType={AllowedL2TransactionTypes.mint}
         onSubmit={initiateMintTransaction}
         isFullWidth
         data-ph-capture-attribute-button-name={
diff --git a/src/pages/tBTC/Bridge/Minting/MakeDeposit.tsx b/src/pages/tBTC/Bridge/Minting/MakeDeposit.tsx
index 7e40cada0..4d405a05f 100644
--- a/src/pages/tBTC/Bridge/Minting/MakeDeposit.tsx
+++ b/src/pages/tBTC/Bridge/Minting/MakeDeposit.tsx
@@ -1,6 +1,9 @@
 import {
+  Alert,
+  AlertIcon,
   Badge,
   BodyMd,
+  BodySm,
   Box,
   BoxLabel,
   Button,
@@ -74,6 +77,8 @@ const BTCAddressSection: FC<{ btcDepositAddress: string }> = ({
       <Toast
         title="The system is continuously checking for new BTC deposits"
         status="info"
+        top={3}
+        zIndex={1}
       />
       <HStack
         alignItems="center"
@@ -186,6 +191,13 @@ const MakeDepositComponent: FC<{
         generate a new address.
       </BodyMd>
       <BTCAddressSection btcDepositAddress={btcDepositAddress} />
+      <Alert status="info" mt={6}>
+        <AlertIcon />
+        <BodySm>
+          Please ensure your deposit is at least 0.01 BTC to proceed with
+          minting tBTC.
+        </BodySm>
+      </Alert>
       <MintDurationTiers
         mt="6"
         items={[
diff --git a/src/pages/tBTC/Bridge/Minting/MintingFlowRouter.tsx b/src/pages/tBTC/Bridge/Minting/MintingFlowRouter.tsx
index 6c7e0e9cc..c944c4a77 100644
--- a/src/pages/tBTC/Bridge/Minting/MintingFlowRouter.tsx
+++ b/src/pages/tBTC/Bridge/Minting/MintingFlowRouter.tsx
@@ -17,7 +17,7 @@ import { tbtcSlice } from "../../../../store/tbtc"
 
 const MintingFlowRouterBase = () => {
   const dispatch = useAppDispatch()
-  const { account } = useIsActive()
+  const { account, chainId } = useIsActive()
   const { mintingStep, updateState, btcDepositAddress, utxo } = useTbtcState()
   const removeDepositData = useRemoveDepositData()
   const { openModal } = useModal()
@@ -36,13 +36,17 @@ const MintingFlowRouterBase = () => {
   }
 
   useEffect(() => {
-    if (!btcDepositAddress || !account) {
+    if (!btcDepositAddress || !account || !chainId) {
       return
     }
     dispatch(
-      tbtcSlice.actions.findUtxo({ btcDepositAddress, depositor: account })
+      tbtcSlice.actions.findUtxo({
+        btcDepositAddress,
+        depositor: account,
+        chainId,
+      })
     )
-  }, [btcDepositAddress, account, dispatch])
+  }, [btcDepositAddress, account, chainId, dispatch])
 
   switch (mintingStep) {
     case MintingStep.ProvideData: {
diff --git a/src/pages/tBTC/Bridge/Minting/ProvideData.tsx b/src/pages/tBTC/Bridge/Minting/ProvideData.tsx
index a52ca4ea4..906d49e08 100644
--- a/src/pages/tBTC/Bridge/Minting/ProvideData.tsx
+++ b/src/pages/tBTC/Bridge/Minting/ProvideData.tsx
@@ -1,6 +1,5 @@
 import {
   BodyMd,
-  Button,
   Checkbox,
   useColorModeValue,
 } from "@threshold-network/components"
@@ -19,7 +18,16 @@ import {
   validateBTCAddress,
   validateETHAddress,
 } from "../../../../utils/forms"
-import { supportedChainId } from "../../../../utils/getEnvVariable"
+import {
+  AllowedL2TransactionTypes,
+  SupportedChainIds,
+} from "../../../../networks/enums/networks"
+import {
+  getChainIdToNetworkName,
+  isL1Network,
+  isSupportedNetwork,
+  isTestnetNetwork,
+} from "../../../../networks/utils"
 import { getBridgeBTCSupportedAddressPrefixesText } from "../../../../utils/tBTC"
 import { downloadFile, isSameETHAddress } from "../../../../web3/utils"
 import { BridgeProcessCardSubTitle } from "../components/BridgeProcessCardSubTitle"
@@ -27,6 +35,7 @@ import { BridgeProcessCardTitle } from "../components/BridgeProcessCardTitle"
 import { useIsActive } from "../../../../hooks/useIsActive"
 import { PosthogButtonId } from "../../../../types/posthog"
 import SubmitTxButton from "../../../../components/SubmitTxButton"
+import { Deposit } from "@keep-network/tbtc-v2.ts"
 
 export interface FormValues {
   ethAddress: string
@@ -38,11 +47,6 @@ type ComponentProps = {
   formId: string
 }
 
-const resolvedBTCAddressPrefix = getBridgeBTCSupportedAddressPrefixesText(
-  "mint",
-  supportedChainId === "1" ? BitcoinNetwork.Mainnet : BitcoinNetwork.Testnet
-)
-
 /**
  * Renders the form for the minting process.
  * @param {string} formId - The ID of the form.
@@ -51,6 +55,14 @@ const resolvedBTCAddressPrefix = getBridgeBTCSupportedAddressPrefixesText(
 const MintingProcessFormBase: FC<ComponentProps & FormikProps<FormValues>> = ({
   formId,
 }) => {
+  const { chainId } = useIsActive()
+  const resolvedBTCAddressPrefix = getBridgeBTCSupportedAddressPrefixesText(
+    "mint",
+    isTestnetNetwork(chainId as number)
+      ? BitcoinNetwork.Testnet
+      : BitcoinNetwork.Mainnet
+  )
+
   return (
     <Form id={formId}>
       <FormikInput
@@ -113,7 +125,7 @@ export const ProvideDataComponent: FC<{
   const [isSubmitButtonLoading, setSubmitButtonLoading] = useState(false)
   const formRef = useRef<FormikProps<FormValues>>(null)
   const threshold = useThreshold()
-  const { account } = useIsActive()
+  const { account, chainId } = useIsActive()
   const { setDepositDataInLocalStorage } = useTBTCDepositDataFromLocalStorage()
   const depositTelemetry = useDepositTelemetry(threshold.tbtc.bitcoinNetwork)
 
@@ -137,10 +149,28 @@ export const ProvideDataComponent: FC<{
           "The account used to generate the deposit address must be the same as the connected wallet."
         )
       }
+
+      if (!isSupportedNetwork(chainId)) {
+        throw new Error(
+          "Your wallet is on an unsupported network. Switch to a supported network"
+        )
+      }
+
+      const chainName = getChainIdToNetworkName(chainId)
+
       setSubmitButtonLoading(true)
-      const deposit = await threshold.tbtc.initiateDeposit(
-        values.btcRecoveryAddress
-      )
+
+      let deposit: Deposit
+      if (isL1Network(chainId)) {
+        deposit = await threshold.tbtc.initiateDeposit(
+          values.btcRecoveryAddress
+        )
+      } else {
+        deposit = await threshold.tbtc.initiateCrossChainDeposit(
+          values.btcRecoveryAddress,
+          chainId as SupportedChainIds
+        )
+      }
       const depositAddress = await threshold.tbtc.calculateDepositAddress()
       const receipt = deposit.getReceipt()
 
@@ -150,18 +180,25 @@ export const ProvideDataComponent: FC<{
       updateState("btcRecoveryAddress", values.btcRecoveryAddress)
       updateState("walletPublicKeyHash", receipt.walletPublicKeyHash.toString())
       updateState("refundLocktime", receipt.refundLocktime.toString())
+      updateState("extraData", receipt.extraData?.toString())
+      updateState("chainName", chainName)
 
       // create a new deposit address,
       updateState("btcDepositAddress", depositAddress)
 
-      setDepositDataInLocalStorage({
-        ethAddress: values.ethAddress,
-        blindingFactor: receipt.blindingFactor.toString(),
-        btcRecoveryAddress: values.btcRecoveryAddress,
-        walletPublicKeyHash: receipt.walletPublicKeyHash.toString(),
-        refundLocktime: receipt.refundLocktime.toString(),
-        btcDepositAddress: depositAddress,
-      })
+      setDepositDataInLocalStorage(
+        {
+          chainName: chainName,
+          ethAddress: values.ethAddress,
+          blindingFactor: receipt.blindingFactor.toString(),
+          btcRecoveryAddress: values.btcRecoveryAddress,
+          walletPublicKeyHash: receipt.walletPublicKeyHash.toString(),
+          refundLocktime: receipt.refundLocktime.toString(),
+          btcDepositAddress: depositAddress,
+          extraData: receipt.extraData?.toString() || "",
+        },
+        chainId
+      )
 
       depositTelemetry(receipt, depositAddress)
 
@@ -175,18 +212,23 @@ export const ProvideDataComponent: FC<{
           depositor: {
             identifierHex: receipt.depositor.identifierHex.toString(),
           },
+          networkInfo: {
+            chainName: chainName,
+            chainId: chainId!.toString(),
+          },
           refundLocktime: receipt.refundLocktime.toString(),
           refundPublicKeyHash: receipt.refundPublicKeyHash.toString(),
           blindingFactor: receipt.blindingFactor.toString(),
           ethAddress: values.ethAddress,
           walletPublicKeyHash: receipt.walletPublicKeyHash.toString(),
           btcRecoveryAddress: values.btcRecoveryAddress,
+          extraData: receipt.extraData?.toString() ?? "",
         }
         downloadFile(JSON.stringify(finalData), fileName, "text/json")
       }
       updateState("mintingStep", MintingStep.Deposit)
     },
-    [shouldDownloadDepositReceipt]
+    [shouldDownloadDepositReceipt, chainId]
   )
 
   return (
@@ -219,6 +261,7 @@ export const ProvideDataComponent: FC<{
       {/* Although the following button doesn't trigger an on-chain transaction, the 
       SubmitTxButton is used here for its built-in TRM Wallet screening validation logic. */}
       <SubmitTxButton
+        l2TransactionType={AllowedL2TransactionTypes.mint}
         isLoading={isSubmitButtonLoading}
         loadingText={
           isSubmitButtonLoading ? "Generating deposit address..." : undefined
diff --git a/src/pages/tBTC/Bridge/ResumeDeposit.tsx b/src/pages/tBTC/Bridge/ResumeDeposit.tsx
index 07bf0ca44..ba279911b 100644
--- a/src/pages/tBTC/Bridge/ResumeDeposit.tsx
+++ b/src/pages/tBTC/Bridge/ResumeDeposit.tsx
@@ -1,9 +1,8 @@
-import { FC, useEffect } from "react"
+import { FC } from "react"
 import {
   BodyLg,
   BodyMd,
   Box,
-  Button,
   Card,
   FileUploader,
   FormControl,
@@ -14,7 +13,6 @@ import { PageComponent } from "../../../types"
 import { BridgeProcessCardTitle } from "./components/BridgeProcessCardTitle"
 import { BridgeContractLink } from "../../../components/tBTC"
 import { useTbtcState } from "../../../hooks/useTbtcState"
-import { MintingStep } from "../../../types/tbtc"
 import { Form } from "../../../components/Forms"
 import {
   isSameETHAddress,
@@ -22,7 +20,7 @@ import {
   parseJSONFile,
   InvalidJSONFileError,
 } from "../../../web3/utils"
-import { getErrorsObj } from "../../../utils/forms"
+import { getErrorsObj, validateBTCAddress } from "../../../utils/forms"
 import { useTBTCDepositDataFromLocalStorage } from "../../../hooks/tbtc"
 import { useThreshold } from "../../../contexts/ThresholdContext"
 import HelperErrorText from "../../../components/Forms/HelperErrorText"
@@ -30,68 +28,108 @@ import { DepositScriptParameters } from "../../../threshold-ts/tbtc"
 import { BridgeProcessEmptyState } from "./components/BridgeProcessEmptyState"
 
 type RecoveryJsonFileData = DepositScriptParameters & {
+  networkInfo: {
+    chainId: string
+    chainName: string
+  }
   btcRecoveryAddress: string
 }
 import { useIsActive } from "../../../hooks/useIsActive"
 import SubmitTxButton from "../../../components/SubmitTxButton"
+import { useCheckDepositExpirationTime } from "../../../hooks/tbtc/useCheckDepositExpirationTime"
+import { BitcoinNetwork } from "@keep-network/tbtc-v2.ts"
+import {
+  AllowedL2TransactionTypes,
+  SupportedChainIds,
+} from "../../../networks/enums/networks"
+import {
+  isL1Network,
+  isL2Network,
+  isSameChainId,
+  isSupportedNetwork,
+} from "../../../networks/utils"
 
 export const ResumeDepositPage: PageComponent = () => {
   const { updateState } = useTbtcState()
-  const { account, isActive } = useIsActive()
+  const { account, chainId, isActive } = useIsActive()
   const navigate = useNavigate()
   const { setDepositDataInLocalStorage } = useTBTCDepositDataFromLocalStorage()
+  const checkDepositExpiration = useCheckDepositExpirationTime()
   const threshold = useThreshold()
 
+  if (!isActive || !isSupportedNetwork(chainId)) {
+    return (
+      <Card position="relative" maxW="640px" m={"0 auto"}>
+        <BridgeProcessEmptyState title="Want to resume deposit?" />
+      </Card>
+    )
+  }
+
   const navigateToMintPage = () => {
     navigate("/tBTC/mint")
   }
 
   const onSubmit = async (values: FormValues) => {
     if (!values.depositParameters) return
-
     const { depositParameters } = values
-    await threshold.tbtc.initiateDepositFromDepositScriptParameters(
-      depositParameters
-    )
-    const btcDepositAddress = await threshold.tbtc.calculateDepositAddress()
-
-    updateState("mintingStep", undefined)
 
-    setDepositDataInLocalStorage({
-      ethAddress: depositParameters?.depositor.identifierHex!,
-      blindingFactor: depositParameters?.blindingFactor!,
-      btcRecoveryAddress: depositParameters?.btcRecoveryAddress!,
-      walletPublicKeyHash: depositParameters?.walletPublicKeyHash!,
-      refundLocktime: depositParameters?.refundLocktime!,
-      btcDepositAddress,
-    })
-
-    navigateToMintPage()
+    try {
+      if (isL1Network(chainId)) {
+        await threshold.tbtc.initiateDepositFromDepositScriptParameters(
+          depositParameters
+        )
+      } else {
+        await threshold.tbtc.initiateCrossChainDepositFromScriptParameters(
+          depositParameters,
+          chainId!
+        )
+      }
+      const btcDepositAddress = await threshold.tbtc.calculateDepositAddress()
+      updateState("mintingStep", undefined)
+      setDepositDataInLocalStorage(
+        {
+          chainName: depositParameters.networkInfo.chainName,
+          ethAddress: depositParameters.depositor.identifierHex,
+          blindingFactor: depositParameters.blindingFactor,
+          btcRecoveryAddress: depositParameters.btcRecoveryAddress,
+          walletPublicKeyHash: depositParameters.walletPublicKeyHash,
+          refundLocktime: depositParameters.refundLocktime,
+          extraData: depositParameters.extraData || "",
+          btcDepositAddress,
+        },
+        chainId
+      )
+      navigateToMintPage()
+    } catch (error) {
+      console.error("Error during deposit initiation:", error)
+    }
   }
 
   return (
-    <Card maxW="640px" m={"0 auto"}>
-      {isActive ? (
-        <>
-          <BridgeProcessCardTitle />
-          <BodyLg>
-            <Box as="span" fontWeight="600" color="brand.500">
-              Resume Minting
-            </Box>{" "}
-            - Upload .JSON file
-          </BodyLg>
-          <BodyMd mt="3" mb="6">
-            To resume your minting you need to upload your .JSON file and sign
-            the Minting Initiation transaction triggered in the dApp.
-          </BodyMd>
-          <ResumeDepositFormik address={account!} onSubmitForm={onSubmit} />
-          <Box as="p" textAlign="center" mt="10">
-            <BridgeContractLink />
-          </Box>
-        </>
-      ) : (
-        <BridgeProcessEmptyState title="Want to resume deposit?" />
-      )}
+    <Card position="relative" maxW="640px" m={"0 auto"}>
+      <>
+        <BridgeProcessCardTitle />
+        <BodyLg>
+          <Box as="span" fontWeight="600" color="brand.500">
+            Resume Minting
+          </Box>{" "}
+          - Upload .JSON file
+        </BodyLg>
+        <BodyMd mt="3" mb="6">
+          To resume your minting you need to upload your .JSON file and sign the
+          Minting Initiation transaction triggered in the dApp.
+        </BodyMd>
+        <ResumeDepositFormik
+          address={account!}
+          chainId={chainId!}
+          onSubmitForm={onSubmit}
+          checkDepositExpiration={checkDepositExpiration}
+          bitcoinNetwork={threshold.tbtc.bitcoinNetwork}
+        />
+        <Box as="p" textAlign="center" mt="10">
+          <BridgeContractLink />
+        </Box>
+      </>
     </Card>
   )
 }
@@ -131,6 +169,7 @@ const ResumeDepositForm: FC<FormikProps<FormValues>> = (props) => {
       {/* Although the following button doesn't trigger an on-chain transaction, the 
       SubmitTxButton is used here for its built-in TRM Wallet screening validation logic. */}
       <SubmitTxButton
+        l2TransactionType={AllowedL2TransactionTypes.mint}
         size="lg"
         isFullWidth
         mt="6"
@@ -153,37 +192,61 @@ type FormValues = {
 type ResumeDepositFormikProps = {
   onSubmitForm: (values: FormValues) => void
   address: string
+  checkDepositExpiration: ReturnType<typeof useCheckDepositExpirationTime>
+  bitcoinNetwork: BitcoinNetwork
+  chainId: SupportedChainIds
 }
 
 const ResumeDepositFormik = withFormik<ResumeDepositFormikProps, FormValues>({
   mapPropsToValues: () => ({ depositParameters: null }),
-  validate: (values, { address }) => {
+  validate: async (
+    values,
+    { address, checkDepositExpiration, bitcoinNetwork, chainId }
+  ) => {
     const errors: FormikErrors<FormValues> = {}
 
-    if (!values.depositParameters) {
+    const dp = values.depositParameters
+
+    if (!dp) {
       errors.depositParameters = "Required."
     } else if (
-      !values.depositParameters?.depositor ||
-      !values.depositParameters?.depositor?.identifierHex ||
-      !isAddress(values.depositParameters?.depositor?.identifierHex) ||
-      !values.depositParameters?.refundLocktime ||
-      !values.depositParameters?.refundPublicKeyHash ||
-      !values.depositParameters?.blindingFactor ||
-      !values.depositParameters?.walletPublicKeyHash ||
-      !values.depositParameters?.btcRecoveryAddress
+      !dp.depositor ||
+      !dp.depositor.identifierHex ||
+      !dp.networkInfo?.chainName ||
+      !dp.networkInfo?.chainId ||
+      !isAddress(dp.depositor.identifierHex) ||
+      !dp.refundLocktime ||
+      !dp.refundPublicKeyHash ||
+      !dp.blindingFactor ||
+      !dp.walletPublicKeyHash ||
+      !dp.btcRecoveryAddress
     ) {
       errors.depositParameters = "Invalid .JSON file."
-    } else if (
-      !isSameETHAddress(
-        values.depositParameters?.depositor?.identifierHex,
-        address
+    } else if (!isSameChainId(dp.networkInfo.chainId, chainId)) {
+      errors.depositParameters = "Chain Id mismatch."
+    } else if (isL2Network(chainId) && !dp.extraData) {
+      errors.depositParameters = "Extra data is required for L2 networks."
+    } else {
+      const btcAddressError = validateBTCAddress(
+        dp.btcRecoveryAddress as string,
+        bitcoinNetwork
       )
-    ) {
-      errors.depositParameters = "You are not a depositor."
+      if (btcAddressError) {
+        errors.depositParameters = btcAddressError
+      } else {
+        // Check deposit expiration
+        const { isExpired } = await checkDepositExpiration(dp.refundLocktime)
+        if (isExpired) {
+          errors.depositParameters = "Deposit reveal time is expired."
+        } else if (!isSameETHAddress(dp.depositor.identifierHex, address)) {
+          errors.depositParameters = "You are not a depositor."
+        }
+      }
     }
 
     return getErrorsObj(errors)
   },
+
   handleSubmit: (values, { props }) => {
     props.onSubmitForm(values)
   },
diff --git a/src/store/tbtc/effects.ts b/src/store/tbtc/effects.ts
index e59c9a474..08222ec5d 100644
--- a/src/store/tbtc/effects.ts
+++ b/src/store/tbtc/effects.ts
@@ -14,6 +14,7 @@ import {
 import { isAddress, isAddressZero } from "../../web3/utils"
 import { AppListenerEffectAPI } from "../listener"
 import { tbtcSlice } from "./tbtcSlice"
+import { getChainIdToNetworkName, isL1Network } from "../../networks/utils"
 
 export const fetchBridgeactivityEffect = async (
   action: ReturnType<typeof tbtcSlice.actions.requestBridgeActivity>,
@@ -46,7 +47,7 @@ export const findUtxoEffect = async (
   action: ReturnType<typeof tbtcSlice.actions.findUtxo>,
   listenerApi: AppListenerEffectAPI
 ) => {
-  const { btcDepositAddress, depositor } = action.payload
+  const { btcDepositAddress, depositor, chainId } = action.payload
 
   const {
     tbtc: {
@@ -55,6 +56,8 @@ export const findUtxoEffect = async (
       walletPublicKeyHash,
       refundLocktime,
       btcRecoveryAddress,
+      chainName,
+      extraData,
     },
   } = listenerApi.getState()
 
@@ -70,6 +73,9 @@ export const findUtxoEffect = async (
   const pollingTask = listenerApi.fork(async (forkApi) => {
     try {
       while (true) {
+        if (getChainIdToNetworkName(chainId) !== chainName) {
+          throw new Error("Chain ID and deposit chain name mismatch")
+        }
         // Initiating deposit from redux store (if deposit object is empty)
         if (!listenerApi.extra.threshold.tbtc.deposit) {
           const bitcoinNetwork = listenerApi.extra.threshold.tbtc.bitcoinNetwork
@@ -83,17 +89,31 @@ export const findUtxoEffect = async (
               btcRecoveryAddress,
               bitcoinNetwork
             ).toString()
-          await forkApi.pause(
-            listenerApi.extra.threshold.tbtc.initiateDepositFromDepositScriptParameters(
-              {
-                depositor: getChainIdentifier(ethAddress),
-                blindingFactor,
-                walletPublicKeyHash,
-                refundPublicKeyHash,
-                refundLocktime,
-              }
+          const depositParams = {
+            depositor: getChainIdentifier(ethAddress),
+            blindingFactor,
+            walletPublicKeyHash,
+            refundPublicKeyHash,
+            refundLocktime,
+          }
+
+          if (isL1Network(chainId)) {
+            await forkApi.pause(
+              listenerApi.extra.threshold.tbtc.initiateDepositFromDepositScriptParameters(
+                depositParams
+              )
             )
-          )
+          } else {
+            await forkApi.pause(
+              listenerApi.extra.threshold.tbtc.initiateCrossChainDepositFromScriptParameters(
+                {
+                  ...depositParams,
+                  extraData,
+                },
+                chainId
+              )
+            )
+          }
         }
 
         // Looking for utxo.
@@ -148,7 +168,8 @@ export const findUtxoEffect = async (
             depositor,
             JSON.parse(
               localStorage.getItem(key) || "{}"
-            ) as TBTCLocalStorageDepositData
+            ) as TBTCLocalStorageDepositData,
+            chainId as number
           )
           listenerApi.dispatch(
             tbtcSlice.actions.updateState({
diff --git a/src/store/tbtc/tbtcSlice.ts b/src/store/tbtc/tbtcSlice.ts
index c0ce5ea11..10eb4a35a 100644
--- a/src/store/tbtc/tbtcSlice.ts
+++ b/src/store/tbtc/tbtcSlice.ts
@@ -109,6 +109,7 @@ export const tbtcSlice = createSlice({
       action: PayloadAction<{
         btcDepositAddress: string
         depositor: string
+        chainId: number
       }>
     ) => {},
     fetchUtxoConfirmations: (
diff --git a/src/types/tbtc.ts b/src/types/tbtc.ts
index 799dd9c48..9e9e198a1 100644
--- a/src/types/tbtc.ts
+++ b/src/types/tbtc.ts
@@ -2,6 +2,7 @@ import { BitcoinUtxo } from "@keep-network/tbtc-v2.ts"
 import { FetchingState } from "."
 import { BridgeActivity, BridgeProcess } from "../threshold-ts/tbtc"
 import { UpdateStateActionPayload } from "./state"
+import { NetworkName } from "../networks/types/networks"
 
 export interface TbtcState {
   mintingStep: MintingStep
@@ -21,6 +22,8 @@ export interface TbtcState {
   tBTCMintAmount: string
   thresholdNetworkFee: string
   mintingFee: string
+  chainName: NetworkName
+  extraData?: string
 
   bridgeActivity: FetchingState<BridgeActivity[]>
 }

From 3649ff4fd22236142fb3d54b49cd33d01e709135 Mon Sep 17 00:00:00 2001
From: evandrosaturnino <evandro.saturnino@gmail.com>
Date: Fri, 15 Nov 2024 03:57:50 -0300
Subject: [PATCH 14/46] update depositor property in minting process

---
 src/hooks/useTbtcState.ts                           |  1 +
 src/pages/tBTC/Bridge/Mint.tsx                      |  2 ++
 src/pages/tBTC/Bridge/Minting/MintingFlowRouter.tsx |  1 -
 src/pages/tBTC/Bridge/Minting/ProvideData.tsx       |  4 ++++
 src/pages/tBTC/Bridge/ResumeDeposit.tsx             | 11 +++++++++--
 src/store/tbtc/effects.ts                           |  6 +++---
 src/store/tbtc/tbtcSlice.ts                         |  1 -
 src/threshold-ts/tbtc/index.ts                      |  7 +------
 src/types/tbtc.ts                                   |  1 +
 src/utils/tbtcLocalStorageData.ts                   |  5 +++++
 10 files changed, 26 insertions(+), 13 deletions(-)

diff --git a/src/hooks/useTbtcState.ts b/src/hooks/useTbtcState.ts
index 2e9711136..934694c16 100644
--- a/src/hooks/useTbtcState.ts
+++ b/src/hooks/useTbtcState.ts
@@ -20,6 +20,7 @@ export const useTbtcState: UseTbtcState = () => {
     updateState("btcRecoveryAddress", undefined)
     updateState("walletPublicKeyHash", undefined)
     updateState("refundLocktime", undefined)
+    updateState("depositor", undefined)
     updateState("btcDepositAddress", undefined)
     updateState("mintingStep", MintingStep.ProvideData)
     updateState("tBTCMintAmount", undefined)
diff --git a/src/pages/tBTC/Bridge/Mint.tsx b/src/pages/tBTC/Bridge/Mint.tsx
index 5c20969d4..253ccd5b8 100644
--- a/src/pages/tBTC/Bridge/Mint.tsx
+++ b/src/pages/tBTC/Bridge/Mint.tsx
@@ -43,6 +43,7 @@ export const MintingFormPage: PageComponent = ({ ...props }) => {
         tBTCDepositData[account].btcDepositAddress !== btcDepositAddress
       ) {
         const {
+          depositor: { identifierHex: depositorAddress },
           btcDepositAddress,
           ethAddress,
           blindingFactor,
@@ -64,6 +65,7 @@ export const MintingFormPage: PageComponent = ({ ...props }) => {
         updateState("btcRecoveryAddress", btcRecoveryAddress)
         updateState("walletPublicKeyHash", walletPublicKeyHash)
         updateState("refundLocktime", refundLocktime)
+        updateState("depositor", depositorAddress)
         updateState("extraData", extraData)
         updateState("chainName", chainName)
         // We reset the minting step to undefined to show skeleton and the
diff --git a/src/pages/tBTC/Bridge/Minting/MintingFlowRouter.tsx b/src/pages/tBTC/Bridge/Minting/MintingFlowRouter.tsx
index c944c4a77..eb0f0410d 100644
--- a/src/pages/tBTC/Bridge/Minting/MintingFlowRouter.tsx
+++ b/src/pages/tBTC/Bridge/Minting/MintingFlowRouter.tsx
@@ -42,7 +42,6 @@ const MintingFlowRouterBase = () => {
     dispatch(
       tbtcSlice.actions.findUtxo({
         btcDepositAddress,
-        depositor: account,
         chainId,
       })
     )
diff --git a/src/pages/tBTC/Bridge/Minting/ProvideData.tsx b/src/pages/tBTC/Bridge/Minting/ProvideData.tsx
index 906d49e08..32381c09a 100644
--- a/src/pages/tBTC/Bridge/Minting/ProvideData.tsx
+++ b/src/pages/tBTC/Bridge/Minting/ProvideData.tsx
@@ -176,6 +176,7 @@ export const ProvideDataComponent: FC<{
 
       // update state,
       updateState("ethAddress", values.ethAddress)
+      updateState("depositor", receipt.depositor.identifierHex.toString())
       updateState("blindingFactor", receipt.blindingFactor.toString())
       updateState("btcRecoveryAddress", values.btcRecoveryAddress)
       updateState("walletPublicKeyHash", receipt.walletPublicKeyHash.toString())
@@ -188,6 +189,9 @@ export const ProvideDataComponent: FC<{
 
       setDepositDataInLocalStorage(
         {
+          depositor: {
+            identifierHex: receipt.depositor.identifierHex.toString(),
+          },
           chainName: chainName,
           ethAddress: values.ethAddress,
           blindingFactor: receipt.blindingFactor.toString(),
diff --git a/src/pages/tBTC/Bridge/ResumeDeposit.tsx b/src/pages/tBTC/Bridge/ResumeDeposit.tsx
index ba279911b..0bb78f1ba 100644
--- a/src/pages/tBTC/Bridge/ResumeDeposit.tsx
+++ b/src/pages/tBTC/Bridge/ResumeDeposit.tsx
@@ -32,6 +32,7 @@ type RecoveryJsonFileData = DepositScriptParameters & {
     chainId: string
     chainName: string
   }
+  ethAddress: string
   btcRecoveryAddress: string
 }
 import { useIsActive } from "../../../hooks/useIsActive"
@@ -88,8 +89,11 @@ export const ResumeDepositPage: PageComponent = () => {
       updateState("mintingStep", undefined)
       setDepositDataInLocalStorage(
         {
+          depositor: {
+            identifierHex: depositParameters.depositor.identifierHex,
+          },
           chainName: depositParameters.networkInfo.chainName,
-          ethAddress: depositParameters.depositor.identifierHex,
+          ethAddress: depositParameters.ethAddress,
           blindingFactor: depositParameters.blindingFactor,
           btcRecoveryAddress: depositParameters.btcRecoveryAddress,
           walletPublicKeyHash: depositParameters.walletPublicKeyHash,
@@ -238,7 +242,10 @@ const ResumeDepositFormik = withFormik<ResumeDepositFormikProps, FormValues>({
         const { isExpired } = await checkDepositExpiration(dp.refundLocktime)
         if (isExpired) {
           errors.depositParameters = "Deposit reveal time is expired."
-        } else if (!isSameETHAddress(dp.depositor.identifierHex, address)) {
+        } else if (
+          isL1Network(chainId) &&
+          !isSameETHAddress(dp.depositor.identifierHex, address)
+        ) {
           errors.depositParameters = "You are not a depositor."
         }
       }
diff --git a/src/store/tbtc/effects.ts b/src/store/tbtc/effects.ts
index 08222ec5d..a3dd600ac 100644
--- a/src/store/tbtc/effects.ts
+++ b/src/store/tbtc/effects.ts
@@ -47,11 +47,11 @@ export const findUtxoEffect = async (
   action: ReturnType<typeof tbtcSlice.actions.findUtxo>,
   listenerApi: AppListenerEffectAPI
 ) => {
-  const { btcDepositAddress, depositor, chainId } = action.payload
+  const { btcDepositAddress, chainId } = action.payload
 
   const {
     tbtc: {
-      ethAddress,
+      depositor,
       blindingFactor,
       walletPublicKeyHash,
       refundLocktime,
@@ -90,7 +90,7 @@ export const findUtxoEffect = async (
               bitcoinNetwork
             ).toString()
           const depositParams = {
-            depositor: getChainIdentifier(ethAddress),
+            depositor: getChainIdentifier(depositor),
             blindingFactor,
             walletPublicKeyHash,
             refundPublicKeyHash,
diff --git a/src/store/tbtc/tbtcSlice.ts b/src/store/tbtc/tbtcSlice.ts
index 10eb4a35a..c19b06ad3 100644
--- a/src/store/tbtc/tbtcSlice.ts
+++ b/src/store/tbtc/tbtcSlice.ts
@@ -108,7 +108,6 @@ export const tbtcSlice = createSlice({
       state,
       action: PayloadAction<{
         btcDepositAddress: string
-        depositor: string
         chainId: number
       }>
     ) => {},
diff --git a/src/threshold-ts/tbtc/index.ts b/src/threshold-ts/tbtc/index.ts
index d91f03267..657eac58b 100644
--- a/src/threshold-ts/tbtc/index.ts
+++ b/src/threshold-ts/tbtc/index.ts
@@ -757,12 +757,7 @@ export class TBTC implements ITBTC {
     }
 
     const depositReceipt = {
-      depositor: {
-        identifierHex: depositor.identifierHex,
-        equals: (identifier: ChainIdentifier) => {
-          return depositor.identifierHex === identifier.identifierHex
-        },
-      },
+      depositor,
       blindingFactor: Hex.from(blindingFactor),
       walletPublicKeyHash: Hex.from(walletPublicKeyHash),
       refundLocktime: Hex.from(refundLocktime),
diff --git a/src/types/tbtc.ts b/src/types/tbtc.ts
index 9e9e198a1..764ac1991 100644
--- a/src/types/tbtc.ts
+++ b/src/types/tbtc.ts
@@ -7,6 +7,7 @@ import { NetworkName } from "../networks/types/networks"
 export interface TbtcState {
   mintingStep: MintingStep
   // deposit data
+  depositor: string
   btcRecoveryAddress: string
   btcDepositAddress: string
   ethAddress: string
diff --git a/src/utils/tbtcLocalStorageData.ts b/src/utils/tbtcLocalStorageData.ts
index c9ea5d60a..3b98e65de 100644
--- a/src/utils/tbtcLocalStorageData.ts
+++ b/src/utils/tbtcLocalStorageData.ts
@@ -1,6 +1,11 @@
 import { writeStorage } from "@rehooks/local-storage"
 
+export type Depositor = {
+  identifierHex: string
+}
+
 export type TBTCDepositData = {
+  depositor: Depositor
   chainName: string
   ethAddress: string
   blindingFactor: string

From c3bfaad766e917fd747387df9f40a732f95b592a Mon Sep 17 00:00:00 2001
From: evandrosaturnino <evandro.saturnino@gmail.com>
Date: Fri, 15 Nov 2024 04:19:24 -0300
Subject: [PATCH 15/46] add tbtc subgraph api secret in github workflow

---
 .github/workflows/reusable-build-and-publish.yml | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/.github/workflows/reusable-build-and-publish.yml b/.github/workflows/reusable-build-and-publish.yml
index 175347f20..00f32954f 100644
--- a/.github/workflows/reusable-build-and-publish.yml
+++ b/.github/workflows/reusable-build-and-publish.yml
@@ -72,6 +72,9 @@ on:
           Project Id gathered from WalletConnect cloud. Required for
           WalletConnect v2.
         required: true
+      tbtcSubgraphApi:
+        description: The API endpoint for the tBTC subgraph.
+        required: true
 
 jobs:
   build-and-publish:

From 87c57e8b0a27e4889b9ee36a898b6e2548493643 Mon Sep 17 00:00:00 2001
From: evandrosaturnino <evandro.saturnino@gmail.com>
Date: Fri, 15 Nov 2024 04:29:51 -0300
Subject: [PATCH 16/46] Update yarn lock to reflect the tbtc sdk version

---
 yarn.lock | 135 ++++++++++++++++++++----------------------------------
 1 file changed, 50 insertions(+), 85 deletions(-)

diff --git a/yarn.lock b/yarn.lock
index fb9c7583d..547cc3a0b 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -3299,33 +3299,16 @@
   resolved "https://registry.yarnpkg.com/@keep-network/bitcoin-spv-sol/-/bitcoin-spv-sol-3.4.0-solc-0.8.tgz#8b44c246ffab8ea993efe196f6bf385b1a3b84dc"
   integrity sha512-KlpY9BbasyLvYXSS7dsJktgRChu/yjdFLOX8ldGA/pltLicCm/l0F4oqxL8wSws9XD12vq9x0B5qzPygVLB2TQ==
 
-"@keep-network/ecdsa@2.0.1":
-  version "2.0.1"
-  resolved "https://registry.yarnpkg.com/@keep-network/ecdsa/-/ecdsa-2.0.1.tgz#f9de5e4ae68c48493b8a46d1d956c8bc157b1145"
-  integrity sha512-51Ef0FGak9dzuTF4e80ed1G2+3v+kQYPieYa3hX7eKg3XG0/C/xOtMSpIOxU7IMdYBHeeH+hRIqDiL5AuOidOg==
+"@keep-network/ecdsa@2.1.0-dev.19":
+  version "2.1.0-dev.19"
+  resolved "https://registry.yarnpkg.com/@keep-network/ecdsa/-/ecdsa-2.1.0-dev.19.tgz#749af8bd65f70135d1734f7c5f9bff82ae308fdb"
+  integrity sha512-cyqRqK/sOqyaXZWY/O9ij6EINQuJ+bHLMiuufOFyP5YCj4GCuNqOcCytGAZPT+mED/0J/xn0vm+fgiCBq/uJkQ==
   dependencies:
-    "@keep-network/random-beacon" "2.0.0"
-    "@keep-network/sortition-pools" "2.0.0"
+    "@keep-network/random-beacon" "2.1.0-dev.18"
+    "@keep-network/sortition-pools" "^2.0.0-pre.16"
     "@openzeppelin/contracts" "^4.6.0"
     "@openzeppelin/contracts-upgradeable" "^4.6.0"
-    "@threshold-network/solidity-contracts" "1.2.1"
-
-"@keep-network/keep-core@1.3.0":
-  version "1.3.0"
-  resolved "https://registry.yarnpkg.com/@keep-network/keep-core/-/keep-core-1.3.0.tgz#09c1fd4d8d021b2afdff4801c7743d4c65b7bce3"
-  integrity sha512-c8efKWPx5da6OSdcm9/uvdDqrfwDcYAExNqPvomhLFC0dATEEFHsr/QOAqiBm4wCZZtWMKt0dYTm5QpGtx5TXQ==
-  dependencies:
-    "@openzeppelin/contracts-ethereum-package" "^2.4.0"
-    "@openzeppelin/upgrades" "^2.7.2"
-    openzeppelin-solidity "2.4.0"
-
-"@keep-network/keep-core@1.7.0":
-  version "1.7.0"
-  resolved "https://registry.yarnpkg.com/@keep-network/keep-core/-/keep-core-1.7.0.tgz#0923d539fc431810bd9b239f91e09a92a2b255a0"
-  integrity sha512-jU0ol4L5a7vFUXCTlYGsjZYhl87cUpiAYz9LgDgvM3sGmwNIVZ9dY3gziINXIbSSFZjoqh3eGDxDPcQmA+Rjrg==
-  dependencies:
-    "@openzeppelin/upgrades" "^2.7.2"
-    openzeppelin-solidity "2.4.0"
+    "@threshold-network/solidity-contracts" "1.3.0-dev.12"
 
 "@keep-network/keep-core@1.8.0-dev.5":
   version "1.8.0-dev.5"
@@ -3351,16 +3334,6 @@
     "@openzeppelin/upgrades" "^2.7.2"
     openzeppelin-solidity "2.4.0"
 
-"@keep-network/keep-ecdsa@1.2.1":
-  version "1.2.1"
-  resolved "https://registry.yarnpkg.com/@keep-network/keep-ecdsa/-/keep-ecdsa-1.2.1.tgz#5dcbc2c3808cce55a6e0d9e524868a0e9a0f1562"
-  integrity sha512-Oz0thgLoemt/nK6dl+MONU7TEoNR3lfbnMY/Aa0oWGcwR5PlNMiBVzYY7OT4oLZIK/MxEHDOWRQAijZEQffI7g==
-  dependencies:
-    "@keep-network/keep-core" "1.3.0"
-    "@keep-network/sortition-pools" "1.1.2"
-    "@openzeppelin/upgrades" "^2.7.2"
-    openzeppelin-solidity "2.3.0"
-
 "@keep-network/keep-ecdsa@>1.9.0-dev <1.9.0-ropsten":
   version "1.9.0-goerli.0"
   resolved "https://registry.yarnpkg.com/@keep-network/keep-ecdsa/-/keep-ecdsa-1.9.0-goerli.0.tgz#ce58b6639062bb4f73a257557aebb16447889e08"
@@ -3389,15 +3362,15 @@
   version "0.0.1"
   resolved "https://codeload.github.com/keep-network/prettier-config-keep/tar.gz/d6ec02e80dd76edfba073ca58ef99aee39002c2c"
 
-"@keep-network/random-beacon@2.0.0":
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/@keep-network/random-beacon/-/random-beacon-2.0.0.tgz#ac52dd03da49ec5b0d39ba85c51de6c4c8f1b1dc"
-  integrity sha512-c5AodlBkMRTEID7bDE7BA9lqDZcH3AFqOPz5b9f5syy62DnuiMkHTHIEIvdWWCL26m21A4PPyPjw7XirauE/OA==
+"@keep-network/random-beacon@2.1.0-dev.18":
+  version "2.1.0-dev.18"
+  resolved "https://registry.yarnpkg.com/@keep-network/random-beacon/-/random-beacon-2.1.0-dev.18.tgz#2647731eea35f931afb565988cc8d8cf6a34f6b7"
+  integrity sha512-UrVq///+jqOLQ5k8/aFvD1ZUMvVe49iS81U8mDoi9A005FiQzKUK9QFKv3Z0h6joG4prF/hlABRTEQ1UA7tgRA==
   dependencies:
-    "@keep-network/sortition-pools" "2.0.0"
-    "@openzeppelin/contracts" "^4.6.0"
+    "@keep-network/sortition-pools" "^2.0.0-pre.16"
+    "@openzeppelin/contracts" "4.7.3"
     "@thesis/solidity-contracts" "github:thesis/solidity-contracts#4985bcf"
-    "@threshold-network/solidity-contracts" "1.2.1"
+    "@threshold-network/solidity-contracts" "1.3.0-dev.11"
 
 "@keep-network/random-beacon@development":
   version "2.1.0-dev.10"
@@ -3409,13 +3382,6 @@
     "@thesis/solidity-contracts" "github:thesis/solidity-contracts#4985bcf"
     "@threshold-network/solidity-contracts" "1.3.0-dev.5"
 
-"@keep-network/sortition-pools@1.1.2":
-  version "1.1.2"
-  resolved "https://registry.yarnpkg.com/@keep-network/sortition-pools/-/sortition-pools-1.1.2.tgz#cfeb31d574b02d1ae32649df01b87af07229010a"
-  integrity sha512-bBaKyxkXDc8kJHq3qeESMrJ02m+Wbh6Uz9qUpWn8Zq3aTZaKXRZfGWT+J71OiBlAdyB4WoHZymrddWHkjImHdQ==
-  dependencies:
-    "@openzeppelin/contracts" "^2.4.0"
-
 "@keep-network/sortition-pools@1.2.0-dev.1":
   version "1.2.0-dev.1"
   resolved "https://registry.yarnpkg.com/@keep-network/sortition-pools/-/sortition-pools-1.2.0-dev.1.tgz#2ee371f1dd1ff71f6d05c9ddc2a83a4a93ff56b3"
@@ -3423,7 +3389,7 @@
   dependencies:
     "@openzeppelin/contracts" "^2.4.0"
 
-"@keep-network/sortition-pools@2.0.0", "@keep-network/sortition-pools@^2.0.0-pre.16":
+"@keep-network/sortition-pools@^2.0.0-pre.16":
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/@keep-network/sortition-pools/-/sortition-pools-2.0.0.tgz#04e29ec756d74e00d13505a3e2a7763b06d7a08d"
   integrity sha512-82pDOKcDBvHBFblCt0ALVr6qC6mxk339ZqnCfYx1zIPaPhzkw1RKOv28AqPoqzhzcdqLIoPh8g9RS/M2Lplh1A==
@@ -3431,15 +3397,14 @@
     "@openzeppelin/contracts" "^4.3.2"
     "@thesis/solidity-contracts" "github:thesis/solidity-contracts#4985bcf"
 
-"@keep-network/tbtc-v2.ts@^2.4.1":
-  version "2.4.1"
-  resolved "https://registry.yarnpkg.com/@keep-network/tbtc-v2.ts/-/tbtc-v2.ts-2.4.1.tgz#177046b32859fe5ad429f52c081e3cac994d3700"
-  integrity sha512-8MPrL4dr0HPDVphhxzfT+ApLqmWNTHJWCd16NFMYjT95Xu1nWuK3v3L6AU7mDb98X1XFT2Qc2OKh4JrtVmVVQw==
+"@keep-network/tbtc-v2.ts@^2.5.0-dev.8":
+  version "2.5.0-dev.8"
+  resolved "https://registry.yarnpkg.com/@keep-network/tbtc-v2.ts/-/tbtc-v2.ts-2.5.0-dev.8.tgz#6ff1f222652891beb125087412df12d05b74eecd"
+  integrity sha512-P/a1TlljPhJUYXuaV75Ck0EINpT96N1cyOMUQc3Bu8mGnUy6CKzRtvDTmYJFRV1W6bHBVgBaI0O09mZADulm8A==
   dependencies:
     "@bitcoinerlab/secp256k1" "^1.0.5"
-    "@keep-network/ecdsa" "2.0.1"
-    "@keep-network/tbtc-v2" "1.6.0"
-    "@ledgerhq/wallet-api-client" "^1.2.1"
+    "@keep-network/ecdsa" "2.1.0-dev.19"
+    "@keep-network/tbtc-v2" "1.7.0-dev.4"
     bignumber.js "^9.1.2"
     bitcoinjs-lib "^6.1.5"
     bufio "^1.0.6"
@@ -3450,30 +3415,20 @@
     url-parse "^1.5.10"
     wif "2.0.6"
 
-"@keep-network/tbtc-v2@1.6.0":
-  version "1.6.0"
-  resolved "https://registry.yarnpkg.com/@keep-network/tbtc-v2/-/tbtc-v2-1.6.0.tgz#06ed337d87bfd6d2d027aca461dbdd985207cc41"
-  integrity sha512-g+bZ1AHQTbNf3Mfze+PpexN7BO2WHHP8emZYo6VKOZi2amqqDjlY3yRKePa42cbNJXIdHcCwLgyLG+2G6WrZiA==
+"@keep-network/tbtc-v2@1.7.0-dev.4":
+  version "1.7.0-dev.4"
+  resolved "https://registry.yarnpkg.com/@keep-network/tbtc-v2/-/tbtc-v2-1.7.0-dev.4.tgz#fafbd3c7ccc8c68dbdb3e9c684b7f106b42a5a78"
+  integrity sha512-+DxR5XebK0DB5WIrQyCQG2osixBYpJhOuwQtLu3EDMsi4tFAPEh5MFjWG5LYeuEtX65p19mSC4Vj69/Z3jMgrA==
   dependencies:
     "@keep-network/bitcoin-spv-sol" "3.4.0-solc-0.8"
-    "@keep-network/ecdsa" "2.0.1"
-    "@keep-network/random-beacon" "2.0.0"
-    "@keep-network/tbtc" "1.1.0"
+    "@keep-network/ecdsa" "2.1.0-dev.19"
+    "@keep-network/random-beacon" "2.1.0-dev.18"
+    "@keep-network/tbtc" "1.1.2-dev.1"
     "@openzeppelin/contracts" "^4.8.1"
     "@openzeppelin/contracts-upgradeable" "^4.8.1"
     "@thesis/solidity-contracts" "github:thesis/solidity-contracts#4985bcf"
 
-"@keep-network/tbtc@1.1.0":
-  version "1.1.0"
-  resolved "https://registry.yarnpkg.com/@keep-network/tbtc/-/tbtc-1.1.0.tgz#9574ff355af04e77fb73a7bbe3e74cfd8764cf3c"
-  integrity sha512-V4sGR/t61PgkEF11GDZL5QNijVSdDhL7A7larcOSSCmKJOugxd5s+d+NdhYcHZhX9IS58ebtepvZan8TydHUHw==
-  dependencies:
-    "@keep-network/keep-ecdsa" "1.2.1"
-    "@summa-tx/bitcoin-spv-sol" "^3.1.0"
-    "@summa-tx/relay-sol" "^2.0.2"
-    openzeppelin-solidity "2.3.0"
-
-"@keep-network/tbtc@development":
+"@keep-network/tbtc@1.1.2-dev.1", "@keep-network/tbtc@development":
   version "1.1.2-dev.1"
   resolved "https://registry.yarnpkg.com/@keep-network/tbtc/-/tbtc-1.1.2-dev.1.tgz#dd1e734c0fed50474c74d7170c8749127231d1f9"
   integrity sha512-IRa0j1D7JBG8UpduaFxkaq2Ii6F61HhNMUBmxr7kAIZwj/yx8sYXWi921mn0L2Z+hAYNcwEUVhCM91VKQH29pQ==
@@ -3574,7 +3529,7 @@
   dependencies:
     "@ledgerhq/wallet-api-client" "1.2.1"
 
-"@ledgerhq/wallet-api-client@1.2.1", "@ledgerhq/wallet-api-client@^1.2.0", "@ledgerhq/wallet-api-client@^1.2.1":
+"@ledgerhq/wallet-api-client@1.2.1", "@ledgerhq/wallet-api-client@^1.2.0":
   version "1.2.1"
   resolved "https://registry.yarnpkg.com/@ledgerhq/wallet-api-client/-/wallet-api-client-1.2.1.tgz#b47fe5b4f431282f50ddb64c8abb911545593eba"
   integrity sha512-uTBTZCpbLTM5y5Cd7ioQB0lcq0b3cbrU2bGzCiKuY1IEd0NUyFhr2dKliRrcLoMPDRtQRmRnSxeX0BFKinoo8Q==
@@ -3731,11 +3686,6 @@
   resolved "https://registry.yarnpkg.com/@nucypher/nucypher-contracts/-/nucypher-contracts-0.13.0.tgz#43ead85d4cdf7eb6b459ba77a6ff90a8bb796300"
   integrity sha512-QB9vCVq2mLR2SeA/gSX8Px2QW3wcc9keQuTwgtDOA5J7PLoxDHEAko4ow6ZlsfjsbK572Xz6YReH09MBr71ujA==
 
-"@openzeppelin/contracts-ethereum-package@^2.4.0":
-  version "2.5.0"
-  resolved "https://registry.yarnpkg.com/@openzeppelin/contracts-ethereum-package/-/contracts-ethereum-package-2.5.0.tgz#cfb4b91f8132edde7e04bcd032575d4c6b544f4a"
-  integrity sha512-14CijdTyy4Y/3D3UUeFC2oW12nt1Yq1M8gFOtkuODEvSYPe3YSAKnKyhUeGf0UDNCZzwfGr15KdiFK6AoJjoSQ==
-
 "@openzeppelin/contracts-upgradeable@^4.6.0", "@openzeppelin/contracts-upgradeable@^4.8.1":
   version "4.9.1"
   resolved "https://registry.yarnpkg.com/@openzeppelin/contracts-upgradeable/-/contracts-upgradeable-4.9.1.tgz#03e33b8059ce43884995e69e4479f5a7f084b404"
@@ -3746,6 +3696,11 @@
   resolved "https://registry.yarnpkg.com/@openzeppelin/contracts-upgradeable/-/contracts-upgradeable-4.5.2.tgz#90d9e47bacfd8693bfad0ac8a394645575528d05"
   integrity sha512-xgWZYaPlrEOQo3cBj97Ufiuv79SPd8Brh4GcFYhPgb6WvAq4ppz8dWKL6h+jLAK01rUqMRp/TS9AdXgAeNvCLA==
 
+"@openzeppelin/contracts@4.7.3":
+  version "4.7.3"
+  resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-4.7.3.tgz#939534757a81f8d69cc854c7692805684ff3111e"
+  integrity sha512-dGRS0agJzu8ybo44pCIf3xBaPQN/65AIXNgK8+4gzKd5kbvlqyxryUYVLJv7fK98Seyd2hDZzVEHSWAh0Bt1Yw==
+
 "@openzeppelin/contracts@^2.4.0":
   version "2.5.1"
   resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-2.5.1.tgz#c76e3fc57aa224da3718ec351812a4251289db31"
@@ -4396,12 +4351,22 @@
   resolved "https://registry.npmjs.org/@threshold-network/components/-/components-1.0.0-dev.31.tgz#7767a9f136156f8d4f3044d90e87a1014eb07a67"
   integrity sha512-ftzJV6p2He3Co0wLYky+sX0NAFVGrJCRvBDI0n3KF4POBO425Qy3yodS7HOkT1TgGRNU8AGO0KebS2X7gfgAEA==
 
-"@threshold-network/solidity-contracts@1.2.1":
-  version "1.2.1"
-  resolved "https://registry.yarnpkg.com/@threshold-network/solidity-contracts/-/solidity-contracts-1.2.1.tgz#8f9d8fe52f24b51acc52fdff765fdef3b8546587"
-  integrity sha512-v19gnQzdU52DLB6ZpkCW4YHTvApmwA1EG/YRxh+FRrzeDOC6rv+EqUhLgKpMtSpgBZT1ryqqLXm1QmjkW6CIGw==
+"@threshold-network/solidity-contracts@1.3.0-dev.11":
+  version "1.3.0-dev.11"
+  resolved "https://registry.yarnpkg.com/@threshold-network/solidity-contracts/-/solidity-contracts-1.3.0-dev.11.tgz#849f20a5094c93359bbdea0c42780c318f985ee0"
+  integrity sha512-QQJB17BvuU/7UaitneoD7zFmIA3fZQ3FAvOAP2q+FkWEBZPYtAMf3+vB7y+Y+QlrcUl1kcA9wXD5auirsdxCBQ==
+  dependencies:
+    "@keep-network/keep-core" ">1.8.1-dev <1.8.1-goerli"
+    "@openzeppelin/contracts" "~4.5.0"
+    "@openzeppelin/contracts-upgradeable" "~4.5.2"
+    "@thesis/solidity-contracts" "github:thesis/solidity-contracts#4985bcf"
+
+"@threshold-network/solidity-contracts@1.3.0-dev.12":
+  version "1.3.0-dev.12"
+  resolved "https://registry.yarnpkg.com/@threshold-network/solidity-contracts/-/solidity-contracts-1.3.0-dev.12.tgz#55e2d789ac6cd2180f8f55cd876a5bdd0a9b45e6"
+  integrity sha512-06EF583uEwko3ik7qjnMOg+sJ+Vb7YWkqag4a9xZq8Mmy8rifpmLjnfDKCVGeKbUis3uI++pTGC9U/EfvVOrlQ==
   dependencies:
-    "@keep-network/keep-core" "1.7.0"
+    "@keep-network/keep-core" ">1.8.1-dev <1.8.1-goerli"
     "@openzeppelin/contracts" "~4.5.0"
     "@openzeppelin/contracts-upgradeable" "~4.5.2"
     "@thesis/solidity-contracts" "github:thesis/solidity-contracts#4985bcf"

From 5989ba1581b5d9e034612db5f346def9a0e99059 Mon Sep 17 00:00:00 2001
From: evandrosaturnino <evandro.saturnino@gmail.com>
Date: Thu, 21 Nov 2024 03:40:47 -0300
Subject: [PATCH 17/46] Update bitcoin electrum credentials logic

---
 .env.example                                  |  9 ++++--
 .env.production                               |  9 ++++--
 .github/workflows/dashboard-ci.yml            |  9 ++++--
 .github/workflows/dashboard-mainnet.yml       |  9 ++++--
 .../workflows/reusable-build-and-publish.yml  | 18 ++++++++----
 README.md                                     |  9 ++++--
 src/contexts/ThresholdContext.tsx             | 10 +++++--
 src/enums/env.ts                              |  9 ++++--
 src/threshold-ts/tbtc/index.ts                |  3 +-
 src/utils/getBitcoinCredentials.ts            | 29 +++++++++++++++++++
 src/utils/getThresholdLib.ts                  | 16 ++++------
 11 files changed, 90 insertions(+), 40 deletions(-)
 create mode 100644 src/utils/getBitcoinCredentials.ts

diff --git a/.env.example b/.env.example
index 799828f47..9e876f45b 100644
--- a/.env.example
+++ b/.env.example
@@ -18,9 +18,12 @@ REACT_APP_FEATURE_FLAG_SENTRY=false
 REACT_APP_SENTRY_DSN=$SENTRY_DSN
 REACT_APP_FEATURE_FLAG_TRM=false
 
-REACT_APP_ELECTRUM_PROTOCOL=$ELECTRUM_PROTOCOL
-REACT_APP_ELECTRUM_HOST=$ELECTRUM_HOST
-REACT_APP_ELECTRUM_PORT=$ELECTRUM_PORT
+REACT_APP_MAINNET_ELECTRUM_PROTOCOL=$MAINNET_ELECTRUM_PROTOCOL
+REACT_APP_MAINNET_ELECTRUM_HOST=$MAINNET_ELECTRUM_HOST
+REACT_APP_MAINNET_ELECTRUM_PORT=$MAINNET_ELECTRUM_PORT
+REACT_APP_TESTNET_ELECTRUM_PROTOCOL=$TESTNET_ELECTRUM_PROTOCOL
+REACT_APP_TESTNET_ELECTRUM_HOST=$TESTNET_ELECTRUM_HOST
+REACT_APP_TESTNET_ELECTRUM_PORT=$TESTNET_ELECTRUM_PORT
 REACT_APP_MOCK_BITCOIN_CLIENT=true
 
 REACT_APP_WALLET_CONNECT_PROJECT_ID=$WALLET_CONNECT_PROJECT_ID
diff --git a/.env.production b/.env.production
index f60c8564f..745dc37e7 100644
--- a/.env.production
+++ b/.env.production
@@ -19,9 +19,12 @@ REACT_APP_FEATURE_FLAG_SENTRY=$SENTRY_SUPPORT
 REACT_APP_SENTRY_DSN=$SENTRY_DSN
 REACT_APP_FEATURE_FLAG_TRM=$TRM_SUPPORT
 
-REACT_APP_ELECTRUM_PROTOCOL=$ELECTRUM_PROTOCOL
-REACT_APP_ELECTRUM_HOST=$ELECTRUM_HOST
-REACT_APP_ELECTRUM_PORT=$ELECTRUM_PORT
+REACT_APP_MAINNET_ELECTRUM_PROTOCOL=$MAINNET_ELECTRUM_PROTOCOL
+REACT_APP_MAINNET_ELECTRUM_HOST=$MAINNET_ELECTRUM_HOST
+REACT_APP_MAINNET_ELECTRUM_PORT=$MAINNET_ELECTRUM_PORT
+REACT_APP_TESTNET_ELECTRUM_PROTOCOL=$TESTNET_ELECTRUM_PROTOCOL
+REACT_APP_TESTNET_ELECTRUM_HOST=$TESTNET_ELECTRUM_HOST
+REACT_APP_TESTNET_ELECTRUM_PORT=$TESTNET_ELECTRUM_PORT
 REACT_APP_MOCK_BITCOIN_CLIENT=false
 
 REACT_APP_WALLET_CONNECT_PROJECT_ID=$WALLET_CONNECT_PROJECT_ID
diff --git a/.github/workflows/dashboard-ci.yml b/.github/workflows/dashboard-ci.yml
index a1bdd71a9..3c52b07eb 100644
--- a/.github/workflows/dashboard-ci.yml
+++ b/.github/workflows/dashboard-ci.yml
@@ -89,9 +89,12 @@ jobs:
           DEFAULT_PROVIDER_CHAIN_ID: 11155111
           ALCHEMY_API: ${{ secrets.ALCHEMY_API }}
           NODE_OPTIONS: --max_old_space_size=4096
-          ELECTRUM_PROTOCOL: ${{ secrets.TESTNET_ELECTRUMX_PROTOCOL }}
-          ELECTRUM_HOST: ${{ secrets.TESTNET_ELECTRUMX_HOST }}
-          ELECTRUM_PORT: ${{ secrets.TESTNET_ELECTRUMX_PORT }}
+          MAINNET_ELECTRUM_PROTOCOL: ${{ secrets.MAINNET_ELECTRUMX_PROTOCOL }}
+          MAINNET_ELECTRUM_HOST: ${{ secrets.MAINNET_ELECTRUMX_HOST }}
+          MAINNET_ELECTRUM_PORT: ${{ secrets.MAINNET_ELECTRUMX_PORT }}
+          TESTNET_ELECTRUM_PROTOCOL: ${{ secrets.TESTNET_ELECTRUMX_PROTOCOL }}
+          TESTNET_ELECTRUM_HOST: ${{ secrets.TESTNET_ELECTRUMX_HOST }}
+          TESTNET_ELECTRUM_PORT: ${{ secrets.TESTNET_ELECTRUMX_PORT }}
           WALLET_CONNECT_PROJECT_ID: ${{ secrets.WALLET_CONNECT_PROJECT_ID }}
           TBTC_SUBGRAPH_API: ${{ secrets.TBTC_SUBGRAPH_API }}
 
diff --git a/.github/workflows/dashboard-mainnet.yml b/.github/workflows/dashboard-mainnet.yml
index 9f43cccfe..94a3c2ebc 100644
--- a/.github/workflows/dashboard-mainnet.yml
+++ b/.github/workflows/dashboard-mainnet.yml
@@ -51,9 +51,12 @@ jobs:
           DEFAULT_PROVIDER_CHAIN_ID: 1
           ALCHEMY_API: ${{ secrets.ALCHEMY_API }}
           NODE_OPTIONS: --max_old_space_size=4096
-          ELECTRUM_PROTOCOL: ${{ secrets.MAINNET_ELECTRUMX_PROTOCOL }}
-          ELECTRUM_HOST: ${{ secrets.MAINNET_ELECTRUMX_HOST }}
-          ELECTRUM_PORT: ${{ secrets.MAINNET_ELECTRUMX_PORT }}
+          MAINNET_ELECTRUM_PROTOCOL: ${{ secrets.MAINNET_ELECTRUMX_PROTOCOL }}
+          MAINNET_ELECTRUM_HOST: ${{ secrets.MAINNET_ELECTRUMX_HOST }}
+          MAINNET_ELECTRUM_PORT: ${{ secrets.MAINNET_ELECTRUMX_PORT }}
+          TESTNET_ELECTRUM_PROTOCOL: ${{ secrets.TESTNET_ELECTRUMX_PROTOCOL }}
+          TESTNET_ELECTRUM_HOST: ${{ secrets.TESTNET_ELECTRUMX_HOST }}
+          TESTNET_ELECTRUM_PORT: ${{ secrets.TESTNET_ELECTRUMX_PORT }}
           SENTRY_SUPPORT: true
           SENTRY_DSN: ${{ secrets.MAINNET_SENTRY_DSN }}
           TRM_SUPPORT: ${{ secrets.TRM_SUPPORT }}
diff --git a/.github/workflows/reusable-build-and-publish.yml b/.github/workflows/reusable-build-and-publish.yml
index 00f32954f..bc1579df5 100644
--- a/.github/workflows/reusable-build-and-publish.yml
+++ b/.github/workflows/reusable-build-and-publish.yml
@@ -164,9 +164,12 @@ jobs:
           DEFAULT_PROVIDER_CHAIN_ID: ${{ env.NETWORK_ID }}
           ALCHEMY_API: ${{ secrets.alchemyApi }}
           NODE_OPTIONS: --max_old_space_size=4096
-          ELECTRUM_PROTOCOL: ${{ secrets.electrumProtocol }}
-          ELECTRUM_HOST: ${{ secrets.electrumHost }}
-          ELECTRUM_PORT: ${{ secrets.electrumPort }}
+          MAINNET_ELECTRUM_PROTOCOL: ${{ secrets.mainnetElectrumProtocol }}
+          MAINNET_ELECTRUM_HOST: ${{ secrets.mainnetElectrumHost }}
+          MAINNET_ELECTRUM_PORT: ${{ secrets.mainnetElectrumPort }}
+          TESTNET_ELECTRUM_PROTOCOL: ${{ secrets.testnetElectrumProtocol }}
+          TESTNET_ELECTRUM_HOST: ${{ secrets.testnetElectrumHost }}
+          TESTNET_ELECTRUM_PORT: ${{ secrets.testnetElectrumPort }}
           SENTRY_SUPPORT: true
           SENTRY_DSN: ${{ secrets.sentryDsn }}
           WALLET_CONNECT_PROJECT_ID: ${{ secrets.walletConnectProjectId }}
@@ -182,9 +185,12 @@ jobs:
           DEFAULT_PROVIDER_CHAIN_ID: ${{ env.NETWORK_ID }}
           ALCHEMY_API: ${{ secrets.alchemyApi }}
           NODE_OPTIONS: --max_old_space_size=4096
-          ELECTRUM_PROTOCOL: ${{ secrets.electrumProtocol }}
-          ELECTRUM_HOST: ${{ secrets.electrumHost }}
-          ELECTRUM_PORT: ${{ secrets.electrumPort }}
+          MAINNET_ELECTRUM_PROTOCOL: ${{ secrets.mainnetElectrumProtocol }}
+          MAINNET_ELECTRUM_HOST: ${{ secrets.mainnetElectrumHost }}
+          MAINNET_ELECTRUM_PORT: ${{ secrets.mainnetElectrumPort }}
+          TESTNET_ELECTRUM_PROTOCOL: ${{ secrets.testnetElectrumProtocol }}
+          TESTNET_ELECTRUM_HOST: ${{ secrets.testnetElectrumHost }}
+          TESTNET_ELECTRUM_PORT: ${{ secrets.testnetElectrumPort }}
           SENTRY_SUPPORT: true
           SENTRY_DSN: ${{ secrets.sentryDsn }}
           WALLET_CONNECT_PROJECT_ID: ${{ secrets.walletConnectProjectId }}
diff --git a/README.md b/README.md
index 3d6ca5375..3168902fc 100644
--- a/README.md
+++ b/README.md
@@ -127,9 +127,12 @@ REACT_APP_FEATURE_FLAG_SENTRY=false
 REACT_APP_SENTRY_DSN=$SENTRY_DSN
 REACT_APP_FEATURE_FLAG_TRM=false
 
-REACT_APP_ELECTRUM_PROTOCOL=wss
-REACT_APP_ELECTRUM_HOST=electrumx-server.test.tbtc.network
-REACT_APP_ELECTRUM_PORT=8443
+REACT_APP_MAINNET_ELECTRUM_PROTOCOL=$MAINNET_ELECTRUM_PROTOCOL
+REACT_APP_MAINNET_ELECTRUM_HOST=$MAINNET_ELECTRUM_HOST
+REACT_APP_MAINNET_ELECTRUM_PORT=$MAINNET_ELECTRUM_PORT
+REACT_APP_TESTNET_ELECTRUM_PROTOCOL=wss
+REACT_APP_TESTNET_ELECTRUM_HOST=electrumx-server.test.tbtc.network
+REACT_APP_TESTNET_ELECTRUM_PORT=8443
 REACT_APP_MOCK_BITCOIN_CLIENT=false
 
 REACT_APP_WALLET_CONNECT_PROJECT_ID=$WALLET_CONNECT_PROJECT_ID
diff --git a/src/contexts/ThresholdContext.tsx b/src/contexts/ThresholdContext.tsx
index 9bd60cbfe..3ee3fb5ff 100644
--- a/src/contexts/ThresholdContext.tsx
+++ b/src/contexts/ThresholdContext.tsx
@@ -7,6 +7,7 @@ import { isTestnetNetwork } from "../networks/utils/connectedNetwork"
 import { BitcoinNetwork } from "@keep-network/tbtc-v2.ts"
 import { getDefaultProviderChainId } from "../utils/getEnvVariable"
 import { useWeb3React } from "@web3-react/core"
+import { getBitcoinCredentials } from "../utils/getBitcoinCredentials"
 
 const ThresholdContext = createContext(threshold)
 
@@ -23,6 +24,10 @@ export const ThresholdProvider: FC = ({ children }) => {
 
   useEffect(() => {
     if (isActive && chainId) {
+      const bitcoinNetwork = isTestnetNetwork(chainId)
+        ? BitcoinNetwork.Testnet
+        : BitcoinNetwork.Mainnet
+
       threshold.updateConfig({
         ethereum: {
           ...threshold.config.ethereum,
@@ -32,9 +37,8 @@ export const ThresholdProvider: FC = ({ children }) => {
         },
         bitcoin: {
           ...threshold.config.bitcoin,
-          network: isTestnetNetwork(chainId)
-            ? BitcoinNetwork.Testnet
-            : BitcoinNetwork.Mainnet,
+          network: bitcoinNetwork,
+          credentials: getBitcoinCredentials(bitcoinNetwork),
         },
       })
       hasThresholdLibConfigBeenUpdated.current = true
diff --git a/src/enums/env.ts b/src/enums/env.ts
index 21373a683..6a9715427 100644
--- a/src/enums/env.ts
+++ b/src/enums/env.ts
@@ -11,9 +11,12 @@ const envVariables = [
   "FEATURE_FLAG_TRM",
   "POSTHOG_HOSTNAME_HTTP",
   "POSTHOG_API_KEY",
-  "ELECTRUM_PROTOCOL",
-  "ELECTRUM_HOST",
-  "ELECTRUM_PORT",
+  "MAINNET_ELECTRUM_PROTOCOL",
+  "MAINNET_ELECTRUM_HOST",
+  "MAINNET_ELECTRUM_PORT",
+  "TESTNET_ELECTRUM_PROTOCOL",
+  "TESTNET_ELECTRUM_HOST",
+  "TESTNET_ELECTRUM_PORT",
   "MOCK_BITCOIN_CLIENT",
   "FEATURE_FLAG_SENTRY",
   "SENTRY_DSN",
diff --git a/src/threshold-ts/tbtc/index.ts b/src/threshold-ts/tbtc/index.ts
index 657eac58b..0dd98bdbf 100644
--- a/src/threshold-ts/tbtc/index.ts
+++ b/src/threshold-ts/tbtc/index.ts
@@ -51,7 +51,6 @@ import {
   getMainnetOrTestnetChainId,
 } from "../../networks/utils"
 import { SupportedChainIds } from "../../networks/enums/networks"
-import { getDefaultProviderChainId } from "../../utils/getEnvVariable"
 import { getThresholdLibProvider } from "../../utils/getThresholdLib"
 
 export enum BridgeActivityStatus {
@@ -498,7 +497,7 @@ export class TBTC implements ITBTC {
     this._isCrossChain = isL2Network(chainId)
 
     const defaultOrConnectedChainId = this._isCrossChain
-      ? getDefaultProviderChainId()
+      ? getMainnetOrTestnetChainId(chainId)
       : chainId
     const defaultOrConnectedProvider = this._isCrossChain
       ? getThresholdLibProvider(defaultOrConnectedChainId)
diff --git a/src/utils/getBitcoinCredentials.ts b/src/utils/getBitcoinCredentials.ts
new file mode 100644
index 000000000..57e424827
--- /dev/null
+++ b/src/utils/getBitcoinCredentials.ts
@@ -0,0 +1,29 @@
+import { BitcoinNetwork } from "@keep-network/tbtc-v2.ts"
+import { BitcoinClientCredentials } from "../threshold-ts/types"
+import { EnvVariable } from "../enums"
+import { getEnvVariable } from "./getEnvVariable"
+
+export const getBitcoinCredentials = (bitcoinNetwork: BitcoinNetwork) => {
+  const credentials: BitcoinClientCredentials[] =
+    bitcoinNetwork === BitcoinNetwork.Mainnet
+      ? [
+          {
+            host: getEnvVariable(EnvVariable.MAINNET_ELECTRUM_HOST),
+            port: +getEnvVariable(EnvVariable.MAINNET_ELECTRUM_PORT),
+            protocol: getEnvVariable(
+              EnvVariable.MAINNET_ELECTRUM_PROTOCOL
+            ) as BitcoinClientCredentials["protocol"],
+          },
+        ]
+      : [
+          {
+            host: getEnvVariable(EnvVariable.TESTNET_ELECTRUM_HOST),
+            port: +getEnvVariable(EnvVariable.TESTNET_ELECTRUM_PORT),
+            protocol: getEnvVariable(
+              EnvVariable.TESTNET_ELECTRUM_PROTOCOL
+            ) as BitcoinClientCredentials["protocol"],
+          },
+        ]
+
+  return credentials
+}
diff --git a/src/utils/getThresholdLib.ts b/src/utils/getThresholdLib.ts
index 9b8850370..5ecf1bc1b 100644
--- a/src/utils/getThresholdLib.ts
+++ b/src/utils/getThresholdLib.ts
@@ -20,6 +20,7 @@ import {
   EthereumConfig,
 } from "../threshold-ts/types"
 import { SupportedChainIds } from "../networks/enums/networks"
+import { getBitcoinCredentials } from "./getBitcoinCredentials"
 
 const defaultProviderChainId = getDefaultProviderChainId()
 
@@ -37,26 +38,19 @@ function getInitialEthereumConfig(
 }
 
 function getInitialBitcoinConfig(): BitcoinConfig {
-  const network = isTestnetNetwork(defaultProviderChainId)
+  const bitcoinNetwork = isTestnetNetwork(defaultProviderChainId)
     ? BitcoinNetwork.Testnet
     : BitcoinNetwork.Mainnet
 
   const shouldMockBitcoinClient =
     getEnvVariable(EnvVariable.MOCK_BITCOIN_CLIENT) === "true"
 
-  const credentials: BitcoinClientCredentials[] = [
-    {
-      host: getEnvVariable(EnvVariable.ELECTRUM_HOST),
-      port: +getEnvVariable(EnvVariable.ELECTRUM_PORT),
-      protocol: getEnvVariable(
-        EnvVariable.ELECTRUM_PROTOCOL
-      ) as BitcoinClientCredentials["protocol"],
-    },
-  ]
+  const credentials: BitcoinClientCredentials[] =
+    getBitcoinCredentials(bitcoinNetwork)
 
   return {
     client: shouldMockBitcoinClient ? new MockBitcoinClient() : undefined,
-    network,
+    network: bitcoinNetwork,
     credentials: !shouldMockBitcoinClient ? credentials : undefined,
   }
 }

From de89ae08cef798cc080d7c671dbde1fa0b5232fb Mon Sep 17 00:00:00 2001
From: evandrosaturnino <evandro.saturnino@gmail.com>
Date: Thu, 21 Nov 2024 03:56:36 -0300
Subject: [PATCH 18/46] Update block explorer url in some tbtc components

---
 src/components/ViewInBlockExplorer.tsx          | 17 +++++++++++++----
 src/components/tBTC/Links.tsx                   |  3 ---
 src/pages/tBTC/Bridge/DepositDetails.tsx        |  1 -
 .../Bridge/components/BridgeProcessStep.tsx     |  2 --
 4 files changed, 13 insertions(+), 10 deletions(-)

diff --git a/src/components/ViewInBlockExplorer.tsx b/src/components/ViewInBlockExplorer.tsx
index 479b7532e..727957c15 100644
--- a/src/components/ViewInBlockExplorer.tsx
+++ b/src/components/ViewInBlockExplorer.tsx
@@ -2,11 +2,12 @@ import { FC } from "react"
 import { LinkProps } from "@chakra-ui/react"
 import Link from "./Link"
 import { ExplorerDataType } from "../networks/enums/networks"
-import { isTestnetNetwork } from "../networks/utils"
+import { getMainnetOrTestnetChainId, isTestnetNetwork } from "../networks/utils"
 import {
   createBlockExplorerLink,
   createExplorerLink,
 } from "../networks/utils/createExplorerLink"
+import { useIsActive } from "../hooks/useIsActive"
 
 export type Chain = "bitcoin" | "ethereum"
 
@@ -18,14 +19,14 @@ export const createLinkToBlockExplorerForChain: Record<
     ethereumNetworkChainId?: string | number
   ) => string
 > = {
-  bitcoin: (id, type, ethereumNetworkChainId = 1) => {
+  bitcoin: (id, type, ethereumNetworkChainId) => {
     const prefix = `https://blockstream.info${
       isTestnetNetwork(Number(ethereumNetworkChainId)) ? "/testnet" : ""
     }`
 
     return createBlockExplorerLink(prefix, id, type)
   },
-  ethereum: (id, type, ethereumNetworkChainId = 1) =>
+  ethereum: (id, type, ethereumNetworkChainId) =>
     createExplorerLink(Number(ethereumNetworkChainId), id, type),
 }
 
@@ -58,10 +59,18 @@ const ViewInBlockExplorer: FC<ViewInBlockExplorerProps> = ({
   ethereumNetworkChainId,
   ...restProps
 }) => {
+  // Some networks, such as Arbitrum and Base, are only available
+  // for specific actions, e.g., signing the L1BitcoinDepositor
+  // contract. For those cases in particular, the connected chainId
+  // should be passed as a prop as ethereumNetworkChainId.
+  const { chainId } = useIsActive()
+  const explorerChainId =
+    ethereumNetworkChainId ?? getMainnetOrTestnetChainId(chainId)
+
   const link = createLinkToBlockExplorerForChain[chain](
     id,
     type,
-    ethereumNetworkChainId
+    explorerChainId
   )
 
   return (
diff --git a/src/components/tBTC/Links.tsx b/src/components/tBTC/Links.tsx
index 0491be04f..9ed2d5c63 100644
--- a/src/components/tBTC/Links.tsx
+++ b/src/components/tBTC/Links.tsx
@@ -3,7 +3,6 @@ import { useTBTCBridgeContractAddress } from "../../hooks/useTBTCBridgeContractA
 import { ExplorerDataType } from "../../networks/enums/networks"
 import ViewInBlockExplorer from "../ViewInBlockExplorer"
 import { useTBTCTokenAddress } from "../../hooks/useTBTCTokenAddress"
-import { useIsActive } from "../../hooks/useIsActive"
 
 type Props = Omit<
   ComponentProps<typeof ViewInBlockExplorer>,
@@ -34,14 +33,12 @@ export const TBTCTokenContractLink: FC<Props> = ({
   text = "token address",
   ...props
 }) => {
-  const { chainId } = useIsActive()
   const address = useTBTCTokenAddress()
   return address ? (
     <ViewInBlockExplorer
       id={address}
       type={ExplorerDataType.ADDRESS}
       text={text}
-      ethereumNetworkChainId={chainId}
       {...props}
     />
   ) : (
diff --git a/src/pages/tBTC/Bridge/DepositDetails.tsx b/src/pages/tBTC/Bridge/DepositDetails.tsx
index d46396d10..28e6e9beb 100644
--- a/src/pages/tBTC/Bridge/DepositDetails.tsx
+++ b/src/pages/tBTC/Bridge/DepositDetails.tsx
@@ -273,7 +273,6 @@ export const DepositDetails: PageComponent = () => {
                             id={item.txHash!}
                             type={ExplorerDataType.TRANSACTION}
                             chain={item.chain}
-                            ethereumNetworkChainId={chainId}
                             text="transaction"
                           />
                           .
diff --git a/src/pages/tBTC/Bridge/components/BridgeProcessStep.tsx b/src/pages/tBTC/Bridge/components/BridgeProcessStep.tsx
index 74086aed1..0e39a4305 100644
--- a/src/pages/tBTC/Bridge/components/BridgeProcessStep.tsx
+++ b/src/pages/tBTC/Bridge/components/BridgeProcessStep.tsx
@@ -41,7 +41,6 @@ export const BridgeProcessStep: FC<BridgeProcessStepProps> = ({
   children,
 }) => {
   const titleTextColor = useColorModeValue("gray.700", "gray.300")
-  const { chainId } = useIsActive()
 
   useEffect(() => {
     if (!isCompleted) return
@@ -90,7 +89,6 @@ export const BridgeProcessStep: FC<BridgeProcessStepProps> = ({
             text={chain === "bitcoin" ? "blockstream" : "network explorer"}
             chain={chain}
             id={txHash}
-            ethereumNetworkChainId={chainId}
             type={ExplorerDataType.TRANSACTION}
           />
         </BodySm>

From 092e58caaa2ba23160a9e02f8561136bd8607234 Mon Sep 17 00:00:00 2001
From: evandrosaturnino <evandro.saturnino@gmail.com>
Date: Thu, 21 Nov 2024 03:59:19 -0300
Subject: [PATCH 19/46] Add chainid to redux effects to avoid incompatibility

---
 src/pages/Overview/Network/index.tsx          |  9 ++--
 .../Staking/AuthorizeStakingApps/index.tsx    | 13 ++++--
 src/pages/Staking/StakeDetailsPage/index.tsx  | 13 ++++--
 src/pages/tBTC/Bridge/index.tsx               | 11 ++---
 src/store/staking/effects.ts                  | 12 +++--
 src/store/staking/stakingSlice.ts             |  1 +
 src/store/tbtc/effects.ts                     | 44 ++++++++++---------
 src/store/tbtc/tbtcSlice.ts                   |  2 +-
 8 files changed, 66 insertions(+), 39 deletions(-)

diff --git a/src/pages/Overview/Network/index.tsx b/src/pages/Overview/Network/index.tsx
index 076ed4c24..0e71fb1ac 100644
--- a/src/pages/Overview/Network/index.tsx
+++ b/src/pages/Overview/Network/index.tsx
@@ -21,26 +21,29 @@ import { selectBridgeActivity, tbtcSlice } from "../../../store/tbtc"
 import ButtonLink from "../../../components/ButtonLink"
 import upgradeToTIcon from "../../../static/images/upgrade-to-t.svg"
 import { useIsActive } from "../../../hooks/useIsActive"
+import { useThreshold } from "../../../contexts/ThresholdContext"
 
 const Network: PageComponent = () => {
   const [tvlInUSD, fetchtTvlData, tvlInTokenUnits] = useFetchTvl()
   const [deposits, isFetching, error] = useFetchRecentDeposits()
-  const { account } = useIsActive()
+  const { account, chainId } = useIsActive()
   const dispatch = useAppDispatch()
   const bridgeActivity = useAppSelector(selectBridgeActivity)
   const isBridgeActivityFetching = useAppSelector(
     (state) => state.tbtc.bridgeActivity.isFetching
   )
+  const threshold = useThreshold()
 
   useEffect(() => {
-    if (!account) return
+    if (!account || !chainId) return
 
     dispatch(
       tbtcSlice.actions.requestBridgeActivity({
         depositor: account,
+        chainId: chainId,
       })
     )
-  }, [dispatch, account])
+  }, [dispatch, account, threshold.tbtc])
 
   useEffect(() => {
     fetchtTvlData()
diff --git a/src/pages/Staking/AuthorizeStakingApps/index.tsx b/src/pages/Staking/AuthorizeStakingApps/index.tsx
index e8689cf15..4e42fc745 100644
--- a/src/pages/Staking/AuthorizeStakingApps/index.tsx
+++ b/src/pages/Staking/AuthorizeStakingApps/index.tsx
@@ -38,10 +38,12 @@ import { FormValues } from "../../../components/Forms"
 import { useAppDispatch } from "../../../hooks/store"
 import { stakingApplicationsSlice } from "../../../store/staking-applications"
 import BundledRewardsAlert from "../../../components/BundledRewardsAlert"
+import { useThreshold } from "../../../contexts/ThresholdContext"
 
 const AuthorizeStakingAppsPage: FC = () => {
   const { stakingProviderAddress } = useParams()
-  const { account, active } = useWeb3React()
+  const { account, active, chainId } = useWeb3React()
+  const threshold = useThreshold()
   const navigate = useNavigate()
   const { openModal } = useModal()
   const tbtcAppFormRef = useRef<FormikProps<FormValues>>(null)
@@ -75,10 +77,15 @@ const AuthorizeStakingAppsPage: FC = () => {
   }, [stakingProviderAddress, navigate])
 
   useEffect(() => {
+    if (!chainId) return
+
     dispatch(
-      requestStakeByStakingProvider({ stakingProvider: stakingProviderAddress })
+      requestStakeByStakingProvider({
+        stakingProvider: stakingProviderAddress,
+        chainId,
+      })
     )
-  }, [stakingProviderAddress, account, dispatch])
+  }, [stakingProviderAddress, account, threshold.staking, dispatch])
 
   useEffect(() => {
     dispatch(stakingApplicationsSlice.actions.getSupportedApps({}))
diff --git a/src/pages/Staking/StakeDetailsPage/index.tsx b/src/pages/Staking/StakeDetailsPage/index.tsx
index 36c638576..9daa685c1 100644
--- a/src/pages/Staking/StakeDetailsPage/index.tsx
+++ b/src/pages/Staking/StakeDetailsPage/index.tsx
@@ -34,10 +34,12 @@ import { useWeb3React } from "@web3-react/core"
 import { AddressZero } from "@ethersproject/constants"
 import { isAddress } from "../../../web3/utils"
 import { stakingApplicationsSlice } from "../../../store/staking-applications"
+import { useThreshold } from "../../../contexts/ThresholdContext"
 
 const StakeDetailsPage: FC = () => {
   const { stakingProviderAddress } = useParams()
-  const { account, active } = useWeb3React()
+  const { account, active, chainId } = useWeb3React()
+  const threshold = useThreshold()
   const { openModal } = useModal()
   const navigate = useNavigate()
   const dispatch = useAppDispatch()
@@ -51,10 +53,15 @@ const StakeDetailsPage: FC = () => {
   }, [dispatch])
 
   useEffect(() => {
+    if (!chainId) return
+
     dispatch(
-      requestStakeByStakingProvider({ stakingProvider: stakingProviderAddress })
+      requestStakeByStakingProvider({
+        stakingProvider: stakingProviderAddress,
+        chainId,
+      })
     )
-  }, [stakingProviderAddress, account, dispatch])
+  }, [stakingProviderAddress, account, threshold.staking, dispatch])
 
   const stake = useAppSelector((state) =>
     selectStakeByStakingProvider(state, stakingProviderAddress!)
diff --git a/src/pages/tBTC/Bridge/index.tsx b/src/pages/tBTC/Bridge/index.tsx
index f4fb63866..a1bbbcd70 100644
--- a/src/pages/tBTC/Bridge/index.tsx
+++ b/src/pages/tBTC/Bridge/index.tsx
@@ -9,11 +9,11 @@ import { ModalType } from "../../../enums"
 import { useTBTCTerms } from "../../../hooks/useTBTCTerms"
 import { useAppDispatch, useAppSelector } from "../../../hooks/store"
 import { selectBridgeActivity, tbtcSlice } from "../../../store/tbtc"
-import { useWeb3React } from "@web3-react/core"
 import { Outlet } from "react-router"
 import { MintPage } from "./Mint"
 import { UnmintPage } from "./Unmint"
 import { useIsActive } from "../../../hooks/useIsActive"
+import { useThreshold } from "../../../contexts/ThresholdContext"
 
 const gridTemplateAreas = {
   base: `
@@ -31,21 +31,22 @@ const TBTCBridge: PageComponent = (props) => {
   const isBridgeActivityFetching = useAppSelector(
     (state) => state.tbtc.bridgeActivity.isFetching
   )
-  const { account } = useIsActive()
+  const { account, chainId } = useIsActive()
+  const threshold = useThreshold()
 
   useEffect(() => {
     if (!hasUserResponded) openModal(ModalType.NewTBTCApp)
   }, [hasUserResponded])
 
   useEffect(() => {
-    if (!account) return
-
+    if (!account || !chainId) return
     dispatch(
       tbtcSlice.actions.requestBridgeActivity({
         depositor: account,
+        chainId: chainId,
       })
     )
-  }, [dispatch, account])
+  }, [dispatch, account, chainId, threshold.tbtc])
 
   return (
     <Grid
diff --git a/src/store/staking/effects.ts b/src/store/staking/effects.ts
index 732ca7664..d610f2bfd 100644
--- a/src/store/staking/effects.ts
+++ b/src/store/staking/effects.ts
@@ -1,5 +1,5 @@
 import { StakeData } from "../../types"
-import { AddressZero, isAddress, isAddressZero } from "../../web3/utils"
+import { isAddress, isAddressZero } from "../../web3/utils"
 import { AppListenerEffectAPI } from "../listener"
 import { selectStakeByStakingProvider } from "./selectors"
 import { requestStakeByStakingProvider, setStakes } from "./stakingSlice"
@@ -8,13 +8,19 @@ export const fetchStakeByStakingProviderEffect = async (
   actionCreator: ReturnType<typeof requestStakeByStakingProvider>,
   listenerApi: AppListenerEffectAPI
 ) => {
-  const { stakingProvider } = actionCreator.payload
+  const { stakingProvider, chainId } = actionCreator.payload
+  const {
+    config: {
+      ethereum: { chainId: ethereumChainId },
+    },
+  } = listenerApi.extra.threshold
 
   if (
     !listenerApi.extra.threshold.staking ||
     !stakingProvider ||
     !isAddress(stakingProvider) ||
-    isAddressZero(stakingProvider)
+    isAddressZero(stakingProvider) ||
+    chainId !== ethereumChainId
   )
     return
 
diff --git a/src/store/staking/stakingSlice.ts b/src/store/staking/stakingSlice.ts
index 89f347301..d790340cd 100644
--- a/src/store/staking/stakingSlice.ts
+++ b/src/store/staking/stakingSlice.ts
@@ -168,6 +168,7 @@ export const stakingSlice = createSlice({
 
 export const requestStakeByStakingProvider = createAction<{
   stakingProvider: string | undefined
+  chainId: string | number
 }>("staking/request-stake-by-staking-provider")
 
 export const {
diff --git a/src/store/tbtc/effects.ts b/src/store/tbtc/effects.ts
index a3dd600ac..452dfa544 100644
--- a/src/store/tbtc/effects.ts
+++ b/src/store/tbtc/effects.ts
@@ -20,8 +20,17 @@ export const fetchBridgeactivityEffect = async (
   action: ReturnType<typeof tbtcSlice.actions.requestBridgeActivity>,
   listenerApi: AppListenerEffectAPI
 ) => {
-  const { depositor } = action.payload
-  if (!isAddress(depositor) || isAddressZero(depositor)) return
+  const { depositor, chainId } = action.payload
+  const {
+    tbtc: { ethereumChainId },
+  } = listenerApi.extra.threshold
+
+  if (
+    !isAddress(depositor) ||
+    isAddressZero(depositor) ||
+    chainId !== ethereumChainId
+  )
+    return
 
   listenerApi.unsubscribe()
 
@@ -161,37 +170,30 @@ export const findUtxoEffect = async (
           }
         }
 
+        listenerApi.dispatch(
+          tbtcSlice.actions.updateState({
+            key: "utxo",
+            value: {
+              ...utxo,
+              transactionHash: utxo.transactionHash.toString(),
+              value: utxo.value.toString(),
+            },
+          })
+        )
+
         if (areAllDepositRevealed) {
           // All deposits are already revealed. Force start from step 1 and
           // remove deposit data.
-          removeDataForAccount(
-            depositor,
-            JSON.parse(
-              localStorage.getItem(key) || "{}"
-            ) as TBTCLocalStorageDepositData,
-            chainId as number
-          )
           listenerApi.dispatch(
             tbtcSlice.actions.updateState({
               key: "mintingStep",
-              value: MintingStep.ProvideData,
+              value: MintingStep.MintingSuccess,
             })
           )
         } else {
           // UTXO exists for a given Bitcoin deposit address and deposit is not
           // yet revealed. Redirect to step 3 to reveal the deposit and set
           // utxo.
-
-          listenerApi.dispatch(
-            tbtcSlice.actions.updateState({
-              key: "utxo",
-              value: {
-                ...utxo,
-                transactionHash: utxo.transactionHash.toString(),
-                value: utxo.value.toString(),
-              },
-            })
-          )
           listenerApi.dispatch(
             tbtcSlice.actions.updateState({
               key: "mintingStep",
diff --git a/src/store/tbtc/tbtcSlice.ts b/src/store/tbtc/tbtcSlice.ts
index c19b06ad3..ddcbcc288 100644
--- a/src/store/tbtc/tbtcSlice.ts
+++ b/src/store/tbtc/tbtcSlice.ts
@@ -35,7 +35,7 @@ export const tbtcSlice = createSlice({
     },
     requestBridgeActivity: (
       state,
-      action: PayloadAction<{ depositor: string }>
+      action: PayloadAction<{ depositor: string; chainId: string | number }>
     ) => {},
     fetchingBridgeActivity: (state) => {
       state.bridgeActivity.isFetching = true

From 6508d9d6c09235b3b1188fd4c6e7d2b0096dc574 Mon Sep 17 00:00:00 2001
From: evandrosaturnino <evandro.saturnino@gmail.com>
Date: Thu, 21 Nov 2024 03:59:46 -0300
Subject: [PATCH 20/46] Add readme file in networks folder

---
 src/networks/README.md | 139 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 139 insertions(+)
 create mode 100644 src/networks/README.md

diff --git a/src/networks/README.md b/src/networks/README.md
new file mode 100644
index 000000000..568c6372f
--- /dev/null
+++ b/src/networks/README.md
@@ -0,0 +1,139 @@
+Networks Configuration
+This folder contains utilities, enumerations, and types that define and manage network configurations used throughout the application. The primary purpose of this module is to expand or remove supported networks within the dApp. Changes to the network setup are managed through the enums and networks.ts files.
+
+Files Overview
+- enums/networks.ts: Contains the enumerations (enums) to categorize and label the supported networks.
+- utils/networks.ts: Defines and exports the list of supported networks with their properties.
+- types/networks.ts: Contains type definitions for network configurations.
+
+Network Enumeration Details
+
+TrmNetworksChainId: Represents key chain IDs for selected networks.
+
+```
+export enum TrmNetworksChainId {
+  ethereum = 1,
+  arbitrum = 42161,
+  base = 8453,
+}
+```
+
+SupportedChainIds: Enumerates the chain IDs of supported networks, including mainnets, testnets, and localhost.
+
+```
+export enum SupportedChainIds {
+  Ethereum = 1,
+  Sepolia = 11155111,
+  Localhost = 1337,
+  Arbitrum = 42161,
+  ArbitrumSepolia = 421614,
+  Base = 8453,
+  BaseSepolia = 84532,
+}
+```
+
+AlchemyName: Identifies the API identifiers (Alchemy) associated with each network.
+
+```
+export enum AlchemyName {
+  Ethereum = "eth",
+  Arbitrum = "arb",
+  Base = "base",
+}
+```
+
+NetworkType: Classifies networks based on whether they are Mainnet or Testnet.
+
+```
+export enum NetworkType {
+  Mainnet = "mainnet",
+  Testnet = "sepolia",
+}
+```
+
+Layer: Indicates whether the network operates at Layer 1 (L1) or Layer 2 (L2).
+
+```
+export enum Layer {
+  L1 = "L1",
+  L2 = "L2",
+}
+```
+
+Network List Definition
+
+The networks.ts file in utils defines an array of Network objects, where each network is described by its chain ID, name, layer, network type, and Alchemy identifier. This array serves as the central configuration point for supported networks.
+
+Example Network Configuration
+
+Below is an example network configuration, which includes key properties for each supported network:
+
+```
+export const networks: Network[] = [
+  {
+    chainId: SupportedChainIds.Ethereum,
+    name: "Ethereum",
+    layer: Layer.L1,
+    networkType: NetworkType.Mainnet,
+    alchemyName: AlchemyName.Ethereum,
+  },
+  {
+    chainId: SupportedChainIds.Sepolia,
+    name: "Sepolia",
+    layer: Layer.L1,
+    networkType: NetworkType.Testnet,
+    alchemyName: AlchemyName.Ethereum,
+  },
+  {
+    chainId: SupportedChainIds.Localhost,
+    name: "Localhost",
+    layer: Layer.L1,
+    networkType: NetworkType.Testnet,
+    alchemyName: "",
+  },
+  {
+    chainId: SupportedChainIds.Arbitrum,
+    name: "Arbitrum",
+    layer: Layer.L2,
+    networkType: NetworkType.Mainnet,
+    alchemyName: AlchemyName.Arbitrum,
+  },
+  {
+    chainId: SupportedChainIds.ArbitrumSepolia,
+    name: "ArbitrumSepolia",
+    layer: Layer.L2,
+    networkType: NetworkType.Testnet,
+    alchemyName: AlchemyName.Arbitrum,
+  },
+  {
+    chainId: SupportedChainIds.Base,
+    name: "Base",
+    layer: Layer.L2,
+    networkType: NetworkType.Mainnet,
+    alchemyName: AlchemyName.Base,
+  },
+  {
+    chainId: SupportedChainIds.BaseSepolia,
+    name: "BaseSepolia",
+    layer: Layer.L2,
+    networkType: NetworkType.Testnet,
+    alchemyName: AlchemyName.Base,
+  },
+]
+```
+
+Adding a New Network
+
+- Update the SupportedChainIds enum: Add the new chain ID with a unique identifier.
+- Add a corresponding entry in networks.ts: Create a new network object with the required properties such as name, layer, networkType, and alchemyName (if applicable).
+- Define the Alchemy name (if needed): If the new network is supported by Alchemy, add its API identifier to the AlchemyName enum.
+
+Removing a Network
+
+- Remove the chain ID from SupportedChainIds.
+- Delete the network entry from networks.ts.
+- Remove its corresponding entry from the AlchemyName enum if no longer needed.
+
+Conclusion
+
+The networks folder acts as the central configuration point for network management in the application. By modifying the enumerations and networks.ts, you can easily add, update, or remove supported networks within the app. Always verify your changes through appropriate testing to ensure the app's functionality remains consistent.

From c1b293ec0f14a9c2d5fff6eef72aa890c9d432af Mon Sep 17 00:00:00 2001
From: evandrosaturnino <evandro.saturnino@gmail.com>
Date: Thu, 21 Nov 2024 04:00:23 -0300
Subject: [PATCH 21/46] Improve minting flow for multiple networks

---
 src/components/tBTC/ExternalPool.tsx          | 28 +++---
 src/contexts/TokenContext.tsx                 | 92 ++++++++++---------
 src/hooks/tbtc/useFetchDepositDetails.ts      | 28 ++++--
 .../utils/getMainnetOrTestnetChainId.ts       |  4 +-
 src/threshold-ts/multicall/index.ts           |  5 +
 src/utils/percentage.ts                       |  1 +
 src/web3/hooks/useTBTCv2TokenContract.ts      |  5 +
 7 files changed, 97 insertions(+), 66 deletions(-)

diff --git a/src/components/tBTC/ExternalPool.tsx b/src/components/tBTC/ExternalPool.tsx
index 9ac4127ef..e390754ba 100644
--- a/src/components/tBTC/ExternalPool.tsx
+++ b/src/components/tBTC/ExternalPool.tsx
@@ -77,19 +77,21 @@ export const ExternalPool: FC<ExternalPoolProps> = ({
                     </HStack>
                   </Td>
                   <Td {...commonCellProps}>
-                    {!!apy && apy.length == 2 && (
-                      <BodyXs>{`${formatPercentage(
-                        apy[0],
-                        2,
-                        false,
-                        true
-                      )} -> ${formatPercentage(
-                        apy[1],
-                        2,
-                        false,
-                        true
-                      )} CRV`}</BodyXs>
-                    )}
+                    {!!apy &&
+                      apy.length === 2 &&
+                      apy.every((value) => value != null) && (
+                        <BodyXs>{`${formatPercentage(
+                          apy[0],
+                          2,
+                          false,
+                          true
+                        )} -> ${formatPercentage(
+                          apy[1],
+                          2,
+                          false,
+                          true
+                        )} CRV`}</BodyXs>
+                      )}
                   </Td>
                   <Td {...commonCellProps}>
                     {!!tvl && <BodyXs>${formatNumeral(tvl)}</BodyXs>}
diff --git a/src/contexts/TokenContext.tsx b/src/contexts/TokenContext.tsx
index 663485bf6..f50aa41e1 100644
--- a/src/contexts/TokenContext.tsx
+++ b/src/contexts/TokenContext.tsx
@@ -1,4 +1,4 @@
-import React, { createContext } from "react"
+import React, { createContext, useEffect } from "react"
 import { Contract } from "@ethersproject/contracts"
 import { AddressZero } from "@ethersproject/constants"
 import { useKeep } from "../web3/hooks/useKeep"
@@ -14,7 +14,7 @@ import { useFetchOwnerStakes } from "../hooks/useFetchOwnerStakes"
 import { useTBTCv2TokenContract } from "../web3/hooks/useTBTCv2TokenContract"
 import { featureFlags } from "../constants"
 import { useIsActive } from "../hooks/useIsActive"
-import { isL1Network } from "../networks/utils/connectedNetwork"
+import { isL1Network, isL2Network } from "../networks/utils/connectedNetwork"
 
 interface TokenContextState extends TokenState {
   contract: Contract | null
@@ -56,22 +56,27 @@ export const TokenContextProvider: React.FC = ({ children }) => {
     tbtcv2: tbtcv2Data,
   } = useTokenState()
 
-  const tokenContracts = [
-    keep.contract!,
-    nu.contract!,
-    t.contract!,
-    tbtcv2.contract!,
-  ]
+  const tokenContracts = {
+    [Token.Keep]: keep.contract!,
+    [Token.Nu]: nu.contract!,
+    [Token.T]: t.contract!,
+    [Token.TBTCV2]: tbtcv2.contract!,
+  }
 
   const fetchBalances = useTokensBalanceCall(
-    tokenContracts,
+    Object.values(tokenContracts),
+    isActive ? account! : AddressZero
+  )
+
+  const fetchtBTCBalance = useTokensBalanceCall(
+    [tbtcv2.contract!],
     isActive ? account! : AddressZero
   )
 
   //
   // SET T CONVERSION RATE FOR KEEP, NU
   //
-  React.useEffect(() => {
+  useEffect(() => {
     setTokenConversionRate(Token.Nu, nuConversion)
     setTokenConversionRate(Token.Keep, keepConversion)
   }, [nuConversion, keepConversion])
@@ -79,7 +84,7 @@ export const TokenContextProvider: React.FC = ({ children }) => {
   //
   // SET USD PRICE
   //
-  React.useEffect(() => {
+  useEffect(() => {
     for (const token in Token) {
       if (token) {
         // @ts-ignore
@@ -91,49 +96,46 @@ export const TokenContextProvider: React.FC = ({ children }) => {
   //
   // FETCH BALANCES ON WALLET LOAD OR NETWORK SWITCH
   //
-  React.useEffect(() => {
-    if (isActive && isL1Network(chainId)) {
-      setTokenLoading(Token.Keep, true)
-      setTokenLoading(Token.Nu, true)
-      setTokenLoading(Token.T, true)
-      setTokenLoading(Token.TBTCV2, true)
-      fetchBalances().then(
-        ([keepBalance = 0, nuBalance = 0, tBalance = 0, tbtcv2Balance = 0]) => {
-          setTokenBalance(Token.Keep, keepBalance.toString())
-          setTokenLoading(Token.Keep, false)
-          setTokenIsLoadedFromConnectedAccount(Token.Keep, true)
+  useEffect(() => {
+    const tokens = Object.keys(tokenContracts) as Token[]
 
-          setTokenBalance(Token.Nu, nuBalance.toString())
-          setTokenLoading(Token.Nu, false)
-          setTokenIsLoadedFromConnectedAccount(Token.Nu, true)
+    const updateTokenState = (
+      token: Token,
+      balance: number | string = 0,
+      isLoaded: boolean = false,
+      isLoading: boolean = false
+    ) => {
+      if (token === Token.TBTCV2 && !featureFlags.TBTC_V2) {
+        setTokenBalance(token, "0")
+      } else {
+        setTokenBalance(token, balance.toString())
+      }
+      setTokenLoading(token, isLoading)
+      setTokenIsLoadedFromConnectedAccount(token, isLoaded)
+    }
 
-          setTokenBalance(Token.T, tBalance.toString())
-          setTokenLoading(Token.T, false)
-          setTokenIsLoadedFromConnectedAccount(Token.T, true)
+    if (isActive && isL1Network(chainId)) {
+      tokens.forEach((token) => setTokenLoading(token, true))
+      fetchBalances().then(([keep, nu, t, tbtcv2]) => {
+        const balances = [keep, nu, t, tbtcv2]
 
-          if (featureFlags.TBTC_V2) {
-            setTokenBalance(Token.TBTCV2, tbtcv2Balance.toString())
-            setTokenLoading(Token.TBTCV2, false)
-            setTokenIsLoadedFromConnectedAccount(Token.TBTCV2, true)
-          }
+        balances.forEach((balance, index) =>
+          updateTokenState(tokens[index], balance, true)
+        )
+      })
+    } else if (isActive && isL2Network(chainId)) {
+      fetchtBTCBalance().then(([tbtcv2]) => {
+        if (featureFlags.TBTC_V2) {
+          updateTokenState(Token.TBTCV2, tbtcv2, true)
         }
-      )
+      })
     } else {
-      // set all token balances to 0 if the user disconnects the wallet
-      for (const token in Token) {
-        if (token) {
-          const key = token as keyof typeof Token
-          setTokenLoading(Token[key], true)
-          setTokenBalance(Token[key], 0)
-          setTokenLoading(Token[key], false)
-          setTokenIsLoadedFromConnectedAccount(Token[key], false)
-        }
-      }
+      tokens.forEach((token) => updateTokenState(token, 0))
     }
   }, [isActive, chainId, account])
 
   // fetch user stakes when they connect their wallet
-  React.useEffect(() => {
+  useEffect(() => {
     fetchOwnerStakes(account!)
   }, [fetchOwnerStakes, account])
 
diff --git a/src/hooks/tbtc/useFetchDepositDetails.ts b/src/hooks/tbtc/useFetchDepositDetails.ts
index 7668f04e8..1c8f39a33 100644
--- a/src/hooks/tbtc/useFetchDepositDetails.ts
+++ b/src/hooks/tbtc/useFetchDepositDetails.ts
@@ -22,7 +22,10 @@ export const useFetchDepositDetails = (depositKey: string | undefined) => {
   const [depositData, setDepositData] = useState<DepositData | undefined>()
 
   useEffect(() => {
+    let isMounted = true
     const fetch = async () => {
+      if (!isMounted) return
+
       setIsFetching(true)
       try {
         const { depositor } = (await threshold.tbtc.bridgeContract!.deposits(
@@ -31,7 +34,17 @@ export const useFetchDepositDetails = (depositKey: string | undefined) => {
           depositor: string
         }
         if (isEmptyOrZeroAddress(depositor)) {
-          throw new Error("Deposit not found...")
+          console.warn("Deposit not found, retrying in 10 seconds...")
+          setIsFetching(false)
+
+          // Retry fetching after 5 seconds because there can be
+          // some time delay due to relayer bot for L2 transactions
+          setTimeout(() => {
+            if (isMounted) {
+              fetch()
+            }
+          }, 5000)
+          return
         }
 
         const revealedDeposits = await threshold.tbtc.findAllRevealedDeposits(
@@ -44,7 +57,7 @@ export const useFetchDepositDetails = (depositKey: string | undefined) => {
 
         if (!deposit) {
           throw new Error(
-            "Could not find `DepositRevealed` event by given deposit key."
+            "Could not find DepositRevealed event by given deposit key."
           )
         }
 
@@ -91,14 +104,17 @@ export const useFetchDepositDetails = (depositKey: string | undefined) => {
         })
       } catch (error) {
         setError((error as Error).toString())
+      } finally {
+        setIsFetching(false)
       }
-      setIsFetching(false)
     }
 
-    if (depositKey && !threshold.tbtc.isCrossChain) {
-      fetch()
+    fetch()
+
+    return () => {
+      isMounted = false
     }
-  }, [depositKey, threshold, reverseTxHash])
+  }, [depositKey])
 
   return { isFetching, data: depositData, error }
 }
diff --git a/src/networks/utils/getMainnetOrTestnetChainId.ts b/src/networks/utils/getMainnetOrTestnetChainId.ts
index cda5009c9..0c67220fe 100644
--- a/src/networks/utils/getMainnetOrTestnetChainId.ts
+++ b/src/networks/utils/getMainnetOrTestnetChainId.ts
@@ -1,8 +1,8 @@
 import { SupportedChainIds } from "../enums/networks"
 import { isTestnetNetwork } from "../utils"
 
-export const getMainnetOrTestnetChainId = (chainId: number | string) => {
-  return isTestnetNetwork(chainId)
+export const getMainnetOrTestnetChainId = (chainId?: number | string) => {
+  return chainId && isTestnetNetwork(chainId)
     ? SupportedChainIds.Sepolia
     : SupportedChainIds.Ethereum
 }
diff --git a/src/threshold-ts/multicall/index.ts b/src/threshold-ts/multicall/index.ts
index c5528393c..65b0df661 100644
--- a/src/threshold-ts/multicall/index.ts
+++ b/src/threshold-ts/multicall/index.ts
@@ -43,6 +43,11 @@ export const MULTICALL_ABI = [
 export const MULTICALL_ADDRESSES = {
   [SupportedChainIds.Ethereum]: "0xeefba1e63905ef1d7acba5a8513c70307c1ce441",
   [SupportedChainIds.Sepolia]: "0xcA11bde05977b3631167028862bE2a173976CA11",
+  [SupportedChainIds.ArbitrumSepolia]:
+    "0xcA11bde05977b3631167028862bE2a173976CA11",
+  [SupportedChainIds.Arbitrum]: "0xcA11bde05977b3631167028862bE2a173976CA11",
+  [SupportedChainIds.Base]: "0xcA11bde05977b3631167028862bE2a173976CA11",
+  [SupportedChainIds.BaseSepolia]: "0xcA11bde05977b3631167028862bE2a173976CA11",
   [SupportedChainIds.Localhost]: process.env.REACT_APP_MULTICALL_ADDRESS,
 } as Record<number | string, string>
 
diff --git a/src/utils/percentage.ts b/src/utils/percentage.ts
index 13171725f..803963c86 100644
--- a/src/utils/percentage.ts
+++ b/src/utils/percentage.ts
@@ -24,6 +24,7 @@ export const formatPercentage = (
   displayLessThanGreaterThanSigns = false,
   displaySign = true
 ): string => {
+  if (!(typeof percentage === "number")) return ""
   if (percentage < 1 && percentage > 0 && displayLessThanGreaterThanSigns) {
     return `<1${displaySign ? "%" : ""}`
   } else if (
diff --git a/src/web3/hooks/useTBTCv2TokenContract.ts b/src/web3/hooks/useTBTCv2TokenContract.ts
index b261d4419..64e9f1ccb 100644
--- a/src/web3/hooks/useTBTCv2TokenContract.ts
+++ b/src/web3/hooks/useTBTCv2TokenContract.ts
@@ -8,6 +8,11 @@ export const TBTCV2_ADDRESSES = {
   [SupportedChainIds.Ethereum]: "0x18084fbA666a33d37592fA2633fD49a74DD93a88",
   // https://sepolia.etherscan.io/address/0x517f2982701695D4E52f1ECFBEf3ba31Df470161
   [SupportedChainIds.Sepolia]: "0x517f2982701695D4E52f1ECFBEf3ba31Df470161",
+  [SupportedChainIds.ArbitrumSepolia]:
+    "0xb8f31A249bcb45267d06b9E51252c4793B917Cd0",
+  [SupportedChainIds.Arbitrum]: "0x6c84a8f1c29108F47a79964b5Fe888D4f4D0dE40",
+  [SupportedChainIds.Base]: "0x236aa50979D5f3De3Bd1Eeb40E81137F22ab794b",
+  [SupportedChainIds.BaseSepolia]: "0xb8f31A249bcb45267d06b9E51252c4793B917Cd0",
   [SupportedChainIds.Localhost]: AddressZero,
 } as Record<number | string, string>
 

From 2ca26a43d5dced63bebe0c66ac70e0af1fb3ae5b Mon Sep 17 00:00:00 2001
From: evandrosaturnino <evandro.saturnino@gmail.com>
Date: Thu, 21 Nov 2024 04:11:11 -0300
Subject: [PATCH 22/46] Run prettier in networks readme file

---
 src/networks/README.md | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/networks/README.md b/src/networks/README.md
index 568c6372f..7ce950d69 100644
--- a/src/networks/README.md
+++ b/src/networks/README.md
@@ -2,6 +2,7 @@ Networks Configuration
 This folder contains utilities, enumerations, and types that define and manage network configurations used throughout the application. The primary purpose of this module is to expand or remove supported networks within the dApp. Changes to the network setup are managed through the enums and networks.ts files.
 
 Files Overview
+
 - enums/networks.ts: Contains the enumerations (enums) to categorize and label the supported networks.
 - utils/networks.ts: Defines and exports the list of supported networks with their properties.
 - types/networks.ts: Contains type definitions for network configurations.

From 4e47fcf178e21f418a29a9965359dd2b564dfae9 Mon Sep 17 00:00:00 2001
From: evandrosaturnino <evandro.saturnino@gmail.com>
Date: Mon, 25 Nov 2024 18:03:39 -0300
Subject: [PATCH 23/46] Update effects to validate connected network

---
 src/App.tsx                                   | 18 ++++++++++---
 src/components/tBTC/Links.tsx                 |  4 +++
 src/hooks/useFetchTvl.ts                      | 16 +++++++++---
 src/pages/Overview/Network/index.tsx          |  7 +++---
 .../Staking/AuthorizeStakingApps/index.tsx    |  1 -
 src/pages/Staking/StakeDetailsPage/index.tsx  |  5 +---
 src/pages/tBTC/Bridge/index.tsx               |  8 +++---
 src/store/staking-applications/effects.ts     | 19 ++++++++++++++
 src/store/staking/effects.ts                  | 13 +++++-----
 src/store/staking/stakingSlice.ts             |  2 --
 src/store/tbtc/effects.ts                     | 25 ++++++++++---------
 src/store/tbtc/tbtcSlice.ts                   |  2 +-
 12 files changed, 78 insertions(+), 42 deletions(-)

diff --git a/src/App.tsx b/src/App.tsx
index 47e269af7..1eb7a8ab9 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -63,6 +63,9 @@ import { useIsEmbed } from "./hooks/useIsEmbed"
 import TBTC from "./pages/tBTC"
 import { useDetectIfEmbed } from "./hooks/useDetectIfEmbed"
 import { useGoogleTagManager } from "./hooks/google-tag-manager"
+import { hexToNumber, isSameChainId } from "./networks/utils"
+import { walletConnected } from "./store/account"
+import { useIsActive } from "./hooks/useIsActive"
 
 const Web3EventHandlerComponent = () => {
   useSubscribeToVendingMachineContractEvents()
@@ -133,11 +136,20 @@ const useSubscribeToVendingMachineContractEvents = () => {
 
 const AppBody = () => {
   const dispatch = useDispatch()
-  const { connector, account } = useWeb3React()
+  const { connector, account, chainId } = useIsActive()
 
   useEffect(() => {
     const updateHandler = (update: ConnectorUpdate) => {
-      if (
+      // if chain is changed then just update the redux store for the wallet
+      // connection
+      if (update.chainId && !isSameChainId(update.chainId, chainId as number)) {
+        dispatch(
+          walletConnected({
+            address: account || "",
+            chainId: hexToNumber(update.chainId),
+          })
+        )
+      } else if (
         update.account &&
         !isSameETHAddress(update.account, account as string)
       ) {
@@ -164,7 +176,7 @@ const AppBody = () => {
       connector?.removeListener(ConnectorEvent.Update, updateHandler)
       connector?.removeListener(ConnectorEvent.Deactivate, deactivateHandler)
     }
-  }, [connector, dispatch, account])
+  }, [connector, dispatch, account, chainId])
 
   useEffect(() => {
     dispatch(fetchETHPriceUSD())
diff --git a/src/components/tBTC/Links.tsx b/src/components/tBTC/Links.tsx
index 9ed2d5c63..ed4400771 100644
--- a/src/components/tBTC/Links.tsx
+++ b/src/components/tBTC/Links.tsx
@@ -3,6 +3,7 @@ import { useTBTCBridgeContractAddress } from "../../hooks/useTBTCBridgeContractA
 import { ExplorerDataType } from "../../networks/enums/networks"
 import ViewInBlockExplorer from "../ViewInBlockExplorer"
 import { useTBTCTokenAddress } from "../../hooks/useTBTCTokenAddress"
+import { useIsActive } from "../../hooks/useIsActive"
 
 type Props = Omit<
   ComponentProps<typeof ViewInBlockExplorer>,
@@ -34,11 +35,14 @@ export const TBTCTokenContractLink: FC<Props> = ({
   ...props
 }) => {
   const address = useTBTCTokenAddress()
+  const { chainId } = useIsActive()
+
   return address ? (
     <ViewInBlockExplorer
       id={address}
       type={ExplorerDataType.ADDRESS}
       text={text}
+      ethereumNetworkChainId={chainId}
       {...props}
     />
   ) : (
diff --git a/src/hooks/useFetchTvl.ts b/src/hooks/useFetchTvl.ts
index 860dcaac0..020c5d2fb 100644
--- a/src/hooks/useFetchTvl.ts
+++ b/src/hooks/useFetchTvl.ts
@@ -1,4 +1,4 @@
-import { useState, useCallback, useMemo } from "react"
+import { useState, useCallback, useMemo, useRef, useEffect } from "react"
 import { BigNumberish } from "ethers"
 import { formatUnits } from "@ethersproject/units"
 import {
@@ -13,7 +13,6 @@ import { useToken } from "./useToken"
 import { Token } from "../enums"
 import { toUsdBalance } from "../utils/getUsdBalance"
 import { useIsActive } from "./useIsActive"
-import { isL1Network } from "../networks/utils"
 import { ContractCall } from "../threshold-ts/multicall"
 
 interface TvlRawData {
@@ -48,6 +47,14 @@ export const useFetchTvl = (): [
 ] => {
   const { chainId } = useIsActive()
   const [rawData, setRawData] = useState<TvlRawData>(initialState)
+  const isMountedRef = useRef(true)
+
+  useEffect(() => {
+    return () => {
+      isMountedRef.current = false
+    }
+  }, [])
+
   const {
     ecdsaTvl,
     tbtcv1Tvl: tbtcTvl,
@@ -120,7 +127,6 @@ export const useFetchTvl = (): [
   const fetchOnChainData = useMulticall(calls)
 
   const fetchTvlData = useCallback(async () => {
-    if (chainId && !isL1Network(chainId)) return initialState
     const chainData = await fetchOnChainData()
     if (chainData.length === 0) return initialState
 
@@ -131,7 +137,9 @@ export const useFetchTvl = (): [
       data[key] = result ? result.toString() : "0"
     })
 
-    setRawData(data)
+    if (isMountedRef.current) {
+      setRawData(data)
+    }
     return data
   }, [fetchOnChainData, chainId])
 
diff --git a/src/pages/Overview/Network/index.tsx b/src/pages/Overview/Network/index.tsx
index 0e71fb1ac..f80691c66 100644
--- a/src/pages/Overview/Network/index.tsx
+++ b/src/pages/Overview/Network/index.tsx
@@ -26,7 +26,7 @@ import { useThreshold } from "../../../contexts/ThresholdContext"
 const Network: PageComponent = () => {
   const [tvlInUSD, fetchtTvlData, tvlInTokenUnits] = useFetchTvl()
   const [deposits, isFetching, error] = useFetchRecentDeposits()
-  const { account, chainId } = useIsActive()
+  const { account } = useIsActive()
   const dispatch = useAppDispatch()
   const bridgeActivity = useAppSelector(selectBridgeActivity)
   const isBridgeActivityFetching = useAppSelector(
@@ -35,15 +35,14 @@ const Network: PageComponent = () => {
   const threshold = useThreshold()
 
   useEffect(() => {
-    if (!account || !chainId) return
+    if (!account) return
 
     dispatch(
       tbtcSlice.actions.requestBridgeActivity({
         depositor: account,
-        chainId: chainId,
       })
     )
-  }, [dispatch, account, threshold.tbtc])
+  }, [dispatch, account, threshold.tbtc.ethereumChainId])
 
   useEffect(() => {
     fetchtTvlData()
diff --git a/src/pages/Staking/AuthorizeStakingApps/index.tsx b/src/pages/Staking/AuthorizeStakingApps/index.tsx
index 4e42fc745..97c7196a6 100644
--- a/src/pages/Staking/AuthorizeStakingApps/index.tsx
+++ b/src/pages/Staking/AuthorizeStakingApps/index.tsx
@@ -82,7 +82,6 @@ const AuthorizeStakingAppsPage: FC = () => {
     dispatch(
       requestStakeByStakingProvider({
         stakingProvider: stakingProviderAddress,
-        chainId,
       })
     )
   }, [stakingProviderAddress, account, threshold.staking, dispatch])
diff --git a/src/pages/Staking/StakeDetailsPage/index.tsx b/src/pages/Staking/StakeDetailsPage/index.tsx
index 9daa685c1..cb52eb83f 100644
--- a/src/pages/Staking/StakeDetailsPage/index.tsx
+++ b/src/pages/Staking/StakeDetailsPage/index.tsx
@@ -38,7 +38,7 @@ import { useThreshold } from "../../../contexts/ThresholdContext"
 
 const StakeDetailsPage: FC = () => {
   const { stakingProviderAddress } = useParams()
-  const { account, active, chainId } = useWeb3React()
+  const { account, active } = useWeb3React()
   const threshold = useThreshold()
   const { openModal } = useModal()
   const navigate = useNavigate()
@@ -53,12 +53,9 @@ const StakeDetailsPage: FC = () => {
   }, [dispatch])
 
   useEffect(() => {
-    if (!chainId) return
-
     dispatch(
       requestStakeByStakingProvider({
         stakingProvider: stakingProviderAddress,
-        chainId,
       })
     )
   }, [stakingProviderAddress, account, threshold.staking, dispatch])
diff --git a/src/pages/tBTC/Bridge/index.tsx b/src/pages/tBTC/Bridge/index.tsx
index a1bbbcd70..d7ff72ab8 100644
--- a/src/pages/tBTC/Bridge/index.tsx
+++ b/src/pages/tBTC/Bridge/index.tsx
@@ -31,7 +31,8 @@ const TBTCBridge: PageComponent = (props) => {
   const isBridgeActivityFetching = useAppSelector(
     (state) => state.tbtc.bridgeActivity.isFetching
   )
-  const { account, chainId } = useIsActive()
+  const mintingStep = useAppSelector((state) => state.tbtc.mintingStep)
+  const { account } = useIsActive()
   const threshold = useThreshold()
 
   useEffect(() => {
@@ -39,14 +40,13 @@ const TBTCBridge: PageComponent = (props) => {
   }, [hasUserResponded])
 
   useEffect(() => {
-    if (!account || !chainId) return
+    if (!account) return
     dispatch(
       tbtcSlice.actions.requestBridgeActivity({
         depositor: account,
-        chainId: chainId,
       })
     )
-  }, [dispatch, account, chainId, threshold.tbtc])
+  }, [dispatch, account, mintingStep, threshold.tbtc.ethereumChainId])
 
   return (
     <Grid
diff --git a/src/store/staking-applications/effects.ts b/src/store/staking-applications/effects.ts
index 086030e45..113dd344b 100644
--- a/src/store/staking-applications/effects.ts
+++ b/src/store/staking-applications/effects.ts
@@ -24,11 +24,21 @@ import {
 import { isAddressZero } from "../../web3/utils"
 import { BigNumber } from "ethers"
 import { MAX_UINT64 } from "../../threshold-ts/utils"
+import { isSameChainId } from "../../networks/utils"
 
 export const getSupportedAppsEffect = async (
   action: ReturnType<typeof stakingApplicationsSlice.actions.getSupportedApps>,
   listenerApi: AppListenerEffectAPI
 ) => {
+  const { account } = listenerApi.getState()
+  const { config } = listenerApi.extra.threshold
+
+  if (
+    !account.chainId ||
+    !isSameChainId(account.chainId, config.ethereum.chainId)
+  )
+    return
+
   try {
     listenerApi.unsubscribe()
     listenerApi.dispatch(
@@ -124,6 +134,15 @@ export const getSupportedAppsStakingProvidersData = async (
   action: ReturnType<typeof setStakes>,
   listenerApi: AppListenerEffectAPI
 ) => {
+  const { account } = listenerApi.getState()
+  const { config } = listenerApi.extra.threshold
+
+  if (
+    !account.chainId ||
+    !isSameChainId(account.chainId, config.ethereum.chainId)
+  )
+    return
+
   try {
     const stakingProviders = selectStakingProviders(listenerApi.getState())
     if (
diff --git a/src/store/staking/effects.ts b/src/store/staking/effects.ts
index d610f2bfd..24b7597a9 100644
--- a/src/store/staking/effects.ts
+++ b/src/store/staking/effects.ts
@@ -1,3 +1,4 @@
+import { isSameChainId } from "../../networks/utils"
 import { StakeData } from "../../types"
 import { isAddress, isAddressZero } from "../../web3/utils"
 import { AppListenerEffectAPI } from "../listener"
@@ -8,19 +9,17 @@ export const fetchStakeByStakingProviderEffect = async (
   actionCreator: ReturnType<typeof requestStakeByStakingProvider>,
   listenerApi: AppListenerEffectAPI
 ) => {
-  const { stakingProvider, chainId } = actionCreator.payload
-  const {
-    config: {
-      ethereum: { chainId: ethereumChainId },
-    },
-  } = listenerApi.extra.threshold
+  const { account } = listenerApi.getState()
+  const { stakingProvider } = actionCreator.payload
+  const { config } = listenerApi.extra.threshold
 
   if (
     !listenerApi.extra.threshold.staking ||
     !stakingProvider ||
     !isAddress(stakingProvider) ||
     isAddressZero(stakingProvider) ||
-    chainId !== ethereumChainId
+    !account.chainId ||
+    !isSameChainId(account.chainId, config.ethereum.chainId)
   )
     return
 
diff --git a/src/store/staking/stakingSlice.ts b/src/store/staking/stakingSlice.ts
index d790340cd..3e5c2f71b 100644
--- a/src/store/staking/stakingSlice.ts
+++ b/src/store/staking/stakingSlice.ts
@@ -9,7 +9,6 @@ import {
   ToppedUpActionPayload,
 } from "../../types/staking"
 import { StakeType, TopUpType, UnstakeType } from "../../enums"
-import { AddressZero } from "../../web3/utils"
 import { UpdateStateActionPayload } from "../../types/state"
 import { startAppListening } from "../listener"
 import { fetchStakeByStakingProviderEffect } from "./effects"
@@ -168,7 +167,6 @@ export const stakingSlice = createSlice({
 
 export const requestStakeByStakingProvider = createAction<{
   stakingProvider: string | undefined
-  chainId: string | number
 }>("staking/request-stake-by-staking-provider")
 
 export const {
diff --git a/src/store/tbtc/effects.ts b/src/store/tbtc/effects.ts
index 452dfa544..7046f12f3 100644
--- a/src/store/tbtc/effects.ts
+++ b/src/store/tbtc/effects.ts
@@ -6,29 +6,28 @@ import {
 } from "../../threshold-ts/utils"
 import { MintingStep } from "../../types/tbtc"
 import { ONE_SEC_IN_MILISECONDS } from "../../utils/date"
-import {
-  key,
-  removeDataForAccount,
-  TBTCLocalStorageDepositData,
-} from "../../utils/tbtcLocalStorageData"
 import { isAddress, isAddressZero } from "../../web3/utils"
 import { AppListenerEffectAPI } from "../listener"
 import { tbtcSlice } from "./tbtcSlice"
-import { getChainIdToNetworkName, isL1Network } from "../../networks/utils"
+import {
+  getChainIdToNetworkName,
+  isL1Network,
+  isSameChainId,
+} from "../../networks/utils"
 
 export const fetchBridgeactivityEffect = async (
   action: ReturnType<typeof tbtcSlice.actions.requestBridgeActivity>,
   listenerApi: AppListenerEffectAPI
 ) => {
-  const { depositor, chainId } = action.payload
-  const {
-    tbtc: { ethereumChainId },
-  } = listenerApi.extra.threshold
+  const { account } = listenerApi.getState()
+  const { depositor } = action.payload
+  const { config } = listenerApi.extra.threshold
 
   if (
     !isAddress(depositor) ||
     isAddressZero(depositor) ||
-    chainId !== ethereumChainId
+    !account.chainId ||
+    !isSameChainId(account.chainId, config.ethereum.chainId)
   )
     return
 
@@ -37,7 +36,7 @@ export const fetchBridgeactivityEffect = async (
   listenerApi.dispatch(tbtcSlice.actions.fetchingBridgeActivity())
 
   try {
-    const data = await listenerApi.extra.threshold.tbtc.bridgeActivity(
+    const data = await listenerApi.extra.threshold.tbtc.getBridgeActivity(
       depositor
     )
     listenerApi.dispatch(tbtcSlice.actions.bridgeActivityFetched(data))
@@ -49,6 +48,8 @@ export const fetchBridgeactivityEffect = async (
         error: "Could not fetch bridge activity.",
       })
     )
+  } finally {
+    listenerApi.subscribe()
   }
 }
 
diff --git a/src/store/tbtc/tbtcSlice.ts b/src/store/tbtc/tbtcSlice.ts
index ddcbcc288..c19b06ad3 100644
--- a/src/store/tbtc/tbtcSlice.ts
+++ b/src/store/tbtc/tbtcSlice.ts
@@ -35,7 +35,7 @@ export const tbtcSlice = createSlice({
     },
     requestBridgeActivity: (
       state,
-      action: PayloadAction<{ depositor: string; chainId: string | number }>
+      action: PayloadAction<{ depositor: string }>
     ) => {},
     fetchingBridgeActivity: (state) => {
       state.bridgeActivity.isFetching = true

From 9ff1563842e756f6d0d3484cb33748fae9068a02 Mon Sep 17 00:00:00 2001
From: evandrosaturnino <evandro.saturnino@gmail.com>
Date: Mon, 25 Nov 2024 18:04:41 -0300
Subject: [PATCH 24/46] Add new step for crosschain minting process

---
 src/components/tBTC/BridgeActivity.tsx        |   3 +-
 src/hooks/tbtc/useFetchDepositDetails.ts      |  59 +-
 src/networks/utils/chainId.ts                 |  11 +
 src/pages/tBTC/Bridge/DepositDetails.tsx      |  44 +-
 .../tBTC/Bridge/Minting/MintingSuccess.tsx    |  19 +-
 .../Bridge/components/DepositDetailsStep.tsx  |  19 +-
 src/threshold-ts/tbtc/index.ts                | 281 +++++--
 .../ArbitrumL1BitcoinDepositor.json           | 737 ++++++++++++++++++
 .../ArbitrumL1BitcoinDepositor.json           | 737 ++++++++++++++++++
 .../BaseL1BitcoinDepositor.json               | 681 ++++++++++++++++
 src/threshold-ts/utils/constants.ts           |   2 +
 src/threshold-ts/utils/contract.ts            |  16 +-
 12 files changed, 2515 insertions(+), 94 deletions(-)
 create mode 100644 src/threshold-ts/tbtc/mainnet-artifacts/ArbitrumL1BitcoinDepositor.json
 create mode 100644 src/threshold-ts/tbtc/sepolia-artifacts/ArbitrumL1BitcoinDepositor.json
 create mode 100644 src/threshold-ts/tbtc/sepolia-artifacts/BaseL1BitcoinDepositor.json

diff --git a/src/components/tBTC/BridgeActivity.tsx b/src/components/tBTC/BridgeActivity.tsx
index 35dbd885f..2afda15ba 100644
--- a/src/components/tBTC/BridgeActivity.tsx
+++ b/src/components/tBTC/BridgeActivity.tsx
@@ -59,7 +59,8 @@ export const BridgeActivity: FC<BridgeActivityProps> = ({
   emptyState,
   children,
 }) => {
-  const isBridgeHistoryEmpty = data.length === 0
+  const { account } = useIsActive()
+  const isBridgeHistoryEmpty = data.length === 0 || !account
 
   return (
     <BridgeActivityContext.Provider
diff --git a/src/hooks/tbtc/useFetchDepositDetails.ts b/src/hooks/tbtc/useFetchDepositDetails.ts
index 1c8f39a33..ab21c1fa8 100644
--- a/src/hooks/tbtc/useFetchDepositDetails.ts
+++ b/src/hooks/tbtc/useFetchDepositDetails.ts
@@ -2,6 +2,7 @@ import { useEffect, useState } from "react"
 import { useThreshold } from "../../contexts/ThresholdContext"
 import { getContractPastEvents, isEmptyOrZeroAddress } from "../../web3/utils"
 import { reverseTxHash } from "../../threshold-ts/utils"
+import { DepositState } from "@keep-network/tbtc-v2.ts"
 
 export type DepositData = {
   depositRevealedTxHash: string
@@ -13,6 +14,8 @@ export type DepositData = {
   requiredConfirmations: number
   treasuryFee: string
   optimisticMintFee: string
+  isCrossChainDeposit: boolean
+  l1BitcoinDepositorDepositStatus?: DepositState
 }
 
 export const useFetchDepositDetails = (depositKey: string | undefined) => {
@@ -22,10 +25,9 @@ export const useFetchDepositDetails = (depositKey: string | undefined) => {
   const [depositData, setDepositData] = useState<DepositData | undefined>()
 
   useEffect(() => {
-    let isMounted = true
-    const fetch = async () => {
-      if (!isMounted) return
+    const isMounted = { current: true }
 
+    const fetch = async () => {
       setIsFetching(true)
       try {
         const { depositor } = (await threshold.tbtc.bridgeContract!.deposits(
@@ -33,17 +35,19 @@ export const useFetchDepositDetails = (depositKey: string | undefined) => {
         )) as {
           depositor: string
         }
+        if (!isMounted.current) return
+
         if (isEmptyOrZeroAddress(depositor)) {
           console.warn("Deposit not found, retrying in 10 seconds...")
           setIsFetching(false)
 
-          // Retry fetching after 5 seconds because there can be
+          // Retry fetching after 10 seconds because there can be
           // some time delay due to relayer bot for L2 transactions
           setTimeout(() => {
-            if (isMounted) {
+            if (isMounted.current) {
               fetch()
             }
-          }, 5000)
+          }, 10000)
           return
         }
 
@@ -61,6 +65,13 @@ export const useFetchDepositDetails = (depositKey: string | undefined) => {
           )
         }
 
+        const l1BitcoinDepositorDepositStatus = !!threshold.tbtc
+          .l1BitcoinDepositorContract
+          ? await threshold.tbtc.l1BitcoinDepositorContract.deposits(depositKey)
+          : DepositState.UNKNOWN
+
+        const isCrossChainDeposit = !!l1BitcoinDepositorDepositStatus
+
         const optimisticMintingRequestedEvents = await getContractPastEvents(
           threshold.tbtc.vaultContract!,
           {
@@ -89,30 +100,34 @@ export const useFetchDepositDetails = (depositKey: string | undefined) => {
         const { treasuryFee, optimisticMintFee, amountToMint } =
           await threshold.tbtc.getEstimatedDepositFees(deposit.amount)
 
-        setDepositData({
-          btcTxHash: btcTxHash.toString(),
-          depositRevealedTxHash: deposit.txHash,
-          amount: amountToMint,
-          treasuryFee,
-          optimisticMintFee,
-          optimisticMintingRequestedTxHash:
-            optimisticMintingRequestedEvents[0]?.transactionHash,
-          optimisticMintingFinalizedTxHash:
-            optimisticMintingFinalizedEvents[0]?.transactionHash,
-          requiredConfirmations,
-          confirmations,
-        })
+        if (isMounted.current) {
+          setDepositData({
+            btcTxHash: btcTxHash.toString(),
+            depositRevealedTxHash: deposit.txHash,
+            amount: amountToMint,
+            treasuryFee,
+            optimisticMintFee,
+            optimisticMintingRequestedTxHash:
+              optimisticMintingRequestedEvents[0]?.transactionHash,
+            optimisticMintingFinalizedTxHash:
+              optimisticMintingFinalizedEvents[0]?.transactionHash,
+            requiredConfirmations,
+            confirmations,
+            isCrossChainDeposit,
+            l1BitcoinDepositorDepositStatus,
+          })
+        }
       } catch (error) {
-        setError((error as Error).toString())
+        if (isMounted.current) setError((error as Error).toString())
       } finally {
-        setIsFetching(false)
+        if (isMounted.current) setIsFetching(false)
       }
     }
 
     fetch()
 
     return () => {
-      isMounted = false
+      isMounted.current = false
     }
   }, [depositKey])
 
diff --git a/src/networks/utils/chainId.ts b/src/networks/utils/chainId.ts
index 807fe3d4a..847c6b924 100644
--- a/src/networks/utils/chainId.ts
+++ b/src/networks/utils/chainId.ts
@@ -3,6 +3,17 @@ import { ethers } from "ethers"
 export const toHex = (value: string | number): string =>
   ethers.utils.hexValue(ethers.BigNumber.from(value))
 
+export const hexToNumber = (value: string | number): number => {
+  if (typeof value === "number") {
+    return value
+  }
+  if (typeof value === "string" && value.startsWith("0x")) {
+    return ethers.BigNumber.from(value).toNumber()
+  }
+
+  return parseInt(value)
+}
+
 export const isSameChainId = (
   chainId1: string | number,
   chainId2: string | number
diff --git a/src/pages/tBTC/Bridge/DepositDetails.tsx b/src/pages/tBTC/Bridge/DepositDetails.tsx
index 28e6e9beb..98dd9bb53 100644
--- a/src/pages/tBTC/Bridge/DepositDetails.tsx
+++ b/src/pages/tBTC/Bridge/DepositDetails.tsx
@@ -70,6 +70,8 @@ import { ExternalPool } from "../../../components/tBTC/ExternalPool"
 import { useFetchExternalPoolData } from "../../../hooks/useFetchExternalPoolData"
 import { TransactionDetailsAmountItem } from "../../../components/TransactionDetails"
 import { BridgeProcessDetailsPageSkeleton } from "./components/BridgeProcessDetailsPageSkeleton"
+import { DepositState } from "@keep-network/tbtc-v2.ts"
+import { chainIdToChainParameterName } from "../../../networks/utils"
 import { useIsActive } from "../../../hooks/useIsActive"
 
 export const DepositDetails: PageComponent = () => {
@@ -83,7 +85,6 @@ export const DepositDetails: PageComponent = () => {
     "curve",
     CurveFactoryPoolId.TBTC_WBTC_SBTC
   )
-  const { chainId } = useIsActive()
 
   const [mintingProgressStep, setMintingProgressStep] =
     useState<DepositDetailsTimelineStep>("bitcoin-confirmations")
@@ -115,6 +116,8 @@ export const DepositDetails: PageComponent = () => {
     data?.optimisticMintingRequestedTxHash
   const optimisticMintingFinalizedTxHash =
     data?.optimisticMintingFinalizedTxHash
+  const l1BitcoinDepositorDepositStatus = data?.l1BitcoinDepositorDepositStatus
+  const isCrossChainDeposit = !!data?.isCrossChainDeposit
   const thresholdNetworkFee = data?.treasuryFee
   const mintingFee = data?.optimisticMintFee
 
@@ -143,6 +146,8 @@ export const DepositDetails: PageComponent = () => {
         requiredConfirmations,
         optimisticMintingFinalizedTxHash,
         optimisticMintingRequestedTxHash,
+        l1BitcoinDepositorDepositStatus,
+        isCrossChainDeposit,
       })
     )
   }, [
@@ -150,6 +155,8 @@ export const DepositDetails: PageComponent = () => {
     requiredConfirmations,
     optimisticMintingFinalizedTxHash,
     optimisticMintingRequestedTxHash,
+    l1BitcoinDepositorDepositStatus,
+    isCrossChainDeposit,
     shouldStartFromFirstStep,
   ])
 
@@ -182,11 +189,13 @@ export const DepositDetails: PageComponent = () => {
           optimisticMintingRequestedTxHash ?? mintingRequestedTxHash,
         optimisticMintingFinalizedTxHash:
           optimisticMintingFinalizedTxHash ?? mintingFinalizedTxHash,
+        l1BitcoinDepositorDepositStatus,
         confirmations: confirmations || txConfirmations,
         requiredConfirmations: requiredConfirmations!,
         amount: amount,
         thresholdNetworkFee,
         mintingFee,
+        isCrossChainDeposit: !!data?.isCrossChainDeposit,
       }}
     >
       <BridgeProcessDetailsCard
@@ -331,13 +340,16 @@ DepositDetails.route = {
 const DepositDetailsPageContext = createContext<
   | (Pick<
       DepositData,
-      "optimisticMintingRequestedTxHash" | "optimisticMintingFinalizedTxHash"
+      | "optimisticMintingRequestedTxHash"
+      | "optimisticMintingFinalizedTxHash"
+      | "l1BitcoinDepositorDepositStatus"
     > & {
       btcTxHash?: string
       confirmations?: number
       requiredConfirmations?: number
       updateStep: (step: DepositDetailsTimelineStep) => void
       step: DepositDetailsTimelineStep
+      isCrossChainDeposit: boolean
       amount?: string
       mintingFee?: string
       thresholdNetworkFee?: string
@@ -464,9 +476,15 @@ const getMintingProgressStep = (
     requiredConfirmations,
     optimisticMintingRequestedTxHash,
     optimisticMintingFinalizedTxHash,
+    l1BitcoinDepositorDepositStatus,
+    isCrossChainDeposit,
   } = depositDetails
 
-  if (optimisticMintingFinalizedTxHash) return "completed"
+  if (
+    (!isCrossChainDeposit && optimisticMintingFinalizedTxHash) ||
+    l1BitcoinDepositorDepositStatus === DepositState.FINALIZED
+  )
+    return "completed"
 
   if (optimisticMintingRequestedTxHash) return "guardian-check"
 
@@ -492,12 +510,15 @@ const StepSwitcher: FC = () => {
     requiredConfirmations,
     optimisticMintingRequestedTxHash,
     optimisticMintingFinalizedTxHash,
+    l1BitcoinDepositorDepositStatus,
     btcTxHash,
     updateStep,
     amount,
     thresholdNetworkFee,
     mintingFee,
+    isCrossChainDeposit,
   } = useDepositDetailsPageContext()
+  const { chainId } = useIsActive()
 
   const onComplete = useCallback(() => {
     if (step === "completed") return
@@ -534,6 +555,8 @@ const StepSwitcher: FC = () => {
       return (
         <Step4
           txHash={optimisticMintingFinalizedTxHash}
+          l1BitcoinDepositorDepositStatus={l1BitcoinDepositorDepositStatus}
+          isCrossChainDeposit={isCrossChainDeposit}
           onComplete={onComplete}
         />
       )
@@ -543,9 +566,18 @@ const StepSwitcher: FC = () => {
           <BodyLg mt="4" fontSize="20px" lineHeight="24px">
             Success!
           </BodyLg>
-          <BodyMd mt="2">
-            Add the tBTC <TBTCTokenContractLink /> to your Ethereum wallet.
-          </BodyMd>
+
+          {isCrossChainDeposit ? (
+            <BodyMd mt="2">
+              Your tokens have been minted and bridged to the depositor wallet
+              on the {chainIdToChainParameterName(chainId)} network - This
+              action usually takes a few minutes to complete this process.
+            </BodyMd>
+          ) : (
+            <BodyMd mt="2">
+              Add the tBTC <TBTCTokenContractLink /> to your Ethereum wallet.
+            </BodyMd>
+          )}
           <Divider my="4" />
           <List spacing="2">
             <TransactionDetailsAmountItem
diff --git a/src/pages/tBTC/Bridge/Minting/MintingSuccess.tsx b/src/pages/tBTC/Bridge/Minting/MintingSuccess.tsx
index 37449f492..36c28e55d 100644
--- a/src/pages/tBTC/Bridge/Minting/MintingSuccess.tsx
+++ b/src/pages/tBTC/Bridge/Minting/MintingSuccess.tsx
@@ -4,27 +4,38 @@ import withOnlyConnectedWallet from "../../../../components/withOnlyConnectedWal
 import { useThreshold } from "../../../../contexts/ThresholdContext"
 import { Navigate } from "react-router"
 import { useRemoveDepositData } from "../../../../hooks/tbtc/useRemoveDepositData"
+import { useFetchDepositDetails } from "../../../../hooks/tbtc"
+import { BridgeProcessDetailsPageSkeleton } from "../components/BridgeProcessDetailsPageSkeleton"
 
 const MintingSuccessComponent: FC = () => {
   const threshold = useThreshold()
   const { utxo } = useTbtcState()
   const removeDepositData = useRemoveDepositData()
 
-  const btcDepositTxHash = utxo.transactionHash.toString()
+  const btcDepositTxHash = utxo?.transactionHash?.toString()
   const depositKey = threshold.tbtc.buildDepositKey(
     btcDepositTxHash,
     utxo.outputIndex,
     "big-endian"
   )
+  const { isFetching, data, error } = useFetchDepositDetails(depositKey)
 
   useEffect(() => {
-    removeDepositData()
-  }, [removeDepositData])
+    if (!isFetching && data && !error) {
+      removeDepositData()
+    }
+  }, [isFetching, data, error, removeDepositData])
+
+  if ((isFetching || !data) && !error) {
+    return <BridgeProcessDetailsPageSkeleton />
+  }
 
   return (
     <Navigate
       to={`/tBTC/mint/deposit/${depositKey}`}
-      state={{ shouldStartFromFirstStep: true }}
+      state={{
+        shouldStartFromFirstStep: !data?.optimisticMintingFinalizedTxHash,
+      }}
       replace={true}
     />
   )
diff --git a/src/pages/tBTC/Bridge/components/DepositDetailsStep.tsx b/src/pages/tBTC/Bridge/components/DepositDetailsStep.tsx
index b50787e0c..70e6c9c5e 100644
--- a/src/pages/tBTC/Bridge/components/DepositDetailsStep.tsx
+++ b/src/pages/tBTC/Bridge/components/DepositDetailsStep.tsx
@@ -14,6 +14,7 @@ import {
   MintingInitializedIcon,
 } from "./DepositDetailsStepIcons"
 import { BridgeProcessStepProps, BridgeProcessStep } from "./BridgeProcessStep"
+import { DepositState } from "@keep-network/tbtc-v2.ts"
 
 const BitcoinConfirmationsSummary: FC<{
   minConfirmationsNeeded?: number
@@ -52,6 +53,11 @@ type CommonStepProps = Pick<BridgeProcessStepProps, "onComplete"> & {
   txHash?: string
 }
 
+type CrossChainStepProps = CommonStepProps & {
+  l1BitcoinDepositorDepositStatus?: DepositState
+  isCrossChainDeposit: boolean
+}
+
 export const Step1: FC<
   { confirmations?: number; requiredConfirmations?: number } & Pick<
     BridgeProcessStepProps,
@@ -140,7 +146,16 @@ export const Step3: FC<CommonStepProps> = ({ txHash, onComplete }) => {
   )
 }
 
-export const Step4: FC<CommonStepProps> = ({ txHash, onComplete }) => {
+export const Step4: FC<CrossChainStepProps> = ({
+  txHash,
+  l1BitcoinDepositorDepositStatus,
+  isCrossChainDeposit,
+  onComplete,
+}) => {
+  const isComplete = isCrossChainDeposit
+    ? l1BitcoinDepositorDepositStatus === DepositState.FINALIZED
+    : true
+
   return (
     <BridgeProcessStep
       title="Minting in progress"
@@ -148,7 +163,7 @@ export const Step4: FC<CommonStepProps> = ({ txHash, onComplete }) => {
       chain="ethereum"
       txHash={txHash}
       progressBarColor="teal.500"
-      isCompleted={true}
+      isCompleted={isComplete}
       onComplete={onComplete}
       isIndeterminate
     >
diff --git a/src/threshold-ts/tbtc/index.ts b/src/threshold-ts/tbtc/index.ts
index 0dd98bdbf..742563e07 100644
--- a/src/threshold-ts/tbtc/index.ts
+++ b/src/threshold-ts/tbtc/index.ts
@@ -43,6 +43,8 @@ import {
   isSameETHAddress,
   isValidBtcAddress,
   ZERO,
+  ArtifactNameType,
+  L2_RELAYER_BOT_WALLET,
 } from "../utils"
 import {
   isL1Network,
@@ -90,6 +92,16 @@ export interface RevealedDepositEvent {
   blockNumber: number
 }
 
+export interface RevealedL2DepositEvent {
+  depositKey: string
+  l2DepositOwner: string
+  l1Sender: string
+  initialAmount: string
+  tbtcAmount: string
+  txHash: string
+  blockNumber: number
+}
+
 export interface RedemptionRequestedEvent {
   amount: string
   walletPublicKeyHash: string
@@ -195,11 +207,13 @@ export interface ITBTC {
    */
   readonly bitcoinNetwork: BitcoinNetwork
 
-  readonly bridgeContract: Contract | null
+  readonly bridgeContract: Contract
 
-  readonly vaultContract: Contract | null
+  readonly vaultContract: Contract
 
-  readonly tokenContract: Contract | null
+  readonly tokenContract: Contract
+
+  readonly l1BitcoinDepositorContract: Contract | undefined
 
   readonly deposit: Deposit | undefined
 
@@ -333,7 +347,7 @@ export interface ITBTC {
    * @param account Ethereum address.
    * @returns Bridge transaction history @see {@link BridgeActivity}.
    */
-  bridgeActivity(account: string): Promise<BridgeActivity[]>
+  getBridgeActivity(account: string): Promise<BridgeActivity[]>
 
   /**
    * Builds the deposit key required to refer a revealed deposit.
@@ -453,6 +467,7 @@ export class TBTC implements ITBTC {
   private _bridgeContract: Contract
   private _tbtcVaultContract: Contract
   private _tokenContract: Contract
+  private _l1BitcoinDepositorContract: Contract | undefined
   private _multicall: IMulticall
   private _bitcoinClient: BitcoinClient
   private _ethereumConfig: EthereumConfig
@@ -496,26 +511,27 @@ export class TBTC implements ITBTC {
     } = ethereumConfig
     this._isCrossChain = isL2Network(chainId)
 
-    const defaultOrConnectedChainId = this._isCrossChain
-      ? getMainnetOrTestnetChainId(chainId)
-      : chainId
-    const defaultOrConnectedProvider = this._isCrossChain
-      ? getThresholdLibProvider(defaultOrConnectedChainId)
-      : providerOrSigner
+    // This ensures that, if the user is connected to an L2 network, the TBTC
+    // contracts are connected to the corresponding Ethereum mainnet or testnet
+    // based on which type of network the user is connected to.
+    const mainnetOrTestnetEthereumChainId = getMainnetOrTestnetChainId(chainId)
+    const defaultOrConnectedProvider = getThresholdLibProvider(
+      mainnetOrTestnetEthereumChainId
+    )
 
     const tbtcVaultArtifact = getArtifact(
       "TBTCVault",
-      defaultOrConnectedChainId,
+      mainnetOrTestnetEthereumChainId,
       shouldUseTestnetDevelopmentContracts
     )
     const bridgeArtifact = getArtifact(
       "Bridge",
-      defaultOrConnectedChainId,
+      mainnetOrTestnetEthereumChainId,
       shouldUseTestnetDevelopmentContracts
     )
     const tbtcTokenArtifact = getArtifact(
       "TBTC",
-      defaultOrConnectedChainId,
+      mainnetOrTestnetEthereumChainId,
       shouldUseTestnetDevelopmentContracts
     )
 
@@ -540,9 +556,24 @@ export class TBTC implements ITBTC {
     this._multicall = new Multicall({
       ...ethereumConfig,
       providerOrSigner: defaultOrConnectedProvider,
-      chainId: defaultOrConnectedChainId,
+      chainId: mainnetOrTestnetEthereumChainId,
     })
 
+    if (this._isCrossChain) {
+      const networkName = getChainIdToNetworkName(chainId)
+      const l1BitcoinDepositorArtifact = getArtifact(
+        `${networkName}L1BitcoinDepositor` as ArtifactNameType,
+        mainnetOrTestnetEthereumChainId
+      )
+
+      this._l1BitcoinDepositorContract = getContract(
+        l1BitcoinDepositorArtifact.address,
+        l1BitcoinDepositorArtifact.abi,
+        defaultOrConnectedProvider,
+        account
+      )
+    }
+
     // @ts-ignore
     this._bitcoinClient =
       bitcoinConfig.client ??
@@ -653,6 +684,10 @@ export class TBTC implements ITBTC {
     return this._tokenContract
   }
 
+  get l1BitcoinDepositorContract() {
+    return this._l1BitcoinDepositorContract
+  }
+
   get isCrossChain(): boolean {
     return this._isCrossChain
   }
@@ -800,8 +835,15 @@ export class TBTC implements ITBTC {
   }
 
   getEstimatedDepositFees = async (depositAmount: string) => {
-    const { depositTreasuryFeeDivisor, optimisticMintingFeeDivisor } =
-      await this._getDepositFees()
+    const {
+      depositTreasuryFeeDivisor,
+      optimisticMintingFeeDivisor,
+      depositTxMaxFee,
+    } = await this._getDepositFees()
+
+    const crossChainTxFee = this.isCrossChain
+      ? BigNumber.from(depositTxMaxFee)
+      : ZERO
 
     // https://github.com/keep-network/tbtc-v2/blob/main/solidity/contracts/bridge/Deposit.sol#L258-L260
     const treasuryFee = BigNumber.from(depositTreasuryFeeDivisor).gt(0)
@@ -819,12 +861,14 @@ export class TBTC implements ITBTC {
       treasuryFee: treasuryFee.mul(this._satoshiMultiplier).toString(),
       optimisticMintFee: optimisticMintFee.toString(),
       amountToMint: amountToMint.toString(),
+      crossChainFee: crossChainTxFee.mul(this._satoshiMultiplier).toString(),
     }
   }
 
   private _getDepositFees = async (): Promise<{
     depositTreasuryFeeDivisor: BigNumber
     optimisticMintingFeeDivisor: BigNumber
+    depositTxMaxFee: BigNumber
   }> => {
     const calls: ContractCall[] = [
       {
@@ -847,6 +891,7 @@ export class TBTC implements ITBTC {
     const depositTreasuryFeeDivisor = BigNumber.from(
       depositParams.depositTreasuryFeeDivisor
     )
+    const depositTxMaxFee = BigNumber.from(depositParams.depositTxMaxFee)
     const optimisticMintingFeeDivisor = BigNumber.from(
       _optimisticMintingFeeDivisor[0]
     )
@@ -854,6 +899,7 @@ export class TBTC implements ITBTC {
     return {
       depositTreasuryFeeDivisor,
       optimisticMintingFeeDivisor,
+      depositTxMaxFee,
     }
   }
 
@@ -917,8 +963,8 @@ export class TBTC implements ITBTC {
     return 6
   }
 
-  bridgeActivity = async (account: string): Promise<BridgeActivity[]> => {
-    const depositActivities = await this._findDepositActivities(account)
+  getBridgeActivity = async (account: string): Promise<BridgeActivity[]> => {
+    const depositActivities = await this._findAllDepositActivities(account)
 
     const redemptionActivities: BridgeActivity[] =
       await this._findRedemptionActivities(account)
@@ -928,21 +974,75 @@ export class TBTC implements ITBTC {
       .sort((a, b) => b.blockNumber - a.blockNumber)
   }
 
-  private _findDepositActivities = async (
+  private _findAllDepositActivities = async (
+    depositor: string
+  ): Promise<BridgeActivity[]> => {
+    const l1DepositActivities = await this._findL1DepositActivities(depositor)
+
+    let l2DepositActivities: BridgeActivity[] = []
+    if (this.isCrossChain) {
+      l2DepositActivities = await this._findL2DepositActivities(depositor)
+    }
+
+    const depositActivities = [...l1DepositActivities, ...l2DepositActivities]
+    depositActivities.sort((a, b) => a.blockNumber - b.blockNumber)
+
+    return depositActivities
+  }
+
+  findAllRevealedDeposits = async (
+    depositor: string
+  ): Promise<RevealedDepositEvent[]> => {
+    const chainId = getMainnetOrTestnetChainId(this.ethereumChainId)
+
+    const bridgeArtifact = getArtifact(
+      "Bridge",
+      chainId,
+      this._ethereumConfig.shouldUseTestnetDevelopmentContracts
+    )
+    const deposits = await getContractPastEvents(this._bridgeContract!, {
+      fromBlock: bridgeArtifact.receipt.blockNumber,
+      filterParams: [null, null, depositor],
+      eventName: "DepositRevealed",
+    })
+
+    return deposits
+      .map((deposit) => {
+        const fundingTxHash = deposit.args?.fundingTxHash
+        const fundingOutputIndex = deposit.args?.fundingOutputIndex
+
+        const depositKey = this.buildDepositKey(
+          fundingTxHash,
+          fundingOutputIndex
+        )
+
+        return {
+          amount: deposit.args?.amount.toString(),
+          walletPublicKeyHash: deposit.args?.walletPubKeyHash,
+          fundingTxHash,
+          fundingOutputIndex,
+          depositKey,
+          txHash: deposit.transactionHash,
+          blockNumber: deposit.blockNumber,
+        }
+      })
+      .reverse()
+  }
+
+  private _findL1DepositActivities = async (
     depositor: string
   ): Promise<BridgeActivity[]> => {
-    // We can assume that all revealed deposits have `PENDING` status.
     const revealedDeposits = await this.findAllRevealedDeposits(depositor)
     const depositKeys = revealedDeposits.map((_) => _.depositKey)
 
+    const estimatedAmountToMintByDepositKey =
+      await this._calculateEstimatedAmountToMintForRevealedDeposits(depositKeys)
+
     const mintedDepositEvents = await this._findAllMintedDeposits(
       depositor,
       depositKeys
     )
 
-    const estimatedAmountToMintByDepositKey =
-      await this._calculateEstimatedAmountToMintForRevealedDeposits(depositKeys)
-
     const mintedDeposits = new Map(
       mintedDepositEvents.map((event) => [
         (event.args?.depositKey as BigNumber).toHexString(),
@@ -956,6 +1056,7 @@ export class TBTC implements ITBTC {
         event.transactionHash,
       ])
     )
+
     const mintedAmountByTxHash = new Map(
       await Promise.all(
         Array.from(mintedDeposits.values()).map((txHash) =>
@@ -986,47 +1087,117 @@ export class TBTC implements ITBTC {
         activityKey: depositKey,
         bridgeProcess: "mint",
         blockNumber,
-      }
+      } as BridgeActivity
     })
   }
 
-  findAllRevealedDeposits = async (
+  private _findL2DepositActivities = async (
     depositor: string
-  ): Promise<RevealedDepositEvent[]> => {
-    const chainId = getMainnetOrTestnetChainId(this.ethereumChainId)
+  ): Promise<BridgeActivity[]> => {
+    const l2DepositActivities: BridgeActivity[] = []
 
-    const bridgeArtifact = getArtifact(
-      "Bridge",
-      chainId,
-      this._ethereumConfig.shouldUseTestnetDevelopmentContracts
+    const l2AllRevealedDeposits = await this.findAllRevealedDeposits(
+      this.l1BitcoinDepositorContract?.address as string
     )
-    const deposits = await getContractPastEvents(this._bridgeContract!, {
-      fromBlock: bridgeArtifact.receipt.blockNumber,
-      filterParams: [null, null, depositor],
-      eventName: "DepositRevealed",
-    })
+    const l2DepositKeys = l2AllRevealedDeposits.map((_) => _.depositKey)
 
-    return deposits
-      .map((deposit) => {
-        const fundingTxHash = deposit.args?.fundingTxHash
-        const fundingOutputIndex = deposit.args?.fundingOutputIndex
+    const estimatedAmountToMintByDepositKey =
+      await this._calculateEstimatedAmountToMintForRevealedDeposits(
+        l2DepositKeys
+      )
 
-        const depositKey = this.buildDepositKey(
-          fundingTxHash,
-          fundingOutputIndex
-        )
+    const l2InitializedDepositsEvents =
+      await this._findAllInitializedL2Deposits(depositor)
+    const l2FinalizedDepositsEvents = await this._findAllFinalizedL2Deposits(
+      depositor
+    )
 
-        return {
-          amount: deposit.args?.amount.toString(),
-          walletPublicKeyHash: deposit.args?.walletPubKeyHash,
-          fundingTxHash,
-          fundingOutputIndex,
-          depositKey,
-          txHash: deposit.transactionHash,
-          blockNumber: deposit.blockNumber,
-        }
-      })
-      .reverse()
+    const l2InitializedDeposits = new Map(
+      l2InitializedDepositsEvents.map((event) => [
+        (event.args?.depositKey as BigNumber).toHexString(),
+        event.transactionHash,
+      ])
+    )
+
+    const l2FinalizedDeposits = new Map(
+      l2FinalizedDepositsEvents.map((event) => [
+        (event.args?.depositKey as BigNumber).toHexString(),
+        event.transactionHash,
+      ])
+    )
+
+    const l2FinalizedDepositAmountByTxHash = new Map<string, BigNumber>(
+      l2FinalizedDepositsEvents.map((event) => [
+        event.transactionHash,
+        event.args?.tbtcAmount as BigNumber,
+      ])
+    )
+
+    for (const l2Deposit of l2AllRevealedDeposits) {
+      const { depositKey, txHash: depositTxHash, blockNumber } = l2Deposit
+
+      if (!l2InitializedDeposits.has(depositKey)) continue
+
+      let status = BridgeActivityStatus.PENDING
+      let txHash = depositTxHash
+      let amount = estimatedAmountToMintByDepositKey.get(depositKey) ?? ZERO
+
+      if (l2FinalizedDeposits.has(depositKey)) {
+        status = BridgeActivityStatus.MINTED
+        txHash = l2FinalizedDeposits.get(depositKey)!
+        amount = l2FinalizedDepositAmountByTxHash.get(txHash)!
+      }
+
+      l2DepositActivities.push({
+        amount: amount.toString(),
+        txHash,
+        status,
+        activityKey: depositKey,
+        bridgeProcess: "mint",
+        blockNumber,
+      } as BridgeActivity)
+    }
+
+    return l2DepositActivities
+  }
+
+  private _findAllFinalizedL2Deposits = async (
+    depositor: string
+  ): Promise<ReturnType<typeof getContractPastEvents>> => {
+    const l2DepositOwner = depositor
+    const l1Sender = L2_RELAYER_BOT_WALLET
+
+    const l1BitcoinDepositorArtifact = getArtifact(
+      `${getChainIdToNetworkName(
+        this.ethereumChainId
+      )}L1BitcoinDepositor` as ArtifactNameType,
+      getMainnetOrTestnetChainId(this.ethereumChainId)
+    )
+    return await getContractPastEvents(this._l1BitcoinDepositorContract!, {
+      fromBlock: l1BitcoinDepositorArtifact.receipt.blockNumber,
+      filterParams: [null, l2DepositOwner, l1Sender],
+      eventName: "DepositFinalized",
+    })
+  }
+
+  private _findAllInitializedL2Deposits = async (
+    depositor: string
+  ): Promise<ReturnType<typeof getContractPastEvents>> => {
+    const l2DepositOwner = depositor
+    const l1Sender = L2_RELAYER_BOT_WALLET
+
+    const l1BitcoinDepositorArtifact = getArtifact(
+      `${getChainIdToNetworkName(
+        this.ethereumChainId
+      )}L1BitcoinDepositor` as ArtifactNameType,
+      getMainnetOrTestnetChainId(this.ethereumChainId)
+    )
+
+    return await getContractPastEvents(this._l1BitcoinDepositorContract!, {
+      fromBlock: l1BitcoinDepositorArtifact.receipt.blockNumber,
+      filterParams: [null, l2DepositOwner, l1Sender],
+      eventName: "DepositInitialized",
+    })
   }
 
   private _calculateEstimatedAmountToMintForRevealedDeposits = async (
diff --git a/src/threshold-ts/tbtc/mainnet-artifacts/ArbitrumL1BitcoinDepositor.json b/src/threshold-ts/tbtc/mainnet-artifacts/ArbitrumL1BitcoinDepositor.json
new file mode 100644
index 000000000..979987aff
--- /dev/null
+++ b/src/threshold-ts/tbtc/mainnet-artifacts/ArbitrumL1BitcoinDepositor.json
@@ -0,0 +1,737 @@
+{
+  "address": "0x75A6e4A7C8fAa162192FAD6C1F7A6d48992c619A",
+  "abi": [
+    {
+      "inputs": [],
+      "stateMutability": "nonpayable",
+      "type": "constructor"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "uint256",
+          "name": "depositKey",
+          "type": "uint256"
+        },
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "l2DepositOwner",
+          "type": "address"
+        },
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "l1Sender",
+          "type": "address"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "initialAmount",
+          "type": "uint256"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "tbtcAmount",
+          "type": "uint256"
+        }
+      ],
+      "name": "DepositFinalized",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "uint256",
+          "name": "depositKey",
+          "type": "uint256"
+        },
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "l2DepositOwner",
+          "type": "address"
+        },
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "l1Sender",
+          "type": "address"
+        }
+      ],
+      "name": "DepositInitialized",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "initializeDepositGasOffset",
+          "type": "uint256"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "finalizeDepositGasOffset",
+          "type": "uint256"
+        }
+      ],
+      "name": "GasOffsetParametersUpdated",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": false,
+          "internalType": "uint8",
+          "name": "version",
+          "type": "uint8"
+        }
+      ],
+      "name": "Initialized",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "l2FinalizeDepositGasLimit",
+          "type": "uint256"
+        }
+      ],
+      "name": "L2FinalizeDepositGasLimitUpdated",
+      "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": true,
+          "internalType": "address",
+          "name": "_address",
+          "type": "address"
+        },
+        {
+          "indexed": false,
+          "internalType": "bool",
+          "name": "authorization",
+          "type": "bool"
+        }
+      ],
+      "name": "ReimbursementAuthorizationUpdated",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": false,
+          "internalType": "address",
+          "name": "newReimbursementPool",
+          "type": "address"
+        }
+      ],
+      "name": "ReimbursementPoolUpdated",
+      "type": "event"
+    },
+    {
+      "inputs": [],
+      "name": "SATOSHI_MULTIPLIER",
+      "outputs": [
+        {
+          "internalType": "uint256",
+          "name": "",
+          "type": "uint256"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "_l2BitcoinDepositor",
+          "type": "address"
+        }
+      ],
+      "name": "attachL2BitcoinDepositor",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "bridge",
+      "outputs": [
+        {
+          "internalType": "contract IBridge",
+          "name": "",
+          "type": "address"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "uint256",
+          "name": "",
+          "type": "uint256"
+        }
+      ],
+      "name": "deposits",
+      "outputs": [
+        {
+          "internalType": "enum L1BitcoinDepositor.DepositState",
+          "name": "",
+          "type": "uint8"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "uint256",
+          "name": "depositKey",
+          "type": "uint256"
+        }
+      ],
+      "name": "finalizeDeposit",
+      "outputs": [],
+      "stateMutability": "payable",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "finalizeDepositGasOffset",
+      "outputs": [
+        {
+          "internalType": "uint256",
+          "name": "",
+          "type": "uint256"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "uint256",
+          "name": "",
+          "type": "uint256"
+        }
+      ],
+      "name": "gasReimbursements",
+      "outputs": [
+        {
+          "internalType": "address",
+          "name": "receiver",
+          "type": "address"
+        },
+        {
+          "internalType": "uint96",
+          "name": "gasSpent",
+          "type": "uint96"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "_tbtcBridge",
+          "type": "address"
+        },
+        {
+          "internalType": "address",
+          "name": "_tbtcVault",
+          "type": "address"
+        },
+        {
+          "internalType": "address",
+          "name": "_wormhole",
+          "type": "address"
+        },
+        {
+          "internalType": "address",
+          "name": "_wormholeRelayer",
+          "type": "address"
+        },
+        {
+          "internalType": "address",
+          "name": "_wormholeTokenBridge",
+          "type": "address"
+        },
+        {
+          "internalType": "address",
+          "name": "_l2WormholeGateway",
+          "type": "address"
+        },
+        {
+          "internalType": "uint16",
+          "name": "_l2ChainId",
+          "type": "uint16"
+        }
+      ],
+      "name": "initialize",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "components": [
+            {
+              "internalType": "bytes4",
+              "name": "version",
+              "type": "bytes4"
+            },
+            {
+              "internalType": "bytes",
+              "name": "inputVector",
+              "type": "bytes"
+            },
+            {
+              "internalType": "bytes",
+              "name": "outputVector",
+              "type": "bytes"
+            },
+            {
+              "internalType": "bytes4",
+              "name": "locktime",
+              "type": "bytes4"
+            }
+          ],
+          "internalType": "struct IBridgeTypes.BitcoinTxInfo",
+          "name": "fundingTx",
+          "type": "tuple"
+        },
+        {
+          "components": [
+            {
+              "internalType": "uint32",
+              "name": "fundingOutputIndex",
+              "type": "uint32"
+            },
+            {
+              "internalType": "bytes8",
+              "name": "blindingFactor",
+              "type": "bytes8"
+            },
+            {
+              "internalType": "bytes20",
+              "name": "walletPubKeyHash",
+              "type": "bytes20"
+            },
+            {
+              "internalType": "bytes20",
+              "name": "refundPubKeyHash",
+              "type": "bytes20"
+            },
+            {
+              "internalType": "bytes4",
+              "name": "refundLocktime",
+              "type": "bytes4"
+            },
+            {
+              "internalType": "address",
+              "name": "vault",
+              "type": "address"
+            }
+          ],
+          "internalType": "struct IBridgeTypes.DepositRevealInfo",
+          "name": "reveal",
+          "type": "tuple"
+        },
+        {
+          "internalType": "address",
+          "name": "l2DepositOwner",
+          "type": "address"
+        }
+      ],
+      "name": "initializeDeposit",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "initializeDepositGasOffset",
+      "outputs": [
+        {
+          "internalType": "uint256",
+          "name": "",
+          "type": "uint256"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "l2BitcoinDepositor",
+      "outputs": [
+        {
+          "internalType": "address",
+          "name": "",
+          "type": "address"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "l2ChainId",
+      "outputs": [
+        {
+          "internalType": "uint16",
+          "name": "",
+          "type": "uint16"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "l2FinalizeDepositGasLimit",
+      "outputs": [
+        {
+          "internalType": "uint256",
+          "name": "",
+          "type": "uint256"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "l2WormholeGateway",
+      "outputs": [
+        {
+          "internalType": "address",
+          "name": "",
+          "type": "address"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "owner",
+      "outputs": [
+        {
+          "internalType": "address",
+          "name": "",
+          "type": "address"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "quoteFinalizeDeposit",
+      "outputs": [
+        {
+          "internalType": "uint256",
+          "name": "cost",
+          "type": "uint256"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "",
+          "type": "address"
+        }
+      ],
+      "name": "reimbursementAuthorizations",
+      "outputs": [
+        {
+          "internalType": "bool",
+          "name": "",
+          "type": "bool"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "reimbursementPool",
+      "outputs": [
+        {
+          "internalType": "contract ReimbursementPool",
+          "name": "",
+          "type": "address"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "renounceOwnership",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "tbtcToken",
+      "outputs": [
+        {
+          "internalType": "contract IERC20Upgradeable",
+          "name": "",
+          "type": "address"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "tbtcVault",
+      "outputs": [
+        {
+          "internalType": "contract ITBTCVault",
+          "name": "",
+          "type": "address"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "newOwner",
+          "type": "address"
+        }
+      ],
+      "name": "transferOwnership",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "uint256",
+          "name": "_initializeDepositGasOffset",
+          "type": "uint256"
+        },
+        {
+          "internalType": "uint256",
+          "name": "_finalizeDepositGasOffset",
+          "type": "uint256"
+        }
+      ],
+      "name": "updateGasOffsetParameters",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "uint256",
+          "name": "_l2FinalizeDepositGasLimit",
+          "type": "uint256"
+        }
+      ],
+      "name": "updateL2FinalizeDepositGasLimit",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "_address",
+          "type": "address"
+        },
+        {
+          "internalType": "bool",
+          "name": "authorization",
+          "type": "bool"
+        }
+      ],
+      "name": "updateReimbursementAuthorization",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "contract ReimbursementPool",
+          "name": "_reimbursementPool",
+          "type": "address"
+        }
+      ],
+      "name": "updateReimbursementPool",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "wormhole",
+      "outputs": [
+        {
+          "internalType": "contract IWormhole",
+          "name": "",
+          "type": "address"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "wormholeRelayer",
+      "outputs": [
+        {
+          "internalType": "contract IWormholeRelayer",
+          "name": "",
+          "type": "address"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "wormholeTokenBridge",
+      "outputs": [
+        {
+          "internalType": "contract IWormholeTokenBridge",
+          "name": "",
+          "type": "address"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    }
+  ],
+  "transactionHash": "0x51e2686f22fd29a987096d0c27b9d1c7256e64cd37fd0a31a0bc316bbfc2b92b",
+  "receipt": {
+    "to": null,
+    "from": "0x949f0ADFDA95351829E49aEec0f99371A227572d",
+    "contractAddress": "0x75A6e4A7C8fAa162192FAD6C1F7A6d48992c619A",
+    "transactionIndex": 75,
+    "gasUsed": "866087",
+    "logsBloom": "0x00000000000000000000000080001000400000000000000000800000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000002000001400000000000000000000000000000000000020000000000000000000800000000800000000000000000000000400000000000000000000000000000000000000200000080000080040004800000000000000000000000000000000400000000000000000000000000000000000000000020000000000000000000040000000000000400100000000000000020000000000000000000000000000000000000000000000000000000000000000000",
+    "blockHash": "0xca28b9305b8bd5685b90d6dc17819fb68d14198e4812b0675e93aab068836f3f",
+    "transactionHash": "0x51e2686f22fd29a987096d0c27b9d1c7256e64cd37fd0a31a0bc316bbfc2b92b",
+    "logs": [
+      {
+        "transactionIndex": 75,
+        "blockNumber": 20632547,
+        "transactionHash": "0x51e2686f22fd29a987096d0c27b9d1c7256e64cd37fd0a31a0bc316bbfc2b92b",
+        "address": "0x75A6e4A7C8fAa162192FAD6C1F7A6d48992c619A",
+        "topics": [
+          "0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b",
+          "0x000000000000000000000000ff79fca71751a5a0c4487a1ace268d6cd2a64db1"
+        ],
+        "data": "0x",
+        "logIndex": 148,
+        "blockHash": "0xca28b9305b8bd5685b90d6dc17819fb68d14198e4812b0675e93aab068836f3f"
+      },
+      {
+        "transactionIndex": 75,
+        "blockNumber": 20632547,
+        "transactionHash": "0x51e2686f22fd29a987096d0c27b9d1c7256e64cd37fd0a31a0bc316bbfc2b92b",
+        "address": "0x75A6e4A7C8fAa162192FAD6C1F7A6d48992c619A",
+        "topics": [
+          "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0",
+          "0x0000000000000000000000000000000000000000000000000000000000000000",
+          "0x000000000000000000000000949f0adfda95351829e49aeec0f99371a227572d"
+        ],
+        "data": "0x",
+        "logIndex": 149,
+        "blockHash": "0xca28b9305b8bd5685b90d6dc17819fb68d14198e4812b0675e93aab068836f3f"
+      },
+      {
+        "transactionIndex": 75,
+        "blockNumber": 20632547,
+        "transactionHash": "0x51e2686f22fd29a987096d0c27b9d1c7256e64cd37fd0a31a0bc316bbfc2b92b",
+        "address": "0x75A6e4A7C8fAa162192FAD6C1F7A6d48992c619A",
+        "topics": [
+          "0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498"
+        ],
+        "data": "0x0000000000000000000000000000000000000000000000000000000000000001",
+        "logIndex": 150,
+        "blockHash": "0xca28b9305b8bd5685b90d6dc17819fb68d14198e4812b0675e93aab068836f3f"
+      },
+      {
+        "transactionIndex": 75,
+        "blockNumber": 20632547,
+        "transactionHash": "0x51e2686f22fd29a987096d0c27b9d1c7256e64cd37fd0a31a0bc316bbfc2b92b",
+        "address": "0x75A6e4A7C8fAa162192FAD6C1F7A6d48992c619A",
+        "topics": [
+          "0x7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f"
+        ],
+        "data": "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000037169570d846cc05d5848aaa30194d308b355638",
+        "logIndex": 151,
+        "blockHash": "0xca28b9305b8bd5685b90d6dc17819fb68d14198e4812b0675e93aab068836f3f"
+      }
+    ],
+    "blockNumber": 20632547,
+    "cumulativeGasUsed": "6345110",
+    "status": 1,
+    "byzantium": true
+  },
+  "numDeployments": 1,
+  "implementation": "0xFf79fca71751A5A0C4487a1aCE268d6cd2A64Db1",
+  "devdoc": "Contract deployed as upgradable proxy"
+}
diff --git a/src/threshold-ts/tbtc/sepolia-artifacts/ArbitrumL1BitcoinDepositor.json b/src/threshold-ts/tbtc/sepolia-artifacts/ArbitrumL1BitcoinDepositor.json
new file mode 100644
index 000000000..3d4267f71
--- /dev/null
+++ b/src/threshold-ts/tbtc/sepolia-artifacts/ArbitrumL1BitcoinDepositor.json
@@ -0,0 +1,737 @@
+{
+  "address": "0xD9B523fb879C63b00ef14e48C98f4e3398d3BA2D",
+  "abi": [
+    {
+      "inputs": [],
+      "stateMutability": "nonpayable",
+      "type": "constructor"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "uint256",
+          "name": "depositKey",
+          "type": "uint256"
+        },
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "l2DepositOwner",
+          "type": "address"
+        },
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "l1Sender",
+          "type": "address"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "initialAmount",
+          "type": "uint256"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "tbtcAmount",
+          "type": "uint256"
+        }
+      ],
+      "name": "DepositFinalized",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "uint256",
+          "name": "depositKey",
+          "type": "uint256"
+        },
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "l2DepositOwner",
+          "type": "address"
+        },
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "l1Sender",
+          "type": "address"
+        }
+      ],
+      "name": "DepositInitialized",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "initializeDepositGasOffset",
+          "type": "uint256"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "finalizeDepositGasOffset",
+          "type": "uint256"
+        }
+      ],
+      "name": "GasOffsetParametersUpdated",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": false,
+          "internalType": "uint8",
+          "name": "version",
+          "type": "uint8"
+        }
+      ],
+      "name": "Initialized",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "l2FinalizeDepositGasLimit",
+          "type": "uint256"
+        }
+      ],
+      "name": "L2FinalizeDepositGasLimitUpdated",
+      "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": true,
+          "internalType": "address",
+          "name": "_address",
+          "type": "address"
+        },
+        {
+          "indexed": false,
+          "internalType": "bool",
+          "name": "authorization",
+          "type": "bool"
+        }
+      ],
+      "name": "ReimbursementAuthorizationUpdated",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": false,
+          "internalType": "address",
+          "name": "newReimbursementPool",
+          "type": "address"
+        }
+      ],
+      "name": "ReimbursementPoolUpdated",
+      "type": "event"
+    },
+    {
+      "inputs": [],
+      "name": "SATOSHI_MULTIPLIER",
+      "outputs": [
+        {
+          "internalType": "uint256",
+          "name": "",
+          "type": "uint256"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "_l2BitcoinDepositor",
+          "type": "address"
+        }
+      ],
+      "name": "attachL2BitcoinDepositor",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "bridge",
+      "outputs": [
+        {
+          "internalType": "contract IBridge",
+          "name": "",
+          "type": "address"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "uint256",
+          "name": "",
+          "type": "uint256"
+        }
+      ],
+      "name": "deposits",
+      "outputs": [
+        {
+          "internalType": "enum L1BitcoinDepositor.DepositState",
+          "name": "",
+          "type": "uint8"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "uint256",
+          "name": "depositKey",
+          "type": "uint256"
+        }
+      ],
+      "name": "finalizeDeposit",
+      "outputs": [],
+      "stateMutability": "payable",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "finalizeDepositGasOffset",
+      "outputs": [
+        {
+          "internalType": "uint256",
+          "name": "",
+          "type": "uint256"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "uint256",
+          "name": "",
+          "type": "uint256"
+        }
+      ],
+      "name": "gasReimbursements",
+      "outputs": [
+        {
+          "internalType": "address",
+          "name": "receiver",
+          "type": "address"
+        },
+        {
+          "internalType": "uint96",
+          "name": "gasSpent",
+          "type": "uint96"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "_tbtcBridge",
+          "type": "address"
+        },
+        {
+          "internalType": "address",
+          "name": "_tbtcVault",
+          "type": "address"
+        },
+        {
+          "internalType": "address",
+          "name": "_wormhole",
+          "type": "address"
+        },
+        {
+          "internalType": "address",
+          "name": "_wormholeRelayer",
+          "type": "address"
+        },
+        {
+          "internalType": "address",
+          "name": "_wormholeTokenBridge",
+          "type": "address"
+        },
+        {
+          "internalType": "address",
+          "name": "_l2WormholeGateway",
+          "type": "address"
+        },
+        {
+          "internalType": "uint16",
+          "name": "_l2ChainId",
+          "type": "uint16"
+        }
+      ],
+      "name": "initialize",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "components": [
+            {
+              "internalType": "bytes4",
+              "name": "version",
+              "type": "bytes4"
+            },
+            {
+              "internalType": "bytes",
+              "name": "inputVector",
+              "type": "bytes"
+            },
+            {
+              "internalType": "bytes",
+              "name": "outputVector",
+              "type": "bytes"
+            },
+            {
+              "internalType": "bytes4",
+              "name": "locktime",
+              "type": "bytes4"
+            }
+          ],
+          "internalType": "struct IBridgeTypes.BitcoinTxInfo",
+          "name": "fundingTx",
+          "type": "tuple"
+        },
+        {
+          "components": [
+            {
+              "internalType": "uint32",
+              "name": "fundingOutputIndex",
+              "type": "uint32"
+            },
+            {
+              "internalType": "bytes8",
+              "name": "blindingFactor",
+              "type": "bytes8"
+            },
+            {
+              "internalType": "bytes20",
+              "name": "walletPubKeyHash",
+              "type": "bytes20"
+            },
+            {
+              "internalType": "bytes20",
+              "name": "refundPubKeyHash",
+              "type": "bytes20"
+            },
+            {
+              "internalType": "bytes4",
+              "name": "refundLocktime",
+              "type": "bytes4"
+            },
+            {
+              "internalType": "address",
+              "name": "vault",
+              "type": "address"
+            }
+          ],
+          "internalType": "struct IBridgeTypes.DepositRevealInfo",
+          "name": "reveal",
+          "type": "tuple"
+        },
+        {
+          "internalType": "address",
+          "name": "l2DepositOwner",
+          "type": "address"
+        }
+      ],
+      "name": "initializeDeposit",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "initializeDepositGasOffset",
+      "outputs": [
+        {
+          "internalType": "uint256",
+          "name": "",
+          "type": "uint256"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "l2BitcoinDepositor",
+      "outputs": [
+        {
+          "internalType": "address",
+          "name": "",
+          "type": "address"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "l2ChainId",
+      "outputs": [
+        {
+          "internalType": "uint16",
+          "name": "",
+          "type": "uint16"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "l2FinalizeDepositGasLimit",
+      "outputs": [
+        {
+          "internalType": "uint256",
+          "name": "",
+          "type": "uint256"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "l2WormholeGateway",
+      "outputs": [
+        {
+          "internalType": "address",
+          "name": "",
+          "type": "address"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "owner",
+      "outputs": [
+        {
+          "internalType": "address",
+          "name": "",
+          "type": "address"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "quoteFinalizeDeposit",
+      "outputs": [
+        {
+          "internalType": "uint256",
+          "name": "cost",
+          "type": "uint256"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "",
+          "type": "address"
+        }
+      ],
+      "name": "reimbursementAuthorizations",
+      "outputs": [
+        {
+          "internalType": "bool",
+          "name": "",
+          "type": "bool"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "reimbursementPool",
+      "outputs": [
+        {
+          "internalType": "contract ReimbursementPool",
+          "name": "",
+          "type": "address"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "renounceOwnership",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "tbtcToken",
+      "outputs": [
+        {
+          "internalType": "contract IERC20Upgradeable",
+          "name": "",
+          "type": "address"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "tbtcVault",
+      "outputs": [
+        {
+          "internalType": "contract ITBTCVault",
+          "name": "",
+          "type": "address"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "newOwner",
+          "type": "address"
+        }
+      ],
+      "name": "transferOwnership",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "uint256",
+          "name": "_initializeDepositGasOffset",
+          "type": "uint256"
+        },
+        {
+          "internalType": "uint256",
+          "name": "_finalizeDepositGasOffset",
+          "type": "uint256"
+        }
+      ],
+      "name": "updateGasOffsetParameters",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "uint256",
+          "name": "_l2FinalizeDepositGasLimit",
+          "type": "uint256"
+        }
+      ],
+      "name": "updateL2FinalizeDepositGasLimit",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "_address",
+          "type": "address"
+        },
+        {
+          "internalType": "bool",
+          "name": "authorization",
+          "type": "bool"
+        }
+      ],
+      "name": "updateReimbursementAuthorization",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "contract ReimbursementPool",
+          "name": "_reimbursementPool",
+          "type": "address"
+        }
+      ],
+      "name": "updateReimbursementPool",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "wormhole",
+      "outputs": [
+        {
+          "internalType": "contract IWormhole",
+          "name": "",
+          "type": "address"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "wormholeRelayer",
+      "outputs": [
+        {
+          "internalType": "contract IWormholeRelayer",
+          "name": "",
+          "type": "address"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "wormholeTokenBridge",
+      "outputs": [
+        {
+          "internalType": "contract IWormholeTokenBridge",
+          "name": "",
+          "type": "address"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    }
+  ],
+  "transactionHash": "0x2673ee5eb6ce999663c7897ab29bf0e0fda955dccc1f7d374968322d0148ade3",
+  "receipt": {
+    "to": null,
+    "from": "0x992500f42A48371c2c9f91EE6165ba8F9dfB1692",
+    "contractAddress": "0xD9B523fb879C63b00ef14e48C98f4e3398d3BA2D",
+    "transactionIndex": 46,
+    "gasUsed": "866135",
+    "logsBloom": "0x00000000000000000000000000000000400000000000000000800000000000000000000000000000000020000000000000000000000280000000080000000000000000000000000000000000000002000001000000000000000000000000000000000000020000000000000000000800000000800000000000000000000000400000000000000000000000000000000000000000000080000000000000800004000000000000000000000000000400000000000000000800000000000000000000000020010000000000000000040000000000000400000000000000000020000000000800000000000000000000000000000000000000000000000000000000",
+    "blockHash": "0x10400e7cfcdc42e3080b7580fcaa58ba8a8023b10d785a58db624c9a7fdc8b2f",
+    "transactionHash": "0x2673ee5eb6ce999663c7897ab29bf0e0fda955dccc1f7d374968322d0148ade3",
+    "logs": [
+      {
+        "transactionIndex": 46,
+        "blockNumber": 6281003,
+        "transactionHash": "0x2673ee5eb6ce999663c7897ab29bf0e0fda955dccc1f7d374968322d0148ade3",
+        "address": "0xD9B523fb879C63b00ef14e48C98f4e3398d3BA2D",
+        "topics": [
+          "0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b",
+          "0x000000000000000000000000f90292a39014033de50c81f651365cb6a1040bb6"
+        ],
+        "data": "0x",
+        "logIndex": 78,
+        "blockHash": "0x10400e7cfcdc42e3080b7580fcaa58ba8a8023b10d785a58db624c9a7fdc8b2f"
+      },
+      {
+        "transactionIndex": 46,
+        "blockNumber": 6281003,
+        "transactionHash": "0x2673ee5eb6ce999663c7897ab29bf0e0fda955dccc1f7d374968322d0148ade3",
+        "address": "0xD9B523fb879C63b00ef14e48C98f4e3398d3BA2D",
+        "topics": [
+          "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0",
+          "0x0000000000000000000000000000000000000000000000000000000000000000",
+          "0x000000000000000000000000992500f42a48371c2c9f91ee6165ba8f9dfb1692"
+        ],
+        "data": "0x",
+        "logIndex": 79,
+        "blockHash": "0x10400e7cfcdc42e3080b7580fcaa58ba8a8023b10d785a58db624c9a7fdc8b2f"
+      },
+      {
+        "transactionIndex": 46,
+        "blockNumber": 6281003,
+        "transactionHash": "0x2673ee5eb6ce999663c7897ab29bf0e0fda955dccc1f7d374968322d0148ade3",
+        "address": "0xD9B523fb879C63b00ef14e48C98f4e3398d3BA2D",
+        "topics": [
+          "0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498"
+        ],
+        "data": "0x0000000000000000000000000000000000000000000000000000000000000001",
+        "logIndex": 80,
+        "blockHash": "0x10400e7cfcdc42e3080b7580fcaa58ba8a8023b10d785a58db624c9a7fdc8b2f"
+      },
+      {
+        "transactionIndex": 46,
+        "blockNumber": 6281003,
+        "transactionHash": "0x2673ee5eb6ce999663c7897ab29bf0e0fda955dccc1f7d374968322d0148ade3",
+        "address": "0xD9B523fb879C63b00ef14e48C98f4e3398d3BA2D",
+        "topics": [
+          "0x7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f"
+        ],
+        "data": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000008d58747ef805317270ff7f8e51a8018d3488b17b",
+        "logIndex": 81,
+        "blockHash": "0x10400e7cfcdc42e3080b7580fcaa58ba8a8023b10d785a58db624c9a7fdc8b2f"
+      }
+    ],
+    "blockNumber": 6281003,
+    "cumulativeGasUsed": "11146181",
+    "status": 1,
+    "byzantium": true
+  },
+  "numDeployments": 1,
+  "implementation": "0xf90292a39014033DE50c81f651365cB6A1040Bb6",
+  "devdoc": "Contract deployed as upgradable proxy"
+}
diff --git a/src/threshold-ts/tbtc/sepolia-artifacts/BaseL1BitcoinDepositor.json b/src/threshold-ts/tbtc/sepolia-artifacts/BaseL1BitcoinDepositor.json
new file mode 100644
index 000000000..fbd7dddff
--- /dev/null
+++ b/src/threshold-ts/tbtc/sepolia-artifacts/BaseL1BitcoinDepositor.json
@@ -0,0 +1,681 @@
+{
+  "address": "0x0c5e36731008f4AFC1AF5Da2C4D5E07eE4a3EB69",
+  "abi": [
+    {
+      "inputs": [],
+      "stateMutability": "nonpayable",
+      "type": "constructor"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "uint256",
+          "name": "depositKey",
+          "type": "uint256"
+        },
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "l2DepositOwner",
+          "type": "address"
+        },
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "l1Sender",
+          "type": "address"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "initialAmount",
+          "type": "uint256"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "tbtcAmount",
+          "type": "uint256"
+        }
+      ],
+      "name": "DepositFinalized",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "uint256",
+          "name": "depositKey",
+          "type": "uint256"
+        },
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "l2DepositOwner",
+          "type": "address"
+        },
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "l1Sender",
+          "type": "address"
+        }
+      ],
+      "name": "DepositInitialized",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "initializeDepositGasOffset",
+          "type": "uint256"
+        },
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "finalizeDepositGasOffset",
+          "type": "uint256"
+        }
+      ],
+      "name": "GasOffsetParametersUpdated",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": false,
+          "internalType": "uint8",
+          "name": "version",
+          "type": "uint8"
+        }
+      ],
+      "name": "Initialized",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": false,
+          "internalType": "uint256",
+          "name": "l2FinalizeDepositGasLimit",
+          "type": "uint256"
+        }
+      ],
+      "name": "L2FinalizeDepositGasLimitUpdated",
+      "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": "address",
+          "name": "newReimbursementPool",
+          "type": "address"
+        }
+      ],
+      "name": "ReimbursementPoolUpdated",
+      "type": "event"
+    },
+    {
+      "inputs": [],
+      "name": "SATOSHI_MULTIPLIER",
+      "outputs": [
+        {
+          "internalType": "uint256",
+          "name": "",
+          "type": "uint256"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "_l2BitcoinDepositor",
+          "type": "address"
+        }
+      ],
+      "name": "attachL2BitcoinDepositor",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "bridge",
+      "outputs": [
+        {
+          "internalType": "contract IBridge",
+          "name": "",
+          "type": "address"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "uint256",
+          "name": "",
+          "type": "uint256"
+        }
+      ],
+      "name": "deposits",
+      "outputs": [
+        {
+          "internalType": "enum L1BitcoinDepositor.DepositState",
+          "name": "",
+          "type": "uint8"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "uint256",
+          "name": "depositKey",
+          "type": "uint256"
+        }
+      ],
+      "name": "finalizeDeposit",
+      "outputs": [],
+      "stateMutability": "payable",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "finalizeDepositGasOffset",
+      "outputs": [
+        {
+          "internalType": "uint256",
+          "name": "",
+          "type": "uint256"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "uint256",
+          "name": "",
+          "type": "uint256"
+        }
+      ],
+      "name": "gasReimbursements",
+      "outputs": [
+        {
+          "internalType": "address",
+          "name": "receiver",
+          "type": "address"
+        },
+        {
+          "internalType": "uint96",
+          "name": "gasSpent",
+          "type": "uint96"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "_tbtcBridge",
+          "type": "address"
+        },
+        {
+          "internalType": "address",
+          "name": "_tbtcVault",
+          "type": "address"
+        },
+        {
+          "internalType": "address",
+          "name": "_wormhole",
+          "type": "address"
+        },
+        {
+          "internalType": "address",
+          "name": "_wormholeRelayer",
+          "type": "address"
+        },
+        {
+          "internalType": "address",
+          "name": "_wormholeTokenBridge",
+          "type": "address"
+        },
+        {
+          "internalType": "address",
+          "name": "_l2WormholeGateway",
+          "type": "address"
+        },
+        {
+          "internalType": "uint16",
+          "name": "_l2ChainId",
+          "type": "uint16"
+        }
+      ],
+      "name": "initialize",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "components": [
+            {
+              "internalType": "bytes4",
+              "name": "version",
+              "type": "bytes4"
+            },
+            {
+              "internalType": "bytes",
+              "name": "inputVector",
+              "type": "bytes"
+            },
+            {
+              "internalType": "bytes",
+              "name": "outputVector",
+              "type": "bytes"
+            },
+            {
+              "internalType": "bytes4",
+              "name": "locktime",
+              "type": "bytes4"
+            }
+          ],
+          "internalType": "struct IBridgeTypes.BitcoinTxInfo",
+          "name": "fundingTx",
+          "type": "tuple"
+        },
+        {
+          "components": [
+            {
+              "internalType": "uint32",
+              "name": "fundingOutputIndex",
+              "type": "uint32"
+            },
+            {
+              "internalType": "bytes8",
+              "name": "blindingFactor",
+              "type": "bytes8"
+            },
+            {
+              "internalType": "bytes20",
+              "name": "walletPubKeyHash",
+              "type": "bytes20"
+            },
+            {
+              "internalType": "bytes20",
+              "name": "refundPubKeyHash",
+              "type": "bytes20"
+            },
+            {
+              "internalType": "bytes4",
+              "name": "refundLocktime",
+              "type": "bytes4"
+            },
+            {
+              "internalType": "address",
+              "name": "vault",
+              "type": "address"
+            }
+          ],
+          "internalType": "struct IBridgeTypes.DepositRevealInfo",
+          "name": "reveal",
+          "type": "tuple"
+        },
+        {
+          "internalType": "address",
+          "name": "l2DepositOwner",
+          "type": "address"
+        }
+      ],
+      "name": "initializeDeposit",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "initializeDepositGasOffset",
+      "outputs": [
+        {
+          "internalType": "uint256",
+          "name": "",
+          "type": "uint256"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "l2BitcoinDepositor",
+      "outputs": [
+        {
+          "internalType": "address",
+          "name": "",
+          "type": "address"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "l2ChainId",
+      "outputs": [
+        {
+          "internalType": "uint16",
+          "name": "",
+          "type": "uint16"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "l2FinalizeDepositGasLimit",
+      "outputs": [
+        {
+          "internalType": "uint256",
+          "name": "",
+          "type": "uint256"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "l2WormholeGateway",
+      "outputs": [
+        {
+          "internalType": "address",
+          "name": "",
+          "type": "address"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "owner",
+      "outputs": [
+        {
+          "internalType": "address",
+          "name": "",
+          "type": "address"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "quoteFinalizeDeposit",
+      "outputs": [
+        {
+          "internalType": "uint256",
+          "name": "cost",
+          "type": "uint256"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "reimbursementPool",
+      "outputs": [
+        {
+          "internalType": "contract ReimbursementPool",
+          "name": "",
+          "type": "address"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "renounceOwnership",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "tbtcToken",
+      "outputs": [
+        {
+          "internalType": "contract IERC20Upgradeable",
+          "name": "",
+          "type": "address"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "tbtcVault",
+      "outputs": [
+        {
+          "internalType": "contract ITBTCVault",
+          "name": "",
+          "type": "address"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "newOwner",
+          "type": "address"
+        }
+      ],
+      "name": "transferOwnership",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "uint256",
+          "name": "_initializeDepositGasOffset",
+          "type": "uint256"
+        },
+        {
+          "internalType": "uint256",
+          "name": "_finalizeDepositGasOffset",
+          "type": "uint256"
+        }
+      ],
+      "name": "updateGasOffsetParameters",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "uint256",
+          "name": "_l2FinalizeDepositGasLimit",
+          "type": "uint256"
+        }
+      ],
+      "name": "updateL2FinalizeDepositGasLimit",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "contract ReimbursementPool",
+          "name": "_reimbursementPool",
+          "type": "address"
+        }
+      ],
+      "name": "updateReimbursementPool",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "wormhole",
+      "outputs": [
+        {
+          "internalType": "contract IWormhole",
+          "name": "",
+          "type": "address"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "wormholeRelayer",
+      "outputs": [
+        {
+          "internalType": "contract IWormholeRelayer",
+          "name": "",
+          "type": "address"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "wormholeTokenBridge",
+      "outputs": [
+        {
+          "internalType": "contract IWormholeTokenBridge",
+          "name": "",
+          "type": "address"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    }
+  ],
+  "transactionHash": "0x5a405183332f623649fcf19f8506cf2582882d5dc2b05582e0066388ef122229",
+  "receipt": {
+    "to": null,
+    "from": "0x68ad60CC5e8f3B7cC53beaB321cf0e6036962dBc",
+    "contractAddress": "0x0c5e36731008f4AFC1AF5Da2C4D5E07eE4a3EB69",
+    "transactionIndex": 94,
+    "gasUsed": "887851",
+    "logsBloom": "0x00000000000000000000000000000000400000000000000400800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000202000001000000000000000000000000000000000000020000000000000000000800000000800000000000000008000000400000000200000000000000000000000000000040000080000000000000800000000000000000000000000000000400000000000000000000000000000010000000000020000000000000200020040000000000000400000000000000000020000000000000000000000000000000100000000000000000000000000000000000",
+    "blockHash": "0x9d4a08d2b6fd26df76447aa1b5e0054686b1d462dc12be4d271dca1299060a2c",
+    "transactionHash": "0x5a405183332f623649fcf19f8506cf2582882d5dc2b05582e0066388ef122229",
+    "logs": [
+      {
+        "transactionIndex": 94,
+        "blockNumber": 5441536,
+        "transactionHash": "0x5a405183332f623649fcf19f8506cf2582882d5dc2b05582e0066388ef122229",
+        "address": "0x0c5e36731008f4AFC1AF5Da2C4D5E07eE4a3EB69",
+        "topics": [
+          "0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b",
+          "0x000000000000000000000000720cb49a8b3c03e199075544f7f1f4d772dd6d06"
+        ],
+        "data": "0x",
+        "logIndex": 75,
+        "blockHash": "0x9d4a08d2b6fd26df76447aa1b5e0054686b1d462dc12be4d271dca1299060a2c"
+      },
+      {
+        "transactionIndex": 94,
+        "blockNumber": 5441536,
+        "transactionHash": "0x5a405183332f623649fcf19f8506cf2582882d5dc2b05582e0066388ef122229",
+        "address": "0x0c5e36731008f4AFC1AF5Da2C4D5E07eE4a3EB69",
+        "topics": [
+          "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0",
+          "0x0000000000000000000000000000000000000000000000000000000000000000",
+          "0x00000000000000000000000068ad60cc5e8f3b7cc53beab321cf0e6036962dbc"
+        ],
+        "data": "0x",
+        "logIndex": 76,
+        "blockHash": "0x9d4a08d2b6fd26df76447aa1b5e0054686b1d462dc12be4d271dca1299060a2c"
+      },
+      {
+        "transactionIndex": 94,
+        "blockNumber": 5441536,
+        "transactionHash": "0x5a405183332f623649fcf19f8506cf2582882d5dc2b05582e0066388ef122229",
+        "address": "0x0c5e36731008f4AFC1AF5Da2C4D5E07eE4a3EB69",
+        "topics": [
+          "0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498"
+        ],
+        "data": "0x0000000000000000000000000000000000000000000000000000000000000001",
+        "logIndex": 77,
+        "blockHash": "0x9d4a08d2b6fd26df76447aa1b5e0054686b1d462dc12be4d271dca1299060a2c"
+      },
+      {
+        "transactionIndex": 94,
+        "blockNumber": 5441536,
+        "transactionHash": "0x5a405183332f623649fcf19f8506cf2582882d5dc2b05582e0066388ef122229",
+        "address": "0x0c5e36731008f4AFC1AF5Da2C4D5E07eE4a3EB69",
+        "topics": [
+          "0x7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f"
+        ],
+        "data": "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000dd0007713cb99564b7835fd628a1718e8f9f9785",
+        "logIndex": 78,
+        "blockHash": "0x9d4a08d2b6fd26df76447aa1b5e0054686b1d462dc12be4d271dca1299060a2c"
+      }
+    ],
+    "blockNumber": 5441536,
+    "cumulativeGasUsed": "8903785",
+    "status": 1,
+    "byzantium": true
+  },
+  "numDeployments": 1,
+  "implementation": "0x720Cb49A8b3c03E199075544F7f1F4d772Dd6d06",
+  "devdoc": "Contract deployed as upgradable proxy"
+}
diff --git a/src/threshold-ts/utils/constants.ts b/src/threshold-ts/utils/constants.ts
index 46483a3c6..bae4a9819 100644
--- a/src/threshold-ts/utils/constants.ts
+++ b/src/threshold-ts/utils/constants.ts
@@ -2,5 +2,7 @@ import { BigNumber, constants } from "ethers"
 
 export const MAX_UINT64 = BigNumber.from("18446744073709551615") // 2^64 - 1
 export const ZERO = constants.Zero
+export const L2_RELAYER_BOT_WALLET =
+  "0x45332EEE9b495b1dda896FD53112eaaCC10b2c19"
 
 export const STANDARD_ERC20_DECIMALS = 18
diff --git a/src/threshold-ts/utils/contract.ts b/src/threshold-ts/utils/contract.ts
index ced42a34c..03e94eac8 100644
--- a/src/threshold-ts/utils/contract.ts
+++ b/src/threshold-ts/utils/contract.ts
@@ -11,6 +11,7 @@ import { AddressZero, getAddress, isAddressZero } from "./address"
 import { LedgerLiveSigner } from "../../utils/ledger"
 import { SupportedChainIds } from "../../networks/enums/networks"
 
+import ArbitrumL1BitcoinDepositorArtifactMainnet from "../tbtc/mainnet-artifacts/ArbitrumL1BitcoinDepositor.json"
 import BridgeArtifactMainnet from "@keep-network/tbtc-v2.ts/src/lib/ethereum/artifacts/mainnet/Bridge.json"
 import NuCypherStakingEscrowMainnet from "../staking/mainnet-artifacts/NuCypherStakingEscrow.json"
 import NuCypherTokenMainnet from "../tokens/mainnet-artifacts/NuCypherToken.json"
@@ -24,6 +25,8 @@ import RandomBeaconArtifactMainnet from "../tbtc/mainnet-artifacts/RandomBeacon.
 import LegacyKeepStakingArtifactMainnet from "../staking/mainnet-artifacts/LegacyKeepStaking.json"
 import TacoRegistryArtifactMainnet from "../mas/mainnet-artifacts/TacoRegistry.json"
 
+import ArbitrumL1BitcoinDepositorArtifactSepolia from "../tbtc/sepolia-artifacts/ArbitrumL1BitcoinDepositor.json"
+import BaseL1BitcoinDepositorArtifactSepolia from "../tbtc/sepolia-artifacts/BaseL1BitcoinDepositor.json"
 import BridgeArtifactSepolia from "@keep-network/tbtc-v2.ts/src/lib/ethereum/artifacts/sepolia/Bridge.json"
 import NuCypherStakingEscrowSepolia from "../staking/sepolia-artifacts/NuCypherStakingEscrow.json"
 import NuCypherTokenSepolia from "../tokens/sepolia-artifacts/NuCypherToken.json"
@@ -50,7 +53,7 @@ import RandomBeaconArtifactDappDevelopmentSepolia from "../tbtc/dapp-development
 import LegacyKeepStakingArtifactDappDevelopmentSepolia from "../staking/dapp-development-sepolia-artifacts/LegacyKeepStaking.json"
 import TacoRegistryArtifactDappDevelopmentSepolia from "../mas/dapp-development-sepolia-artifacts/TacoRegistry.json"
 
-type ArtifactNameType =
+export type ArtifactNameType =
   | "TacoRegistry"
   | "LegacyKeepStaking"
   | "RandomBeacon"
@@ -63,6 +66,8 @@ type ArtifactNameType =
   | "VendingMachineKeep"
   | "VendingMachineNuCypher"
   | "WalletRegistry"
+  | "ArbitrumL1BitcoinDepositor"
+  | "BaseL1BitcoinDepositor"
 type ArtifactType = {
   address: string
   abi: ContractInterface
@@ -70,6 +75,7 @@ type ArtifactType = {
 }
 
 const mainnetArtifacts = new Map<ArtifactNameType, ArtifactType>([
+  ["ArbitrumL1BitcoinDepositor", ArbitrumL1BitcoinDepositorArtifactMainnet],
   ["TacoRegistry", TacoRegistryArtifactMainnet],
   ["LegacyKeepStaking", LegacyKeepStakingArtifactMainnet],
   ["RandomBeacon", RandomBeaconArtifactMainnet],
@@ -83,7 +89,9 @@ const mainnetArtifacts = new Map<ArtifactNameType, ArtifactType>([
   ["VendingMachineKeep", VendingMachineKeepMainnet],
   ["VendingMachineNuCypher", VendingMachineNuCypherMainnet],
 ])
-const testnetArtifacts = new Map<ArtifactNameType, ArtifactType>([
+const sepoliaArtifacts = new Map<ArtifactNameType, ArtifactType>([
+  ["ArbitrumL1BitcoinDepositor", ArbitrumL1BitcoinDepositorArtifactSepolia],
+  ["BaseL1BitcoinDepositor", BaseL1BitcoinDepositorArtifactSepolia],
   ["TacoRegistry", TacoRegistryArtifactSepolia],
   ["LegacyKeepStaking", LegacyKeepStakingArtifactSepolia],
   ["RandomBeacon", RandomBeaconArtifactSepolia],
@@ -190,10 +198,10 @@ export const getArtifact = (
     case SupportedChainIds.Sepolia:
       const artifacts = shouldUseTestnetDevelopmentContracts
         ? testnetDevelopmentArtifacts
-        : testnetArtifacts
+        : sepoliaArtifacts
       return artifacts.get(artifactName)!
     default:
-      throw new Error("Can't get tbtc-v2 artifacts!")
+      throw new Error("Can't get the contract artifact!")
   }
 }
 

From 28f2de6469bd2caccfd68e1fd304e4831d575a16 Mon Sep 17 00:00:00 2001
From: evandrosaturnino <evandro.saturnino@gmail.com>
Date: Tue, 26 Nov 2024 22:17:42 -0300
Subject: [PATCH 25/46] Update contracts connection by chain ID

---
 src/components/Forms/HelperErrorText.tsx      |  26 ++-
 .../Modal/ClaimingRewards/index.tsx           |   3 +
 .../Modal/ConfirmStakingParams/index.tsx      |   8 +-
 .../InititateDeauthorization.tsx              |  41 ++--
 .../index.tsx                                 |  15 +-
 .../index.tsx                                 |  12 +-
 .../AuthorizeStakingApps.tsx                  |   8 +-
 .../ConfirmDeauthorization.tsx                |  18 +-
 .../IncreaseAuthorization.tsx                 |  23 +-
 src/components/Modal/SubmitStake/index.tsx    |   4 +-
 .../Modal/TACoCommitmentModal/index.tsx       |   5 +-
 .../Modal/TopupTModal/LegacyTopUpModal.tsx    |   3 +
 .../Modal/TopupTModal/TopUpTModal.tsx         |   4 +-
 src/components/Modal/UnstakeTModal/Step2.tsx  |   4 +-
 .../Modal/UpgradeToTModal/TransactionIdle.tsx |   7 +-
 .../Modal/tBTC/InitiateUnminting.tsx          |   1 +
 src/components/Navbar/index.tsx               |   4 +-
 src/components/SubmitTxButton.tsx             |  11 +-
 .../UpgradeCard/UpgradeCardTemplate.tsx       |  11 +-
 src/components/tBTC/BridgeActivity.tsx        |   2 +-
 .../useRequestEthereumAccount.ts              |  10 +-
 src/hooks/staking-applications/index.ts       |   2 +-
 .../useAuthorizeMultipleAppsTransaction.ts    |   2 +-
 .../useBondOperatorTransaction.ts             |   5 +-
 ...> useConfirmDeauthorizationTransaction.ts} |   8 +-
 .../useIncreaseAuthorizationTransaction.ts    |   6 +-
 .../useInitiateDeauthorization.ts             |   6 +-
 .../useRegisterOperatorTransaction.ts         |   6 +-
 .../useStakingAppContract.ts                  |  11 +-
 .../useStakingApplicationAddress.ts           |   9 +-
 .../useUpdateOperatorStatus.tsx               |   6 +-
 src/networks/constants/networks.ts            |   5 -
 src/networks/enums/networks.ts                |   4 -
 src/networks/utils/index.ts                   |   1 -
 .../utils/validateL2TransactionType.ts        |  11 -
 .../index.tsx                                 |  19 +-
 src/pages/tBTC/Bridge/MintUnmintNav.tsx       |  13 +-
 .../tBTC/Bridge/Minting/InitiateMinting.tsx   |   5 +-
 src/pages/tBTC/Bridge/Minting/ProvideData.tsx |   7 +-
 src/pages/tBTC/Bridge/ResumeDeposit.tsx       |  14 +-
 src/pages/tBTC/Bridge/Unmint.tsx              |   2 +
 src/store/account/effects.ts                  |  15 +-
 src/store/staking-applications/effects.ts     |  44 ++--
 src/store/staking/effects.ts                  |   2 +-
 src/store/tbtc/effects.ts                     |   6 +-
 src/threshold-ts/applications/index.ts        |   4 +-
 src/threshold-ts/index.ts                     |  35 +--
 src/threshold-ts/mas/index.ts                 | 147 +++++++-----
 src/threshold-ts/staking/index.ts             | 209 ++++++++++++------
 src/threshold-ts/tbtc/index.ts                | 122 ++++++----
 src/threshold-ts/utils/contract.ts            | 121 +++++-----
 src/threshold-ts/vending-machine/index.ts     |  25 ++-
 src/utils/getEnvVariable.ts                   |   7 +-
 src/utils/getStakingAppLabel.ts               |  14 +-
 src/web3/hooks/useNu.ts                       |  10 +-
 src/web3/hooks/useNuStakingEscrowContract.ts  |   2 +-
 56 files changed, 676 insertions(+), 449 deletions(-)
 rename src/hooks/staking-applications/{useConfirmDeatuhorizationTransaction.ts => useConfirmDeauthorizationTransaction.ts} (63%)
 delete mode 100644 src/networks/utils/validateL2TransactionType.ts

diff --git a/src/components/Forms/HelperErrorText.tsx b/src/components/Forms/HelperErrorText.tsx
index 817b0818c..3d090740e 100644
--- a/src/components/Forms/HelperErrorText.tsx
+++ b/src/components/Forms/HelperErrorText.tsx
@@ -1,20 +1,26 @@
 import { FC } from "react"
-import { FormErrorMessage, FormHelperText } from "@threshold-network/components"
+import {
+  Box,
+  FormErrorMessage,
+  FormHelperText,
+} from "@threshold-network/components"
 
 const HelperErrorText: FC<{
   errorMsgText?: string | JSX.Element
   hasError?: boolean
   helperText?: string | JSX.Element
 }> = ({ errorMsgText, helperText, hasError }) => {
-  if (hasError) {
-    return (
-      <FormErrorMessage>
-        {errorMsgText || "Please enter a valid value"}
-      </FormErrorMessage>
-    )
-  }
-
-  return helperText ? <FormHelperText>{helperText}</FormHelperText> : null
+  return (
+    <Box mt={2} maxWidth="100%" overflow="hidden" textOverflow="ellipsis">
+      {hasError ? (
+        <FormErrorMessage>
+          {errorMsgText || "Please enter a valid value"}
+        </FormErrorMessage>
+      ) : helperText ? (
+        <FormHelperText>{helperText}</FormHelperText>
+      ) : null}
+    </Box>
+  )
 }
 
 export default HelperErrorText
diff --git a/src/components/Modal/ClaimingRewards/index.tsx b/src/components/Modal/ClaimingRewards/index.tsx
index 9d7c504df..5e2ca0c48 100644
--- a/src/components/Modal/ClaimingRewards/index.tsx
+++ b/src/components/Modal/ClaimingRewards/index.tsx
@@ -34,6 +34,7 @@ import { useModal } from "../../../hooks/useModal"
 import { ModalType } from "../../../enums"
 import ModalCloseButton from "../ModalCloseButton"
 import SubmitTxButton from "../../SubmitTxButton"
+import { useMerkleDropContract } from "../../../web3/hooks/useMerkleDropContract"
 
 const ClaimingRewardsBase: FC<
   BaseModalProps & {
@@ -44,6 +45,7 @@ const ClaimingRewardsBase: FC<
   const { openModal } = useModal()
   const beneficiaryRewards = useSelector(selectAccumulatedRewardsPerBeneficiary)
   const rewards = useSelector(selectInterimRewards)
+  const merkleDropContract = useMerkleDropContract()
 
   const onClaimSuccess = useCallback<OnSuccessCallback>(
     (receipt) => {
@@ -99,6 +101,7 @@ const ClaimingRewardsBase: FC<
           Cancel
         </Button>
         <SubmitTxButton
+          isDisabled={!merkleDropContract}
           onSubmit={() => {
             claim(Object.keys(rewards))
           }}
diff --git a/src/components/Modal/ConfirmStakingParams/index.tsx b/src/components/Modal/ConfirmStakingParams/index.tsx
index e5149aeb9..6426d96a8 100644
--- a/src/components/Modal/ConfirmStakingParams/index.tsx
+++ b/src/components/Modal/ConfirmStakingParams/index.tsx
@@ -30,6 +30,7 @@ import { useStakeTransaction } from "../../../web3/hooks/useStakeTransaction"
 import { formatTokenAmount } from "../../../utils/formatAmount"
 import ModalCloseButton from "../ModalCloseButton"
 import SubmitTxButton from "../../SubmitTxButton"
+import { useTStakingContract } from "../../../web3/hooks"
 
 const ConfirmStakingParamsModal: FC<
   BaseModalProps & { stakeAmount: string }
@@ -40,6 +41,7 @@ const ConfirmStakingParamsModal: FC<
   const { account } = useWeb3React()
   const { updateState } = useStakingState()
   const checkIfProviderUsed = useCheckDuplicateProviderAddress()
+  const stakingContract = useTStakingContract()
 
   // stake transaction, opens success modal on success callback
   // not needed once MAS is launched
@@ -129,7 +131,11 @@ const ConfirmStakingParamsModal: FC<
         <Button onClick={closeModal} variant="outline" mr={2}>
           Cancel
         </Button>
-        <SubmitTxButton type="submit" form="advanced-staking-params-form">
+        <SubmitTxButton
+          isDisabled={!stakingContract}
+          type="submit"
+          form="advanced-staking-params-form"
+        >
           {featureFlags.MULTI_APP_STAKING ? "Continue" : "Stake"}
         </SubmitTxButton>
       </ModalFooter>
diff --git a/src/components/Modal/DeauthorizeApplicationModal/InititateDeauthorization.tsx b/src/components/Modal/DeauthorizeApplicationModal/InititateDeauthorization.tsx
index ccd8d64af..87825d8b0 100644
--- a/src/components/Modal/DeauthorizeApplicationModal/InititateDeauthorization.tsx
+++ b/src/components/Modal/DeauthorizeApplicationModal/InititateDeauthorization.tsx
@@ -23,36 +23,44 @@ import StakingApplicationOperationIcon from "../../StakingApplicationOperationIc
 import shortenAddress from "../../../utils/shortenAddress"
 import TokenBalance from "../../TokenBalance"
 import { StakingAppName } from "../../../store/staking-applications"
-import { useInitiateDeauthorization } from "../../../hooks/staking-applications"
+import {
+  appNameToThresholdApp,
+  useInitiateDeauthorization,
+} from "../../../hooks/staking-applications"
 import { getStakingAppLabelFromAppName } from "../../../utils/getStakingAppLabel"
 import ModalCloseButton from "../ModalCloseButton"
 import { StakingProviderAppInfo } from "../../../threshold-ts/applications"
 import SubmitTxButton from "../../SubmitTxButton"
+import { useThreshold } from "../../../contexts/ThresholdContext"
 
 const InitiateDeauthorization: FC<
   {
     closeModal: () => void
     stakingProvider: string
     decreaseAmount: string
-    stakingAppName: StakingAppName
+    appName: StakingAppName
   } & Pick<StakingProviderAppInfo, "isOperatorInPool" | "operator">
 > = ({
   closeModal,
   stakingProvider,
   decreaseAmount,
-  stakingAppName,
+  appName,
   isOperatorInPool,
   operator,
 }) => {
+  const threshold = useThreshold()
+  const appContract =
+    threshold.multiAppStaking[appNameToThresholdApp[appName]]?.contract
+
   let shouldUpdateOperatorStatusAfterInitiation
-  if (stakingAppName === "taco") {
+  if (appName === "taco") {
     shouldUpdateOperatorStatusAfterInitiation = false
   } else {
     shouldUpdateOperatorStatusAfterInitiation =
       isOperatorInPool !== undefined && !isOperatorInPool
   }
   const { sendTransaction } = useInitiateDeauthorization(
-    stakingAppName,
+    appName,
     shouldUpdateOperatorStatusAfterInitiation
   )
 
@@ -68,7 +76,7 @@ const InitiateDeauthorization: FC<
         <InfoBox variant="modal">
           <H5 mb={4}>
             You're about to initiate the decrease of your{" "}
-            {getStakingAppLabelFromAppName(stakingAppName)} authorization.
+            {getStakingAppLabelFromAppName(appName)} authorization.
           </H5>
           <BodyLg>
             Initiation and confirmation of deauthorization is a two step action.
@@ -78,7 +86,7 @@ const InitiateDeauthorization: FC<
           )}
         </InfoBox>
         <StakingApplicationOperationIcon
-          stakingApplication={stakingAppName}
+          stakingApplication={appName}
           operation="decrease"
           h="88px"
           mx="auto"
@@ -125,21 +133,17 @@ const InitiateDeauthorization: FC<
           </FlowStep>
           <FlowStep
             preTitle="Step 2"
-            title={
-              stakingAppName === "taco" ? "6 month cooldown" : "45 day cooldown"
-            }
+            title={appName === "taco" ? "6 month cooldown" : "45 day cooldown"}
             status={FlowStepStatus.inactive}
             size="sm"
           >
-            You must wait a {stakingAppName === "taco" ? "6 month" : "45 day"}{" "}
-            cooldown to then confirm the deauthorization. This is 1 transaction.
+            You must wait a {appName === "taco" ? "6 month" : "45 day"} cooldown
+            to then confirm the deauthorization. This is 1 transaction.
           </FlowStep>
         </Stack>
         <Alert status="warning">
           <AlertIcon />
-          Take note! In this {stakingAppName === "taco"
-            ? "6 month"
-            : "45 day"}{" "}
+          Take note! In this {appName === "taco" ? "6 month" : "45 day"}{" "}
           cooldown period, you cannot increase or decrease your authorization.
           As a measure of security for the entire network, in the event of
           slashing you will be slashed based on your initial amount.
@@ -149,7 +153,12 @@ const InitiateDeauthorization: FC<
         <Button variant="outline" onClick={closeModal} mr={2}>
           Dismiss
         </Button>
-        <SubmitTxButton onSubmit={handleInitiateClick}>Initiate</SubmitTxButton>
+        <SubmitTxButton
+          isDisabled={!appContract}
+          onSubmit={handleInitiateClick}
+        >
+          Initiate
+        </SubmitTxButton>
       </ModalFooter>
     </>
   )
diff --git a/src/components/Modal/MapOperatorToStakingProviderConfirmationModal/index.tsx b/src/components/Modal/MapOperatorToStakingProviderConfirmationModal/index.tsx
index 39a259f18..32d9f2fc0 100644
--- a/src/components/Modal/MapOperatorToStakingProviderConfirmationModal/index.tsx
+++ b/src/components/Modal/MapOperatorToStakingProviderConfirmationModal/index.tsx
@@ -26,6 +26,7 @@ import withBaseModal from "../withBaseModal"
 import { OnSuccessCallback } from "../../../web3/hooks"
 import { ApplicationForOperatorMapping } from "../MapOperatorToStakingProviderModal"
 import SubmitTxButton from "../../SubmitTxButton"
+import { useThreshold } from "../../../contexts/ThresholdContext"
 
 const OperatorMappingConfirmation: FC<
   BoxProps & { appName: string; operator: string; stakingProvider: string }
@@ -59,6 +60,7 @@ const MapOperatorToStakingProviderConfirmationModal: FC<
   }
 > = ({ applications, closeModal }) => {
   const { account } = useWeb3React()
+  const threshold = useThreshold()
   const { registerMultipleOperators } =
     useRegisterMultipleOperatorsTransaction()
   const dispatch = useAppDispatch()
@@ -167,9 +169,18 @@ const MapOperatorToStakingProviderConfirmationModal: FC<
       </ModalBody>
       <ModalFooter>
         <Button onClick={closeModal} variant="outline" mr={2}>
-          Dismiss
+          Dismis
         </Button>
-        <SubmitTxButton onSubmit={submitMappingOperator}>
+        <SubmitTxButton
+          isDisabled={
+            !(
+              threshold.multiAppStaking.ecdsa?.contract ??
+              threshold.multiAppStaking.randomBeacon?.contract ??
+              threshold.multiAppStaking.taco?.contract
+            )
+          }
+          onSubmit={submitMappingOperator}
+        >
           Map Address
         </SubmitTxButton>
       </ModalFooter>
diff --git a/src/components/Modal/MapOperatorToStakingProviderModal/index.tsx b/src/components/Modal/MapOperatorToStakingProviderModal/index.tsx
index 174cdd689..2404f0b20 100644
--- a/src/components/Modal/MapOperatorToStakingProviderModal/index.tsx
+++ b/src/components/Modal/MapOperatorToStakingProviderModal/index.tsx
@@ -80,27 +80,27 @@ const MapOperatorToStakingProviderModal: FC<
     switch (appName) {
       case "tbtc":
         const stakingProviderMappedEcdsa =
-          await threshold.multiAppStaking.ecdsa.operatorToStakingProvider(
+          await threshold.multiAppStaking.ecdsa?.operatorToStakingProvider(
             operator
-          )
+          )!
         return (
           !isAddressZero(stakingProviderMappedEcdsa) &&
           !isSameETHAddress(stakingProviderMappedEcdsa, account!)
         )
       case "randomBeacon":
         const stakingProviderMappedRandomBeacon =
-          await threshold.multiAppStaking.randomBeacon.operatorToStakingProvider(
+          await threshold.multiAppStaking.randomBeacon?.operatorToStakingProvider(
             operator
-          )
+          )!
         return (
           !isAddressZero(stakingProviderMappedRandomBeacon) &&
           !isSameETHAddress(stakingProviderMappedRandomBeacon, account!)
         )
       case "taco":
         stakingProviderMapped =
-          await threshold.multiAppStaking.taco.operatorToStakingProvider(
+          await threshold.multiAppStaking.taco?.operatorToStakingProvider(
             operator
-          )
+          )!
         return (
           !isAddressZero(stakingProviderMapped) &&
           !isSameETHAddress(stakingProviderMapped, account!)
diff --git a/src/components/Modal/StakingApplications/AuthorizeStakingApps.tsx b/src/components/Modal/StakingApplications/AuthorizeStakingApps.tsx
index 36b3fa5f2..f986ff320 100644
--- a/src/components/Modal/StakingApplications/AuthorizeStakingApps.tsx
+++ b/src/components/Modal/StakingApplications/AuthorizeStakingApps.tsx
@@ -32,6 +32,7 @@ import {
 import { getStakingAppLabelFromAppName } from "../../../utils/getStakingAppLabel"
 import ModalCloseButton from "../ModalCloseButton"
 import SubmitTxButton from "../../SubmitTxButton"
+import { useThreshold } from "../../../contexts/ThresholdContext"
 
 export type AuthorizeAppsProps = BaseModalProps & {
   stakingProvider: string
@@ -49,6 +50,7 @@ const AuthorizeStakingAppsBase: FC<AuthorizeAppsProps> = ({
   applications,
   closeModal,
 }) => {
+  const threshold = useThreshold()
   const tbtcAppAuthData = useAppSelector((state) =>
     selectStakingAppByStakingProvider(state, "tbtc", stakingProvider)
   )
@@ -102,7 +104,11 @@ const AuthorizeStakingAppsBase: FC<AuthorizeAppsProps> = ({
         <Button onClick={closeModal} variant="outline" mr={2}>
           Dismiss
         </Button>
-        <SubmitTxButton mr={2} onSubmit={onAuthorize}>
+        <SubmitTxButton
+          isDisabled={!threshold.staking.stakingContract}
+          mr={2}
+          onSubmit={onAuthorize}
+        >
           Authorize
         </SubmitTxButton>
       </ModalFooter>
diff --git a/src/components/Modal/StakingApplications/ConfirmDeauthorization.tsx b/src/components/Modal/StakingApplications/ConfirmDeauthorization.tsx
index 18fbb165a..d1aa967bf 100644
--- a/src/components/Modal/StakingApplications/ConfirmDeauthorization.tsx
+++ b/src/components/Modal/StakingApplications/ConfirmDeauthorization.tsx
@@ -19,9 +19,13 @@ import { formatTokenAmount } from "../../../utils/formatAmount"
 import withBaseModal from "../withBaseModal"
 import { StakingAppName } from "../../../store/staking-applications"
 import { BaseModalProps } from "../../../types"
-import { useConfirmDeatuhorizationTransaction } from "../../../hooks/staking-applications"
+import {
+  appNameToThresholdApp,
+  useConfirmDeauthorizationTransaction,
+} from "../../../hooks/staking-applications"
 import ModalCloseButton from "../ModalCloseButton"
 import SubmitTxButton from "../../SubmitTxButton"
+import { useThreshold } from "../../../contexts/ThresholdContext"
 
 export type ConfirmDeauthorizationProps = BaseModalProps & {
   stakingProvider: string
@@ -35,8 +39,12 @@ const ConfirmDeauthorizationBase: FC<ConfirmDeauthorizationProps> = ({
   decreaseAmount,
   closeModal,
 }) => {
+  const threshold = useThreshold()
+  const stakingAppContract =
+    threshold.multiAppStaking[appNameToThresholdApp[stakingAppName]]?.contract
+
   const { sendTransaction } =
-    useConfirmDeatuhorizationTransaction(stakingAppName)
+    useConfirmDeauthorizationTransaction(stakingAppName)
 
   const onDeauthorize = async () => {
     await sendTransaction(stakingProvider)
@@ -79,7 +87,11 @@ const ConfirmDeauthorizationBase: FC<ConfirmDeauthorizationProps> = ({
         <Button onClick={closeModal} variant="outline" mr={2}>
           Cancel
         </Button>
-        <SubmitTxButton mr={2} onSubmit={onDeauthorize}>
+        <SubmitTxButton
+          isDisabled={!stakingAppContract}
+          mr={2}
+          onSubmit={onDeauthorize}
+        >
           Confirm Deauthorization
         </SubmitTxButton>
       </ModalFooter>
diff --git a/src/components/Modal/StakingApplications/IncreaseAuthorization.tsx b/src/components/Modal/StakingApplications/IncreaseAuthorization.tsx
index 7ee7d9892..db899fcb6 100644
--- a/src/components/Modal/StakingApplications/IncreaseAuthorization.tsx
+++ b/src/components/Modal/StakingApplications/IncreaseAuthorization.tsx
@@ -13,7 +13,10 @@ import {
   BodySm,
 } from "@threshold-network/components"
 import InfoBox from "../../InfoBox"
-import { useIncreaseAuthorizationTransaction } from "../../../hooks/staking-applications"
+import {
+  appNameToThresholdApp,
+  useIncreaseAuthorizationTransaction,
+} from "../../../hooks/staking-applications"
 import shortenAddress from "../../../utils/shortenAddress"
 import { formatTokenAmount } from "../../../utils/formatAmount"
 import withBaseModal from "../withBaseModal"
@@ -25,19 +28,23 @@ import StakingApplicationOperationIcon from "../../StakingApplicationOperationIc
 import ModalCloseButton from "../ModalCloseButton"
 import { OnSuccessCallback } from "../../../web3/hooks"
 import SubmitTxButton from "../../SubmitTxButton"
+import { useThreshold } from "../../../contexts/ThresholdContext"
 
 export type IncreaseAuthorizationProps = BaseModalProps & {
   stakingProvider: string
-  stakingAppName: StakingAppName
+  appName: StakingAppName
   increaseAmount: string
 }
 
 const IncreaseAuthorizationBase: FC<IncreaseAuthorizationProps> = ({
   stakingProvider,
-  stakingAppName,
+  appName,
   increaseAmount,
   closeModal,
 }) => {
+  const threshold = useThreshold()
+  const appContract =
+    threshold.multiAppStaking[appNameToThresholdApp[appName]]?.contract
   const { openModal } = useModal()
   const onSuccess = useCallback<OnSuccessCallback>(
     (receipt) => {
@@ -50,7 +57,7 @@ const IncreaseAuthorizationBase: FC<IncreaseAuthorizationProps> = ({
     [openModal, stakingProvider, increaseAmount]
   )
   const { sendTransaction } = useIncreaseAuthorizationTransaction(
-    stakingAppName,
+    appName,
     onSuccess
   )
 
@@ -71,7 +78,7 @@ const IncreaseAuthorizationBase: FC<IncreaseAuthorizationProps> = ({
           </BodyLg>
         </InfoBox>
         <StakingApplicationOperationIcon
-          stakingApplication={stakingAppName}
+          stakingApplication={appName}
           operation="increase"
           w="88px"
           h="88px"
@@ -99,7 +106,11 @@ const IncreaseAuthorizationBase: FC<IncreaseAuthorizationProps> = ({
         <Button onClick={closeModal} variant="outline" mr={2}>
           Cancel
         </Button>
-        <SubmitTxButton mr={2} onSubmit={onAuthorizeIncrease}>
+        <SubmitTxButton
+          isDisabled={!appContract}
+          mr={2}
+          onSubmit={onAuthorizeIncrease}
+        >
           Authorize Increase
         </SubmitTxButton>
       </ModalFooter>
diff --git a/src/components/Modal/SubmitStake/index.tsx b/src/components/Modal/SubmitStake/index.tsx
index 07fc6c3b8..5bcde1e27 100644
--- a/src/components/Modal/SubmitStake/index.tsx
+++ b/src/components/Modal/SubmitStake/index.tsx
@@ -25,11 +25,13 @@ import { StakingContractLearnMore } from "../../Link"
 import StakingStats from "../../StakingStats"
 import ModalCloseButton from "../ModalCloseButton"
 import SubmitTxButton from "../../SubmitTxButton"
+import { useTStakingContract } from "../../../web3/hooks"
 
 const SubmitStakeModal: FC<BaseModalProps> = () => {
   const { closeModal, openModal } = useModal()
   const [isAcknowledgementChecked, setIsAcknowledgementChecked] =
     useState(false)
+  const stakingContract = useTStakingContract()
 
   // stake transaction, opens success modal on success callback
   const { stake } = useStakeTransaction((receipt) => {
@@ -100,7 +102,7 @@ const SubmitStakeModal: FC<BaseModalProps> = () => {
               Cancel
             </Button>
             <SubmitTxButton
-              isDisabled={!isAcknowledgementChecked}
+              isDisabled={!isAcknowledgementChecked || !stakingContract}
               onSubmit={submitStake}
             >
               Stake
diff --git a/src/components/Modal/TACoCommitmentModal/index.tsx b/src/components/Modal/TACoCommitmentModal/index.tsx
index c71342dbd..dd5472d6d 100644
--- a/src/components/Modal/TACoCommitmentModal/index.tsx
+++ b/src/components/Modal/TACoCommitmentModal/index.tsx
@@ -29,7 +29,6 @@ import {
 } from "../../../web3/hooks"
 import { useModal } from "../../../hooks/useModal"
 import { useThreshold } from "../../../contexts/ThresholdContext"
-import { stakingAppNameToThresholdAppService } from "../../../hooks/staking-applications/useStakingAppContract"
 import SubmitTxButton from "../../SubmitTxButton"
 
 export type TACoCommitProps = BaseModalProps & {
@@ -63,8 +62,7 @@ const TACoCommitmentModal: FC<TACoCommitProps> = ({
     [authorizedAmount]
   )
   const { sendTransaction } = useSendTransactionFromFn(
-    threshold.multiAppStaking![stakingAppNameToThresholdAppService["taco"]]
-      .makeCommitment,
+    threshold.multiAppStaking.taco?.makeCommitment!,
     onSuccess
   )
 
@@ -167,6 +165,7 @@ const TACoCommitmentModal: FC<TACoCommitProps> = ({
           Cancel
         </Button>
         <SubmitTxButton
+          isDisabled={!threshold.multiAppStaking.taco?.contract}
           onSubmit={() => submitCommitment(stakingProvider, value)}
           type="submit"
         >
diff --git a/src/components/Modal/TopupTModal/LegacyTopUpModal.tsx b/src/components/Modal/TopupTModal/LegacyTopUpModal.tsx
index 7240f4e19..16830c0dd 100644
--- a/src/components/Modal/TopupTModal/LegacyTopUpModal.tsx
+++ b/src/components/Modal/TopupTModal/LegacyTopUpModal.tsx
@@ -36,6 +36,7 @@ import { StakingContractLearnMore } from "../../Link"
 import { useModal } from "../../../hooks/useModal"
 import { StakeData } from "../../../types/staking"
 import ModalCloseButton from "../ModalCloseButton"
+import { useTStakingContract } from "../../../web3/hooks"
 
 const stakeTypeToDappHref: Record<StakeType.KEEP | StakeType.NU, ExternalHref> =
   {
@@ -52,6 +53,7 @@ const LegacyTopUpModal: FC<BaseModalProps & { stake: StakeData }> = ({
   // TODO find a solution to style bullets with chakra theme.
   const bulletColor = useColorModeValue("gray.700", "gray.300")
   const bulletColorStyle = { "::marker": { color: bulletColor } }
+  const stakingContract = useTStakingContract()
 
   const onSubmitForm = (tokenAmount: string | number) => {
     openModal(ModalType.TopupT, {
@@ -101,6 +103,7 @@ const LegacyTopUpModal: FC<BaseModalProps & { stake: StakeData }> = ({
                 submitButtonText="Top-up"
                 maxTokenAmount={tBalance}
                 shouldDisplayMaxAmountInLabel
+                isDisabled={!stakingContract}
               />
             </TabPanel>
             {stake.stakeType !== StakeType.T && (
diff --git a/src/components/Modal/TopupTModal/TopUpTModal.tsx b/src/components/Modal/TopupTModal/TopUpTModal.tsx
index 758c36fa7..79ae175bb 100644
--- a/src/components/Modal/TopupTModal/TopUpTModal.tsx
+++ b/src/components/Modal/TopupTModal/TopUpTModal.tsx
@@ -20,7 +20,7 @@ import { StakeData } from "../../../types/staking"
 import { ModalType, TopUpType } from "../../../enums"
 import withBaseModal from "../withBaseModal"
 import ModalCloseButton from "../ModalCloseButton"
-import { OnSuccessCallback } from "../../../web3/hooks"
+import { OnSuccessCallback, useTStakingContract } from "../../../web3/hooks"
 import SubmitTxButton from "../../SubmitTxButton"
 
 const TopupTModal: FC<
@@ -30,6 +30,7 @@ const TopupTModal: FC<
     topUpType: TopUpType
   }
 > = ({ stake, amountTopUp, topUpType }) => {
+  const stakingContract = useTStakingContract()
   const { closeModal, openModal } = useModal()
 
   const onSuccess = useCallback<OnSuccessCallback>(
@@ -80,6 +81,7 @@ const TopupTModal: FC<
           Cancel
         </Button>
         <SubmitTxButton
+          isDisabled={!stakingContract}
           onSubmit={() => {
             topup({
               stakingProvider: stake.stakingProvider,
diff --git a/src/components/Modal/UnstakeTModal/Step2.tsx b/src/components/Modal/UnstakeTModal/Step2.tsx
index 034c432a0..e60e64309 100644
--- a/src/components/Modal/UnstakeTModal/Step2.tsx
+++ b/src/components/Modal/UnstakeTModal/Step2.tsx
@@ -26,7 +26,7 @@ import { ModalType, UnstakeType } from "../../../enums"
 import withBaseModal from "../withBaseModal"
 import { DeauthorizeInfo } from "./DeauthorizeInfo"
 import ModalCloseButton from "../ModalCloseButton"
-import { OnSuccessCallback } from "../../../web3/hooks"
+import { OnSuccessCallback, useTStakingContract } from "../../../web3/hooks"
 import SubmitTxButton from "../../SubmitTxButton"
 
 const UnstakeTModal: FC<
@@ -36,6 +36,7 @@ const UnstakeTModal: FC<
     unstakeType: UnstakeType
   }
 > = ({ stake, amountToUnstake, unstakeType, closeModal }) => {
+  const stakingContract = useTStakingContract()
   const { openModal } = useModal()
   const _amountToUnstake =
     unstakeType === UnstakeType.ALL
@@ -119,6 +120,7 @@ const UnstakeTModal: FC<
           Cancel
         </Button>
         <SubmitTxButton
+          isDisabled={!stakingContract}
           onSubmit={() => {
             unstake({
               stakingProvider: stake.stakingProvider,
diff --git a/src/components/Modal/UpgradeToTModal/TransactionIdle.tsx b/src/components/Modal/UpgradeToTModal/TransactionIdle.tsx
index 3dcad19ea..f3a8ec96d 100644
--- a/src/components/Modal/UpgradeToTModal/TransactionIdle.tsx
+++ b/src/components/Modal/UpgradeToTModal/TransactionIdle.tsx
@@ -34,7 +34,7 @@ const TransactionIdle: FC<TransactionIdleProps> = ({
 }) => {
   const { amount: receivedAmount } = useTConvertedAmount(token, upgradedAmount)
   const { formattedAmount: exchangeRate } = useTExchangeRate(token)
-  const contract = useVendingMachineContract(token)
+  const vendingMachineContract = useVendingMachineContract(token)
   const { upgradeToT } = useUpgradeToT(token)
 
   return (
@@ -65,9 +65,9 @@ const TransactionIdle: FC<TransactionIdleProps> = ({
           mt="2rem"
         >
           This action is reversible via the{" "}
-          {contract ? (
+          {vendingMachineContract ? (
             <ViewInBlockExplorer
-              id={contract.address}
+              id={vendingMachineContract.address}
               type={ExplorerDataType.ADDRESS}
               text="vending machine contract."
             />
@@ -83,6 +83,7 @@ const TransactionIdle: FC<TransactionIdleProps> = ({
           Cancel
         </Button>
         <SubmitTxButton
+          isDisabled={!vendingMachineContract}
           onSubmit={async () => {
             await upgradeToT(upgradedAmount)
           }}
diff --git a/src/components/Modal/tBTC/InitiateUnminting.tsx b/src/components/Modal/tBTC/InitiateUnminting.tsx
index 8d86a0bf8..40d4d211d 100644
--- a/src/components/Modal/tBTC/InitiateUnminting.tsx
+++ b/src/components/Modal/tBTC/InitiateUnminting.tsx
@@ -129,6 +129,7 @@ const InitiateUnmintingBase: FC<InitiateUnmintingProps> = ({
           Cancel
         </Button>
         <SubmitTxButton
+          isDisabled={!threshold.tbtc.bridgeContract}
           onSubmit={initiateUnminting}
           data-ph-capture-attribute-button-name={"Unmint (Modal)"}
           data-ph-capture-attribute-button-id={
diff --git a/src/components/Navbar/index.tsx b/src/components/Navbar/index.tsx
index bbc64d4e6..c9cec894f 100644
--- a/src/components/Navbar/index.tsx
+++ b/src/components/Navbar/index.tsx
@@ -24,8 +24,10 @@ const Navbar: FC = () => {
   useEffect(() => {
     if (ledgerLiveAccountAddress && isEmbed) {
       dispatch(walletConnected({ address: ledgerLiveAccountAddress, chainId }))
+    } else if (account) {
+      dispatch(walletConnected({ address: account, chainId }))
     }
-  }, [ledgerLiveAccountAddress, dispatch, isEmbed])
+  }, [account, chainId, ledgerLiveAccountAddress, dispatch, isEmbed])
 
   return (
     <NavbarComponent
diff --git a/src/components/SubmitTxButton.tsx b/src/components/SubmitTxButton.tsx
index ded3ac841..21d82c154 100644
--- a/src/components/SubmitTxButton.tsx
+++ b/src/components/SubmitTxButton.tsx
@@ -4,16 +4,12 @@ import { useIsActive } from "../hooks/useIsActive"
 import { useConnectWallet } from "../hooks/useConnectWallet"
 import { RootState } from "../store"
 import { useSelector } from "react-redux"
-import { isL2Network, isValidL2Transaction } from "../networks/utils/"
-import { AllowedL2TransactionTypes } from "../networks/enums/networks"
 
 interface SubmitTxButtonProps extends ButtonProps {
-  l2TransactionType?: AllowedL2TransactionTypes
   onSubmit?: () => void
 }
 
 const SubmitTxButton: FC<SubmitTxButtonProps> = ({
-  l2TransactionType,
   onSubmit,
   isLoading,
   isDisabled,
@@ -25,12 +21,9 @@ const SubmitTxButton: FC<SubmitTxButtonProps> = ({
     trm: { isFetching },
   } = useSelector((state: RootState) => state.account)
 
-  const { isActive, chainId } = useIsActive()
+  const { isActive } = useIsActive()
   const connectWallet = useConnectWallet()
-  const isButtonDisabled =
-    isBlocked ||
-    isDisabled ||
-    (isL2Network(chainId) && !isValidL2Transaction(l2TransactionType))
+  const isButtonDisabled = isBlocked || isDisabled
 
   const onConnectWalletClick = () => {
     connectWallet()
diff --git a/src/components/UpgradeCard/UpgradeCardTemplate.tsx b/src/components/UpgradeCard/UpgradeCardTemplate.tsx
index 27fde1336..3526a43e1 100644
--- a/src/components/UpgradeCard/UpgradeCardTemplate.tsx
+++ b/src/components/UpgradeCard/UpgradeCardTemplate.tsx
@@ -16,6 +16,7 @@ import { UpgredableToken } from "../../types"
 import { Token } from "../../enums"
 import { useWeb3React } from "@web3-react/core"
 import { BigNumber } from "ethers"
+import { useVendingMachineContract } from "../../web3/hooks"
 
 export interface UpgradeCardTemplateProps {
   token: UpgredableToken
@@ -34,6 +35,7 @@ const UpgradeCardTemplate: FC<UpgradeCardTemplateProps> = ({
   const { formattedAmount } = useTConvertedAmount(token, amountToConvert)
   const { formattedAmount: exchangeRate } = useTExchangeRate(token)
   const { account } = useWeb3React()
+  const vendingMachineContract = useVendingMachineContract(token)
 
   const titleText = useMemo(() => {
     switch (token) {
@@ -75,10 +77,11 @@ const UpgradeCardTemplate: FC<UpgradeCardTemplateProps> = ({
           mt={10}
           onSubmit={onSubmit}
           isDisabled={
-            !!account &&
-            (amountToConvert == 0 ||
-              amountToConvert == "" ||
-              BigNumber.from(amountToConvert).gt(max))
+            !vendingMachineContract ||
+            (!!account &&
+              (amountToConvert == 0 ||
+                amountToConvert == "" ||
+                BigNumber.from(amountToConvert).gt(max)))
           }
         >
           Upgrade
diff --git a/src/components/tBTC/BridgeActivity.tsx b/src/components/tBTC/BridgeActivity.tsx
index 2afda15ba..2fcf8be92 100644
--- a/src/components/tBTC/BridgeActivity.tsx
+++ b/src/components/tBTC/BridgeActivity.tsx
@@ -219,7 +219,7 @@ const EmptyActivity: FC = () => {
 
 const BridgeActivityLoadingState = () => {
   return (
-    <Stack>
+    <Stack mt="1rem">
       <Skeleton height="20px" />
       <Skeleton height="20px" />
       <Skeleton height="20px" />
diff --git a/src/hooks/ledger-live-app/useRequestEthereumAccount.ts b/src/hooks/ledger-live-app/useRequestEthereumAccount.ts
index 130cce76c..44c0b5ed8 100644
--- a/src/hooks/ledger-live-app/useRequestEthereumAccount.ts
+++ b/src/hooks/ledger-live-app/useRequestEthereumAccount.ts
@@ -26,7 +26,7 @@ export function useRequestEthereumAccount(): UseRequestAccountReturn {
   const { setEthAccount } = useLedgerLiveApp()
   const { walletApiReactTransport } = useWalletApiReactTransport()
   const useRequestAccountReturn = useWalletApiRequestAccount()
-  const { account, requestAccount } = useRequestAccountReturn
+  const { account: ledgerLiveAccount, requestAccount } = useRequestAccountReturn
   const { chainId } = useWeb3React()
   const dispatch = useAppDispatch()
   const { isEmbed } = useIsEmbed()
@@ -38,10 +38,12 @@ export function useRequestEthereumAccount(): UseRequestAccountReturn {
     // here to indicate as early as as possible that the sdk is in the
     // initializing process.
     if (isEmbed) {
-      setEthAccount(account || undefined)
-      dispatch(walletConnected({ address: account?.address || "", chainId }))
+      setEthAccount(ledgerLiveAccount || undefined)
+      dispatch(
+        walletConnected({ address: ledgerLiveAccount?.address || "", chainId })
+      )
     }
-  }, [account, isEmbed])
+  }, [ledgerLiveAccount, chainId, isEmbed])
 
   const requestEthereumAccount = useCallback(async () => {
     const defaultOrConnectedChainId = useDefaultOrConnectedChainId()
diff --git a/src/hooks/staking-applications/index.ts b/src/hooks/staking-applications/index.ts
index a2c2e46a5..7aa50eaf9 100644
--- a/src/hooks/staking-applications/index.ts
+++ b/src/hooks/staking-applications/index.ts
@@ -8,7 +8,7 @@ export * from "./useAuthorizeMultipleAppsTransaction"
 export * from "./useIncreaseAuthorizationTransaction"
 export * from "./useStakingApplicationAddress"
 export * from "./useSubscribeToAuthorizationDecreaseApprovedEvent"
-export * from "./useConfirmDeatuhorizationTransaction"
+export * from "./useConfirmDeauthorizationTransaction"
 export * from "./useInitiateDeauthorization"
 export * from "./useSubscribeToAuthorizationDecreaseRequestedEvent"
 export * from "./useStakingApplicationDecreaseDelay"
diff --git a/src/hooks/staking-applications/useAuthorizeMultipleAppsTransaction.ts b/src/hooks/staking-applications/useAuthorizeMultipleAppsTransaction.ts
index 716eacea4..77fc0cb60 100644
--- a/src/hooks/staking-applications/useAuthorizeMultipleAppsTransaction.ts
+++ b/src/hooks/staking-applications/useAuthorizeMultipleAppsTransaction.ts
@@ -14,7 +14,7 @@ export const useAuthorizeMultipleAppsTransaction = () => {
   const { openModal } = useModal()
 
   const { sendTransaction, status } = useSendTransactionFromFn(
-    threshold.staking!.increaseAuthorization
+    threshold.staking.increaseAuthorization
   )
 
   const authorizeMultipleApps = useCallback(
diff --git a/src/hooks/staking-applications/useBondOperatorTransaction.ts b/src/hooks/staking-applications/useBondOperatorTransaction.ts
index f2a4eb177..c49f25eaf 100644
--- a/src/hooks/staking-applications/useBondOperatorTransaction.ts
+++ b/src/hooks/staking-applications/useBondOperatorTransaction.ts
@@ -5,7 +5,7 @@ import {
   OnSuccessCallback,
   useSendTransactionFromFn,
 } from "../../web3/hooks"
-import { stakingAppNameToThresholdAppService } from "./useStakingAppContract"
+import { appNameToThresholdApp } from "./useStakingAppContract"
 
 export const useBondOperatorTransaction = (
   appName: StakingAppName,
@@ -15,8 +15,7 @@ export const useBondOperatorTransaction = (
   const threshold = useThreshold()
 
   return useSendTransactionFromFn(
-    threshold.multiAppStaking![stakingAppNameToThresholdAppService[appName]]
-      .bondOperator,
+    threshold.multiAppStaking[appNameToThresholdApp[appName]]?.bondOperator!,
     onSuccess,
     onError
   )
diff --git a/src/hooks/staking-applications/useConfirmDeatuhorizationTransaction.ts b/src/hooks/staking-applications/useConfirmDeauthorizationTransaction.ts
similarity index 63%
rename from src/hooks/staking-applications/useConfirmDeatuhorizationTransaction.ts
rename to src/hooks/staking-applications/useConfirmDeauthorizationTransaction.ts
index 1fec0902d..c4bcea1a4 100644
--- a/src/hooks/staking-applications/useConfirmDeatuhorizationTransaction.ts
+++ b/src/hooks/staking-applications/useConfirmDeauthorizationTransaction.ts
@@ -5,9 +5,9 @@ import {
   OnSuccessCallback,
   useSendTransactionFromFn,
 } from "../../web3/hooks"
-import { stakingAppNameToThresholdAppService } from "./useStakingAppContract"
+import { appNameToThresholdApp } from "./useStakingAppContract"
 
-export const useConfirmDeatuhorizationTransaction = (
+export const useConfirmDeauthorizationTransaction = (
   appName: StakingAppName,
   onSuccess?: OnSuccessCallback,
   onError?: OnErrorCallback
@@ -15,8 +15,8 @@ export const useConfirmDeatuhorizationTransaction = (
   const threshold = useThreshold()
 
   return useSendTransactionFromFn(
-    threshold.multiAppStaking![stakingAppNameToThresholdAppService[appName]]
-      .approveAuthorizationDecrease,
+    threshold.multiAppStaking[appNameToThresholdApp[appName]]
+      ?.approveAuthorizationDecrease!,
     onSuccess,
     onError
   )
diff --git a/src/hooks/staking-applications/useIncreaseAuthorizationTransaction.ts b/src/hooks/staking-applications/useIncreaseAuthorizationTransaction.ts
index 74a56af5e..1a741fe5a 100644
--- a/src/hooks/staking-applications/useIncreaseAuthorizationTransaction.ts
+++ b/src/hooks/staking-applications/useIncreaseAuthorizationTransaction.ts
@@ -5,7 +5,7 @@ import {
   OnSuccessCallback,
   useSendTransactionFromFn,
 } from "../../web3/hooks"
-import { stakingAppNameToThresholdAppService } from "./useStakingAppContract"
+import { appNameToThresholdApp } from "./useStakingAppContract"
 
 export const useIncreaseAuthorizationTransaction = (
   appName: StakingAppName,
@@ -15,8 +15,8 @@ export const useIncreaseAuthorizationTransaction = (
   const threshold = useThreshold()
 
   return useSendTransactionFromFn(
-    threshold.multiAppStaking![stakingAppNameToThresholdAppService[appName]]
-      .increaseAuthorization,
+    threshold.multiAppStaking[appNameToThresholdApp[appName]]
+      ?.increaseAuthorization!,
     onSuccess,
     onError
   )
diff --git a/src/hooks/staking-applications/useInitiateDeauthorization.ts b/src/hooks/staking-applications/useInitiateDeauthorization.ts
index 42e80a686..659ffaf87 100644
--- a/src/hooks/staking-applications/useInitiateDeauthorization.ts
+++ b/src/hooks/staking-applications/useInitiateDeauthorization.ts
@@ -9,7 +9,7 @@ import {
 } from "../../web3/hooks"
 import { isAddressZero } from "../../web3/utils"
 import { useModal } from "../useModal"
-import { stakingAppNameToThresholdAppService } from "./useStakingAppContract"
+import { appNameToThresholdApp } from "./useStakingAppContract"
 import { useUpdateOperatorStatus } from "./useUpdateOperatorStatus"
 
 export const useInitiateDeauthorization = (
@@ -42,8 +42,8 @@ export const useInitiateDeauthorization = (
     sendTransaction: requestAuthorizationDecrease,
     status: deauthorizationTxStatus,
   } = useSendTransactionFromFn(
-    threshold.multiAppStaking![stakingAppNameToThresholdAppService[appName]]
-      .requestAuthorizationDecrease,
+    threshold.multiAppStaking[appNameToThresholdApp[appName]]
+      ?.requestAuthorizationDecrease!,
     onSuccess,
     onErrorRequestAuthorizationDecrease
   )
diff --git a/src/hooks/staking-applications/useRegisterOperatorTransaction.ts b/src/hooks/staking-applications/useRegisterOperatorTransaction.ts
index 7f5bea0a4..fc1a231f7 100644
--- a/src/hooks/staking-applications/useRegisterOperatorTransaction.ts
+++ b/src/hooks/staking-applications/useRegisterOperatorTransaction.ts
@@ -5,7 +5,7 @@ import {
   OnSuccessCallback,
   useSendTransactionFromFn,
 } from "../../web3/hooks"
-import { stakingAppNameToThresholdAppService } from "./useStakingAppContract"
+import { appNameToThresholdApp } from "./useStakingAppContract"
 
 export const useRegisterOperatorTransaction = (
   appName: StakingAppName,
@@ -15,8 +15,8 @@ export const useRegisterOperatorTransaction = (
   const threshold = useThreshold()
 
   return useSendTransactionFromFn(
-    threshold.multiAppStaking![stakingAppNameToThresholdAppService[appName]]
-      .registerOperator,
+    threshold.multiAppStaking[appNameToThresholdApp[appName]]
+      ?.registerOperator!,
     onSuccess,
     onError
   )
diff --git a/src/hooks/staking-applications/useStakingAppContract.ts b/src/hooks/staking-applications/useStakingAppContract.ts
index 58636ee9b..bc8f1b9af 100644
--- a/src/hooks/staking-applications/useStakingAppContract.ts
+++ b/src/hooks/staking-applications/useStakingAppContract.ts
@@ -2,7 +2,7 @@ import { StakingAppName } from "../../store/staking-applications"
 import { useThreshold } from "../../contexts/ThresholdContext"
 import { Contract } from "ethers"
 
-export const stakingAppNameToThresholdAppService: Record<
+export const appNameToThresholdApp: Record<
   StakingAppName,
   "ecdsa" | "randomBeacon" | "taco"
 > = {
@@ -11,13 +11,8 @@ export const stakingAppNameToThresholdAppService: Record<
   taco: "taco",
 }
 
-export const useStakingAppContract = (
-  appName: StakingAppName
-): Contract | null => {
+export const useStakingAppContract = (appName: StakingAppName): Contract => {
   const threshold = useThreshold()
 
-  if (!threshold.multiAppStaking) return null
-
-  return threshold.multiAppStaking[stakingAppNameToThresholdAppService[appName]]
-    .contract
+  return threshold.multiAppStaking[appNameToThresholdApp[appName]]?.contract!
 }
diff --git a/src/hooks/staking-applications/useStakingApplicationAddress.ts b/src/hooks/staking-applications/useStakingApplicationAddress.ts
index 20721999f..4338124ed 100644
--- a/src/hooks/staking-applications/useStakingApplicationAddress.ts
+++ b/src/hooks/staking-applications/useStakingApplicationAddress.ts
@@ -1,12 +1,13 @@
 import { useThreshold } from "../../contexts/ThresholdContext"
 import { StakingAppName } from "../../store/staking-applications"
 import { AddressZero } from "../../web3/utils"
-import { stakingAppNameToThresholdAppService } from "./useStakingAppContract"
+import { appNameToThresholdApp } from "./useStakingAppContract"
 
 export const useStakingApplicationAddress = (appName: StakingAppName) => {
+  const threshold = useThreshold()
+
   return (
-    useThreshold().multiAppStaking![
-      stakingAppNameToThresholdAppService[appName]
-    ]?.address ?? AddressZero
+    threshold.multiAppStaking[appNameToThresholdApp[appName]]?.address ??
+    AddressZero
   )
 }
diff --git a/src/hooks/staking-applications/useUpdateOperatorStatus.tsx b/src/hooks/staking-applications/useUpdateOperatorStatus.tsx
index 1f8739d4a..34c9a11f7 100644
--- a/src/hooks/staking-applications/useUpdateOperatorStatus.tsx
+++ b/src/hooks/staking-applications/useUpdateOperatorStatus.tsx
@@ -1,13 +1,13 @@
 import { useThreshold } from "../../contexts/ThresholdContext"
 import { StakingAppName } from "../../store/staking-applications"
 import { useSendTransactionFromFn } from "../../web3/hooks"
-import { stakingAppNameToThresholdAppService } from "./useStakingAppContract"
+import { appNameToThresholdApp } from "./useStakingAppContract"
 
 export const useUpdateOperatorStatus = (appName: StakingAppName) => {
   const threshold = useThreshold()
 
   return useSendTransactionFromFn(
-    threshold.multiAppStaking![stakingAppNameToThresholdAppService[appName]]
-      .updateOperatorStatus
+    threshold.multiAppStaking[appNameToThresholdApp[appName]]
+      ?.updateOperatorStatus!
   )
 }
diff --git a/src/networks/constants/networks.ts b/src/networks/constants/networks.ts
index 8e571b10a..e14705c9b 100644
--- a/src/networks/constants/networks.ts
+++ b/src/networks/constants/networks.ts
@@ -1,7 +1,2 @@
-import { AllowedL2TransactionTypes } from "../enums/networks"
-
 export const DECIMALS = 18
 export const ETH_SYMBOL = "ETH"
-export const ALLOWED_L2_TRANSACTIONS: AllowedL2TransactionTypes[] = [
-  AllowedL2TransactionTypes.mint,
-]
diff --git a/src/networks/enums/networks.ts b/src/networks/enums/networks.ts
index 0580aaa12..93f1f27ae 100644
--- a/src/networks/enums/networks.ts
+++ b/src/networks/enums/networks.ts
@@ -1,7 +1,3 @@
-export enum AllowedL2TransactionTypes {
-  mint = "MINT",
-}
-
 export enum TrmNetworksChainId {
   ethereum = 1,
   arbitrum = 42161,
diff --git a/src/networks/utils/index.ts b/src/networks/utils/index.ts
index bb8a72361..e0e31c80b 100644
--- a/src/networks/utils/index.ts
+++ b/src/networks/utils/index.ts
@@ -6,6 +6,5 @@ export * from "./createExplorerLink"
 export * from "./getRpcUrl"
 export * from "./mappings"
 export * from "./networks"
-export * from "./validateL2TransactionType"
 export * from "./networksAlchemyConfig"
 export * from "./getMainnetOrTestnetChainId"
diff --git a/src/networks/utils/validateL2TransactionType.ts b/src/networks/utils/validateL2TransactionType.ts
deleted file mode 100644
index 0af9f1c62..000000000
--- a/src/networks/utils/validateL2TransactionType.ts
+++ /dev/null
@@ -1,11 +0,0 @@
-import { ALLOWED_L2_TRANSACTIONS } from "../constants/networks"
-import { AllowedL2TransactionTypes } from "../enums/networks"
-
-export function isValidL2Transaction<T = AllowedL2TransactionTypes>(
-  type?: T
-): boolean {
-  if (!type) return false
-  return ALLOWED_L2_TRANSACTIONS.includes(
-    type as unknown as AllowedL2TransactionTypes
-  )
-}
diff --git a/src/pages/Staking/AuthorizeStakingApps/AuthorizeApplicationsCardCheckbox/index.tsx b/src/pages/Staking/AuthorizeStakingApps/AuthorizeApplicationsCardCheckbox/index.tsx
index 3cf37f81e..bce5d62f0 100644
--- a/src/pages/Staking/AuthorizeStakingApps/AuthorizeApplicationsCardCheckbox/index.tsx
+++ b/src/pages/Staking/AuthorizeStakingApps/AuthorizeApplicationsCardCheckbox/index.tsx
@@ -26,6 +26,7 @@ import { ModalType } from "../../../../enums"
 import { StakingAppName } from "../../../../store/staking-applications"
 import { FormikProps } from "formik"
 import {
+  appNameToThresholdApp,
   useStakingApplicationAddress,
   useStakingApplicationDecreaseDelay,
   useUpdateOperatorStatus,
@@ -36,6 +37,7 @@ import { calculatePercenteage } from "../../../../utils/percentage"
 import { StakingAppForm } from "../../../../components/StakingApplicationForms"
 import { AuthorizationStatus } from "../../../../types"
 import SubmitTxButton from "../../../../components/SubmitTxButton"
+import { useThreshold } from "../../../../contexts/ThresholdContext"
 
 interface CommonProps {
   stakingAppId: StakingAppName
@@ -240,7 +242,7 @@ export const AuthorizeApplicationsCardCheckboxBase: FC<
       openModal(ModalType.IncreaseAuthorization, {
         stakingProvider,
         increaseAmount: tokenAmount,
-        stakingAppName: appAuthData.stakingAppId,
+        appName: appAuthData.stakingAppId,
       })
     }
   }
@@ -249,7 +251,7 @@ export const AuthorizeApplicationsCardCheckboxBase: FC<
     openModal(ModalType.DeauthorizeApplication, {
       stakingProvider: stakingProvider,
       decreaseAmount: tokenAmount,
-      stakingAppName: appAuthData.stakingAppId,
+      appName: appAuthData.stakingAppId,
       operator: appAuthData.operator,
       isOperatorInPool: appAuthData.isOperatorInPool,
     })
@@ -263,7 +265,7 @@ export const AuthorizeApplicationsCardCheckboxBase: FC<
   const onConfirmDeauthorization = () => {
     openModal(ModalType.ConfirmDeauthorization, {
       stakingProvider,
-      stakingAppName: appAuthData.stakingAppId,
+      appName: appAuthData.stakingAppId,
       decreaseAmount: appAuthData.pendingAuthorizationDecrease,
     })
   }
@@ -372,6 +374,7 @@ export const AuthorizeApplicationsCardCheckboxBase: FC<
           onConfirmDeauthorization={onConfirmDeauthorization}
           onActivateDeauthorizationRequest={updateOperatorStatus}
           status={status}
+          appName={appAuthData.stakingAppId}
         />
       )}
     </Card>
@@ -386,6 +389,7 @@ const Deauthorization: FC<{
   onConfirmDeauthorization: () => void
   onActivateDeauthorizationRequest: () => void
   status: AuthorizationStatus
+  appName: StakingAppName
 }> = ({
   pendingAuthorizationDecrease,
   remainingAuthorizationDecreaseDelay,
@@ -394,7 +398,11 @@ const Deauthorization: FC<{
   onConfirmDeauthorization,
   onActivateDeauthorizationRequest,
   status,
+  appName,
 }) => {
+  const threshold = useThreshold()
+  const appContract =
+    threshold.multiAppStaking[appNameToThresholdApp[appName]]?.contract
   const progressBarValue =
     remainingAuthorizationDecreaseDelay === "0"
       ? 100
@@ -466,7 +474,10 @@ const Deauthorization: FC<{
           </Button>
         )}
         {status === "deauthorization-initiation-needed" && (
-          <SubmitTxButton onSubmit={onActivateDeauthorizationRequest}>
+          <SubmitTxButton
+            isDisabled={!appContract}
+            onSubmit={onActivateDeauthorizationRequest}
+          >
             Activate Deauthorization Request
           </SubmitTxButton>
         )}
diff --git a/src/pages/tBTC/Bridge/MintUnmintNav.tsx b/src/pages/tBTC/Bridge/MintUnmintNav.tsx
index ef2835aa7..9a60b7583 100644
--- a/src/pages/tBTC/Bridge/MintUnmintNav.tsx
+++ b/src/pages/tBTC/Bridge/MintUnmintNav.tsx
@@ -9,14 +9,9 @@ import { Box, Card, FilterTabs, FilterTab } from "@threshold-network/components"
 import Link from "../../../components/Link"
 import { PageComponent } from "../../../types"
 import { isL2Network } from "../../../networks/utils"
-import { isValidL2Transaction } from "../../../networks/utils/validateL2TransactionType"
 import { useIsActive } from "../../../hooks/useIsActive"
 
-const renderNavItem = (
-  page: PageComponent,
-  index: number,
-  chainId?: number | string
-) => (
+const renderNavItem = (page: PageComponent, index: number) => (
   <FilterTab
     key={page.route.path}
     as={Link}
@@ -54,11 +49,9 @@ export const MintUnmintNav: FC<
               .filter(
                 (page) =>
                   !!page.route.title &&
-                  isValidL2Transaction(page.route.title?.toUpperCase())
-              )
-              .map((filteredPage, index) =>
-                renderNavItem(filteredPage, index, chainId)
+                  page.route.title.toLowerCase() === "mint"
               )
+              .map((filteredPage, index) => renderNavItem(filteredPage, index))
           : pages
               .filter((page) => !!page.route.title)
               .map((filteredPage, index) => renderNavItem(filteredPage, index))}
diff --git a/src/pages/tBTC/Bridge/Minting/InitiateMinting.tsx b/src/pages/tBTC/Bridge/Minting/InitiateMinting.tsx
index 6d8b13753..9546c0859 100644
--- a/src/pages/tBTC/Bridge/Minting/InitiateMinting.tsx
+++ b/src/pages/tBTC/Bridge/Minting/InitiateMinting.tsx
@@ -16,7 +16,6 @@ import { Toast } from "../../../../components/Toast"
 import { useModal } from "../../../../hooks/useModal"
 import { PosthogButtonId } from "../../../../types/posthog"
 import SubmitTxButton from "../../../../components/SubmitTxButton"
-import { AllowedL2TransactionTypes } from "../../../../networks/enums/networks"
 
 const InitiateMintingComponent: FC<{
   utxo: BitcoinUtxo
@@ -50,7 +49,7 @@ const InitiateMintingComponent: FC<{
     }
 
     getEstimatedDepositFees()
-  }, [depositedAmount, updateState, threshold])
+  }, [depositedAmount, updateState, threshold.tbtc])
 
   const initiateMintTransaction = async () => {
     await revealDeposit(utxo)
@@ -98,7 +97,7 @@ const InitiateMintingComponent: FC<{
       </InfoBox>
       <MintingTransactionDetails />
       <SubmitTxButton
-        l2TransactionType={AllowedL2TransactionTypes.mint}
+        isDisabled={!threshold.tbtc.bridgeContract}
         onSubmit={initiateMintTransaction}
         isFullWidth
         data-ph-capture-attribute-button-name={
diff --git a/src/pages/tBTC/Bridge/Minting/ProvideData.tsx b/src/pages/tBTC/Bridge/Minting/ProvideData.tsx
index 32381c09a..06433ccea 100644
--- a/src/pages/tBTC/Bridge/Minting/ProvideData.tsx
+++ b/src/pages/tBTC/Bridge/Minting/ProvideData.tsx
@@ -18,10 +18,7 @@ import {
   validateBTCAddress,
   validateETHAddress,
 } from "../../../../utils/forms"
-import {
-  AllowedL2TransactionTypes,
-  SupportedChainIds,
-} from "../../../../networks/enums/networks"
+import { SupportedChainIds } from "../../../../networks/enums/networks"
 import {
   getChainIdToNetworkName,
   isL1Network,
@@ -265,7 +262,7 @@ export const ProvideDataComponent: FC<{
       {/* Although the following button doesn't trigger an on-chain transaction, the 
       SubmitTxButton is used here for its built-in TRM Wallet screening validation logic. */}
       <SubmitTxButton
-        l2TransactionType={AllowedL2TransactionTypes.mint}
+        isDisabled={!threshold.tbtc.bridgeContract}
         isLoading={isSubmitButtonLoading}
         loadingText={
           isSubmitButtonLoading ? "Generating deposit address..." : undefined
diff --git a/src/pages/tBTC/Bridge/ResumeDeposit.tsx b/src/pages/tBTC/Bridge/ResumeDeposit.tsx
index 0bb78f1ba..23d3d58b8 100644
--- a/src/pages/tBTC/Bridge/ResumeDeposit.tsx
+++ b/src/pages/tBTC/Bridge/ResumeDeposit.tsx
@@ -39,10 +39,7 @@ import { useIsActive } from "../../../hooks/useIsActive"
 import SubmitTxButton from "../../../components/SubmitTxButton"
 import { useCheckDepositExpirationTime } from "../../../hooks/tbtc/useCheckDepositExpirationTime"
 import { BitcoinNetwork } from "@keep-network/tbtc-v2.ts"
-import {
-  AllowedL2TransactionTypes,
-  SupportedChainIds,
-} from "../../../networks/enums/networks"
+import { SupportedChainIds } from "../../../networks/enums/networks"
 import {
   isL1Network,
   isL2Network,
@@ -141,6 +138,7 @@ export const ResumeDepositPage: PageComponent = () => {
 const ResumeDepositForm: FC<FormikProps<FormValues>> = (props) => {
   const { setValues, getFieldMeta, setFieldError, isSubmitting, values } = props
   const { error } = getFieldMeta("depositParameters")
+  const threshold = useThreshold()
 
   const isError = Boolean(error)
 
@@ -173,11 +171,15 @@ const ResumeDepositForm: FC<FormikProps<FormValues>> = (props) => {
       {/* Although the following button doesn't trigger an on-chain transaction, the 
       SubmitTxButton is used here for its built-in TRM Wallet screening validation logic. */}
       <SubmitTxButton
-        l2TransactionType={AllowedL2TransactionTypes.mint}
         size="lg"
         isFullWidth
         mt="6"
-        isDisabled={!values.depositParameters || isError || isSubmitting}
+        isDisabled={
+          !values.depositParameters ||
+          isError ||
+          isSubmitting ||
+          !threshold.tbtc.bridgeContract
+        }
         type="submit"
         isLoading={isSubmitting}
       >
diff --git a/src/pages/tBTC/Bridge/Unmint.tsx b/src/pages/tBTC/Bridge/Unmint.tsx
index affac648e..29fff14e3 100644
--- a/src/pages/tBTC/Bridge/Unmint.tsx
+++ b/src/pages/tBTC/Bridge/Unmint.tsx
@@ -148,6 +148,7 @@ const UnmintFormBase: FC<UnmintFormBaseProps> = ({
   maxTokenAmount,
   bitcoinNetwork,
 }) => {
+  const threshold = useThreshold()
   const supportedPrefixesText = getBridgeBTCSupportedAddressPrefixesText(
     "unmint",
     bitcoinNetwork
@@ -195,6 +196,7 @@ const UnmintFormBase: FC<UnmintFormBaseProps> = ({
         size="lg"
         isFullWidth
         mt={error ? "0" : "10"}
+        isDisabled={!threshold.tbtc.bridgeContract}
         type="submit"
         isLoading={isSubmitting}
       >
diff --git a/src/store/account/effects.ts b/src/store/account/effects.ts
index 83d730e12..6419ce481 100644
--- a/src/store/account/effects.ts
+++ b/src/store/account/effects.ts
@@ -28,7 +28,14 @@ export const getStakingProviderOperatorInfo = async (
     const stakes = action.payload
     const threshold = listenerApi.extra.threshold
 
-    if (!account || !threshold.staking || !threshold.multiAppStaking) return
+    if (
+      !account ||
+      !threshold.staking ||
+      !threshold.multiAppStaking.ecdsa ||
+      !threshold.multiAppStaking.randomBeacon ||
+      !threshold.multiAppStaking.taco
+    )
+      return
 
     const stake = stakes.find((_: StakeData) =>
       isSameETHAddress(_.stakingProvider, address)
@@ -61,9 +68,9 @@ export const getStakingProviderOperatorInfo = async (
 
     listenerApi.dispatch(
       setMappedOperators({
-        tbtc: mappedOperators.tbtc,
-        randomBeacon: mappedOperators.randomBeacon,
-        taco: mappedOperators.taco,
+        tbtc: mappedOperators.tbtc ?? "",
+        randomBeacon: mappedOperators.randomBeacon ?? "",
+        taco: mappedOperators.taco ?? "",
       })
     )
   } catch (error: any) {
diff --git a/src/store/staking-applications/effects.ts b/src/store/staking-applications/effects.ts
index 113dd344b..f6b4874f9 100644
--- a/src/store/staking-applications/effects.ts
+++ b/src/store/staking-applications/effects.ts
@@ -31,11 +31,16 @@ export const getSupportedAppsEffect = async (
   listenerApi: AppListenerEffectAPI
 ) => {
   const { account } = listenerApi.getState()
-  const { config } = listenerApi.extra.threshold
 
   if (
     !account.chainId ||
-    !isSameChainId(account.chainId, config.ethereum.chainId)
+    !isSameChainId(
+      account.chainId,
+      listenerApi.extra.threshold.config.ethereum.chainId
+    ) ||
+    !listenerApi.extra.threshold.multiAppStaking.ecdsa ||
+    !listenerApi.extra.threshold.multiAppStaking.randomBeacon ||
+    !listenerApi.extra.threshold.multiAppStaking.taco
   )
     return
 
@@ -57,34 +62,36 @@ export const getSupportedAppsEffect = async (
       })
     )
     const data =
-      await listenerApi.extra.threshold.multiAppStaking!.getSupportedAppsAuthParameters()
+      await listenerApi.extra.threshold.multiAppStaking.getSupportedAppsAuthParameters()
     const payload = {
       tbtc: {
-        minimumAuthorization: data.tbtc.minimumAuthorization.toString(),
+        minimumAuthorization: data.tbtc!.minimumAuthorization.toString(),
 
         authorizationDecreaseDelay:
-          data.tbtc.authorizationDecreaseDelay.toString(),
+          data.tbtc!.authorizationDecreaseDelay.toString(),
 
         authorizationDecreaseChangePeriod:
-          data.tbtc.authorizationDecreaseChangePeriod.toString(),
+          data.tbtc!.authorizationDecreaseChangePeriod.toString(),
       },
       randomBeacon: {
-        minimumAuthorization: data.randomBeacon.minimumAuthorization.toString(),
+        minimumAuthorization:
+          data.randomBeacon!.minimumAuthorization.toString(),
 
         authorizationDecreaseDelay:
-          data.randomBeacon.authorizationDecreaseDelay.toString(),
+          data.randomBeacon!.authorizationDecreaseDelay.toString(),
 
         authorizationDecreaseChangePeriod:
-          data.randomBeacon.authorizationDecreaseChangePeriod.toString(),
+          data.randomBeacon!.authorizationDecreaseChangePeriod.toString(),
       },
       taco: {
-        minimumAuthorization: data.taco._minimumAuthorization?.toString() ?? "",
+        minimumAuthorization:
+          data.taco!._minimumAuthorization?.toString() ?? "",
 
         authorizationDecreaseDelay:
-          data.taco.authorizationDecreaseDelay.toString(),
+          data.taco!.authorizationDecreaseDelay.toString(),
 
         authorizationDecreaseChangePeriod:
-          data.taco.authorizationDecreaseChangePeriod.toString(),
+          data.taco!.authorizationDecreaseChangePeriod.toString(),
       },
     }
     listenerApi.dispatch(
@@ -135,11 +142,14 @@ export const getSupportedAppsStakingProvidersData = async (
   listenerApi: AppListenerEffectAPI
 ) => {
   const { account } = listenerApi.getState()
-  const { config } = listenerApi.extra.threshold
+  const threshold = listenerApi.extra.threshold
 
   if (
     !account.chainId ||
-    !isSameChainId(account.chainId, config.ethereum.chainId)
+    !isSameChainId(account.chainId, threshold.config.ethereum.chainId) ||
+    !threshold.multiAppStaking.ecdsa ||
+    !threshold.multiAppStaking.randomBeacon ||
+    !threshold.multiAppStaking.taco
   )
     return
 
@@ -155,19 +165,19 @@ export const getSupportedAppsStakingProvidersData = async (
 
     await getKeepStakingAppStakingProvidersData(
       stakingProviders,
-      listenerApi.extra.threshold.multiAppStaking.ecdsa,
+      listenerApi.extra.threshold.multiAppStaking.ecdsa!,
       "tbtc",
       listenerApi
     )
     await getKeepStakingAppStakingProvidersData(
       stakingProviders,
-      listenerApi.extra.threshold.multiAppStaking.randomBeacon,
+      listenerApi.extra.threshold.multiAppStaking.randomBeacon!,
       "randomBeacon",
       listenerApi
     )
     await getKeepStakingAppStakingProvidersData(
       stakingProviders,
-      listenerApi.extra.threshold.multiAppStaking.taco,
+      listenerApi.extra.threshold.multiAppStaking.taco!,
       "taco",
       listenerApi
     )
diff --git a/src/store/staking/effects.ts b/src/store/staking/effects.ts
index 24b7597a9..4180d3955 100644
--- a/src/store/staking/effects.ts
+++ b/src/store/staking/effects.ts
@@ -57,7 +57,7 @@ const fetchStake = async (
   listenerApi: AppListenerEffectAPI
 ) => {
   const stake =
-    await listenerApi.extra.threshold.staking!.getStakeByStakingProvider(
+    await listenerApi.extra.threshold.staking.getStakeByStakingProvider(
       stakingProvider
     )
 
diff --git a/src/store/tbtc/effects.ts b/src/store/tbtc/effects.ts
index 7046f12f3..2e0626361 100644
--- a/src/store/tbtc/effects.ts
+++ b/src/store/tbtc/effects.ts
@@ -21,13 +21,15 @@ export const fetchBridgeactivityEffect = async (
 ) => {
   const { account } = listenerApi.getState()
   const { depositor } = action.payload
-  const { config } = listenerApi.extra.threshold
 
   if (
     !isAddress(depositor) ||
     isAddressZero(depositor) ||
     !account.chainId ||
-    !isSameChainId(account.chainId, config.ethereum.chainId)
+    !isSameChainId(
+      account.chainId,
+      listenerApi.extra.threshold.config.ethereum.chainId
+    )
   )
     return
 
diff --git a/src/threshold-ts/applications/index.ts b/src/threshold-ts/applications/index.ts
index cecbb2985..d3e5530df 100644
--- a/src/threshold-ts/applications/index.ts
+++ b/src/threshold-ts/applications/index.ts
@@ -283,8 +283,8 @@ export class Application implements IApplication {
   ): Promise<StakingProviderAppInfo> => {
     const calls: ContractCall[] = [
       {
-        interface: this._staking.stakingContract.interface,
-        address: this._staking.stakingContract.address,
+        interface: this._staking.stakingContract!.interface,
+        address: this._staking.stakingContract!.address,
         method: "authorizedStake",
         args: [stakingProvider, this.address],
       },
diff --git a/src/threshold-ts/index.ts b/src/threshold-ts/index.ts
index 3a44db39c..94ecd70c0 100644
--- a/src/threshold-ts/index.ts
+++ b/src/threshold-ts/index.ts
@@ -4,14 +4,13 @@ import { IStaking, Staking } from "./staking"
 import { ITBTC, TBTC } from "./tbtc"
 import { ThresholdConfig } from "./types"
 import { IVendingMachines, VendingMachines } from "./vending-machine"
-import { isL1Network } from "../networks/utils"
 
 export class Threshold {
   config!: ThresholdConfig
-  multicall!: IMulticall | null
-  staking!: IStaking | null
-  multiAppStaking!: MultiAppStaking | null
-  vendingMachines!: IVendingMachines | null
+  multicall!: IMulticall
+  staking!: IStaking
+  multiAppStaking!: MultiAppStaking
+  vendingMachines!: IVendingMachines
   tbtc!: ITBTC
 
   constructor(config: ThresholdConfig) {
@@ -22,24 +21,14 @@ export class Threshold {
     this.config = config
     const { ethereum, bitcoin } = config
 
-    if (isL1Network(ethereum.chainId)) {
-      this.multicall = new Multicall(ethereum)
-      this.vendingMachines = new VendingMachines(ethereum)
-      this.staking = new Staking(ethereum, this.multicall, this.vendingMachines)
-      this.multiAppStaking = new MultiAppStaking(
-        this.staking,
-        this.multicall,
-        ethereum
-      )
-    } else {
-      this.staking = null
-      this.multiAppStaking = null
-      this.vendingMachines = null
-      this.multicall = null
-      console.warn(
-        `Contracts like VendingMachines, Multicall and Staking are not available on chain ID ${ethereum.chainId}.`
-      )
-    }
+    this.multicall = new Multicall(ethereum)
+    this.vendingMachines = new VendingMachines(ethereum)
+    this.staking = new Staking(ethereum, this.multicall, this.vendingMachines)
+    this.multiAppStaking = new MultiAppStaking(
+      this.staking,
+      this.multicall,
+      ethereum
+    )
     this.tbtc = new TBTC(ethereum, bitcoin)
   }
 
diff --git a/src/threshold-ts/mas/index.ts b/src/threshold-ts/mas/index.ts
index 7dffb2ed1..8b4e01113 100644
--- a/src/threshold-ts/mas/index.ts
+++ b/src/threshold-ts/mas/index.ts
@@ -23,9 +23,9 @@ export interface MappedOperatorsForStakingProvider {
 export class MultiAppStaking {
   private _staking: IStaking
   private _multicall: IMulticall
-  public readonly randomBeacon: IApplication
-  public readonly ecdsa: IApplication
-  public readonly taco: IApplication
+  public readonly randomBeacon: IApplication | null
+  public readonly ecdsa: IApplication | null
+  public readonly taco: IApplication | null
 
   constructor(
     staking: IStaking,
@@ -39,99 +39,140 @@ export class MultiAppStaking {
       config.chainId,
       config.shouldUseTestnetDevelopmentContracts
     )
-    this.randomBeacon = new Application(this._staking, this._multicall, {
-      address: randomBeaconArtifact.address,
-      abi: randomBeaconArtifact.abi,
-      ...config,
-    })
+    this.randomBeacon = randomBeaconArtifact
+      ? new Application(this._staking, this._multicall, {
+          address: randomBeaconArtifact.address,
+          abi: randomBeaconArtifact.abi,
+          ...config,
+        })
+      : null
     const walletRegistryArtifacts = getArtifact(
       "WalletRegistry",
       config.chainId,
       config.shouldUseTestnetDevelopmentContracts
     )
-    this.ecdsa = new Application(this._staking, this._multicall, {
-      address: walletRegistryArtifacts.address,
-      abi: walletRegistryArtifacts.abi,
-      ...config,
-    })
+    this.ecdsa = walletRegistryArtifacts
+      ? new Application(this._staking, this._multicall, {
+          address: walletRegistryArtifacts.address,
+          abi: walletRegistryArtifacts.abi,
+          ...config,
+        })
+      : null
     const tacoRegistryArtifacts = getArtifact(
       "TacoRegistry",
       config.chainId,
       config.shouldUseTestnetDevelopmentContracts
     )
-    this.taco = new Application(this._staking, this._multicall, {
-      address: tacoRegistryArtifacts.address,
-      abi: tacoRegistryArtifacts.abi,
-      ...config,
-    })
+    this.taco = tacoRegistryArtifacts
+      ? new Application(this._staking, this._multicall, {
+          address: tacoRegistryArtifacts.address,
+          abi: tacoRegistryArtifacts.abi,
+          ...config,
+        })
+      : null
   }
 
-  async getSupportedAppsAuthParameters(): Promise<SupportedAppAuthorizationParameters> {
-    const calls: ContractCall[] = [
-      {
+  async getSupportedAppsAuthParameters(): Promise<
+    Partial<SupportedAppAuthorizationParameters>
+  > {
+    const calls: ContractCall[] = []
+    const results: Partial<SupportedAppAuthorizationParameters> = {}
+
+    let index = 0
+
+    if (this.ecdsa) {
+      calls.push({
         interface: this.ecdsa.contract.interface,
         address: this.ecdsa.address,
         method: "authorizationParameters",
         args: [],
-      },
-      {
+      })
+    }
+
+    if (this.randomBeacon) {
+      calls.push({
         interface: this.randomBeacon.contract.interface,
         address: this.randomBeacon.address,
         method: "authorizationParameters",
         args: [],
-      },
-      {
+      })
+    }
+
+    if (this.taco) {
+      calls.push({
         interface: this.taco.contract.interface,
         address: this.taco.address,
         method: "authorizationParameters",
         args: [],
-      },
-    ]
-
-    const [
-      tbtcMinAuthorizationParams,
-      randomBeaconMinAuthorizationParams,
-      tacoMinAuthorizationParams,
-    ] = await this._multicall.aggregate(calls)
-
-    return {
-      tbtc: tbtcMinAuthorizationParams,
-      randomBeacon: randomBeaconMinAuthorizationParams,
-      taco: tacoMinAuthorizationParams,
+      })
+    }
+
+    const callResults = await this._multicall.aggregate(calls)
+
+    if (this.ecdsa) {
+      results.tbtc = callResults[index++]
+    }
+
+    if (this.randomBeacon) {
+      results.randomBeacon = callResults[index++]
+    }
+
+    if (this.taco) {
+      results.taco = callResults[index++]
     }
+
+    return results
   }
 
   async getMappedOperatorsForStakingProvider(
     stakingProvider: string
-  ): Promise<MappedOperatorsForStakingProvider> {
-    const calls: ContractCall[] = [
-      {
+  ): Promise<Partial<MappedOperatorsForStakingProvider>> {
+    const calls: ContractCall[] = []
+    const results: Partial<MappedOperatorsForStakingProvider> = {}
+
+    let index = 0
+
+    if (this.ecdsa) {
+      calls.push({
         interface: this.ecdsa.contract.interface,
         address: this.ecdsa.address,
         method: "stakingProviderToOperator",
         args: [stakingProvider],
-      },
-      {
+      })
+    }
+
+    if (this.randomBeacon) {
+      calls.push({
         interface: this.randomBeacon.contract.interface,
         address: this.randomBeacon.address,
         method: "stakingProviderToOperator",
         args: [stakingProvider],
-      },
-      {
+      })
+    }
+
+    if (this.taco) {
+      calls.push({
         interface: this.taco.contract.interface,
         address: this.taco.address,
         method: "stakingProviderToOperator",
         args: [stakingProvider],
-      },
-    ]
+      })
+    }
+
+    const callResults = await this._multicall.aggregate(calls)
+
+    if (this.ecdsa) {
+      results.tbtc = callResults[index++].toString()
+    }
 
-    const [mappedOperatorTbtc, mappedOperatorRandomBeacon, mappedOperatorTaco] =
-      await this._multicall.aggregate(calls)
+    if (this.randomBeacon) {
+      results.randomBeacon = callResults[index++].toString()
+    }
 
-    return {
-      tbtc: mappedOperatorTbtc.toString(),
-      randomBeacon: mappedOperatorRandomBeacon.toString(),
-      taco: mappedOperatorTaco.toString(),
+    if (this.taco) {
+      results.taco = callResults[index++].toString()
     }
+
+    return results
   }
 }
diff --git a/src/threshold-ts/staking/index.ts b/src/threshold-ts/staking/index.ts
index 7f8c50487..686fd7716 100644
--- a/src/threshold-ts/staking/index.ts
+++ b/src/threshold-ts/staking/index.ts
@@ -1,4 +1,10 @@
-import { BigNumber, BigNumberish, Contract, ContractTransaction } from "ethers"
+import {
+  BigNumber,
+  BigNumberish,
+  Contract,
+  ContractTransaction,
+  constants,
+} from "ethers"
 import { ContractCall, IMulticall } from "../multicall"
 import { EthereumConfig } from "../types"
 import {
@@ -46,8 +52,8 @@ interface OwnerRefreshedResult {
 }
 
 export interface IStaking {
-  stakingContract: Contract
-  legacyNuStakingContract: Contract
+  stakingContract: Contract | null
+  legacyNuStakingContract: Contract | null
   STAKING_CONTRACT_DEPLOYMENT_BLOCK: number
   /**
    * Returns the authorized stake amount of the staking provider for the application.
@@ -65,7 +71,7 @@ export interface IStaking {
    * provider’s authorizer.
    * @param stakingProvider Staking provider address.
    * @param application Application address.
-   * @param amount Amount to authrozie.
+   * @param amount Amount to authorize.
    * @returns Ethers `ContractTransaction` instance.
    */
   increaseAuthorization(
@@ -104,7 +110,7 @@ export interface IStaking {
   getOwnerStakes(owner: string): Promise<Array<Stake>>
 
   /**
-   * Returns the current and outdated staking providers for a givne owner
+   * Returns the current and outdated staking providers for a given owner
    * address. The outdated array is necessary while fetching all owner stakes.
    * We need to filter out outdated staking providers eg. the `Staked` event was
    * emitted with the owner address that we are looking for but then the owner
@@ -117,10 +123,10 @@ export interface IStaking {
 }
 
 export class Staking implements IStaking {
-  private _staking: Contract
+  private _staking: Contract | null
   private _multicall: IMulticall
-  private _legacyKeepStaking: Contract
-  private _legacyNuStaking: Contract
+  private _legacyKeepStaking: Contract | null
+  private _legacyNuStaking: Contract | null
   private _vendingMachines: IVendingMachines
   public readonly STAKING_CONTRACT_DEPLOYMENT_BLOCK: number
 
@@ -137,34 +143,40 @@ export class Staking implements IStaking {
       config.chainId,
       config.shouldUseTestnetDevelopmentContracts
     )
-    this._staking = getContract(
-      stakingArtifact.address,
-      stakingArtifact.abi,
-      config.providerOrSigner,
-      config.account
-    )
+    this._staking = stakingArtifact
+      ? getContract(
+          stakingArtifact.address,
+          stakingArtifact.abi,
+          config.providerOrSigner,
+          config.account
+        )
+      : null
     const legacyKeepStakingArtifact = getArtifact(
       "LegacyKeepStaking",
       config.chainId,
       config.shouldUseTestnetDevelopmentContracts
     )
-    this._legacyKeepStaking = getContract(
-      legacyKeepStakingArtifact.address,
-      legacyKeepStakingArtifact.abi,
-      config.providerOrSigner,
-      config.account
-    )
+    this._legacyKeepStaking = legacyKeepStakingArtifact
+      ? getContract(
+          legacyKeepStakingArtifact.address,
+          legacyKeepStakingArtifact.abi,
+          config.providerOrSigner,
+          config.account
+        )
+      : null
     const nuCypherStakingEscrowArtifact = getArtifact(
       "NuCypherStakingEscrow",
       config.chainId,
       config.shouldUseTestnetDevelopmentContracts
     )
-    this._legacyNuStaking = getContract(
-      nuCypherStakingEscrowArtifact.address,
-      nuCypherStakingEscrowArtifact.abi,
-      config.providerOrSigner,
-      config.account
-    )
+    this._legacyNuStaking = nuCypherStakingEscrowArtifact
+      ? getContract(
+          nuCypherStakingEscrowArtifact.address,
+          nuCypherStakingEscrowArtifact.abi,
+          config.providerOrSigner,
+          config.account
+        )
+      : null
     this._multicall = multicall
     this._vendingMachines = vendingMachines
   }
@@ -173,6 +185,11 @@ export class Staking implements IStaking {
     stakingProvider: string,
     application: string
   ): Promise<BigNumber> {
+    if (!this._staking) {
+      throw new Error(
+        "Staking contract is not available on the current network"
+      )
+    }
     return this._staking.authorizedStake(stakingProvider, application)
   }
 
@@ -189,6 +206,11 @@ export class Staking implements IStaking {
     application: string,
     amount: BigNumberish
   ): Promise<ContractTransaction> => {
+    if (!this._staking) {
+      throw new Error(
+        "Staking contract is not available on the current network"
+      )
+    }
     return await this._staking.increaseAuthorization(
       stakingProvider,
       application,
@@ -200,51 +222,76 @@ export class Staking implements IStaking {
     stakingProvider: string,
     stakeType?: StakeType
   ): Promise<Stake> => {
-    const multicalls: ContractCall[] = [
-      {
-        interface: this._staking.interface,
-        address: this._staking.address,
-        method: "rolesOf",
-        args: [stakingProvider],
-      },
-      {
-        interface: this._staking.interface,
-        address: this._staking.address,
-        method: "stakes",
-        args: [stakingProvider],
-      },
-      {
+    const multicalls: ContractCall[] = []
+
+    if (this._staking) {
+      multicalls.push(
+        ...[
+          {
+            interface: this._staking.interface,
+            address: this._staking.address,
+            method: "rolesOf",
+            args: [stakingProvider],
+          },
+          {
+            interface: this._staking.interface,
+            address: this._staking.address,
+            method: "stakes",
+            args: [stakingProvider],
+          },
+        ]
+      )
+    }
+
+    // Only add the eligibleStake call if _legacyKeepStaking is available
+    if (this._staking && this._legacyKeepStaking) {
+      multicalls.push({
         interface: this._legacyKeepStaking.interface,
         address: this._legacyKeepStaking.address,
         method: "eligibleStake",
         args: [stakingProvider, this._staking.address],
-      },
-    ]
+      })
+    }
+
+    const results = await this._multicall.aggregate(multicalls)
 
-    const [rolesOf, stakes, { balance: eligibleKeepStake }] =
-      await this._multicall.aggregate(multicalls)
+    const rolesOf = results[0]
+    const stakes = results[1]
+    const eligibleKeepStakeResult = this._legacyKeepStaking
+      ? results[2]
+      : { balance: ZERO }
 
     const { owner, authorizer, beneficiary } = rolesOf
 
     const { tStake, keepInTStake, nuInTStake } = stakes
 
-    // The NU staker can have only one stake.
-    const { stakingProvider: nuStakingProvider, value: nuStake } =
-      await this._legacyNuStaking.stakerInfo(owner)
+    const eligibleKeepStake = eligibleKeepStakeResult.balance || ZERO
 
-    const possibleNuTopUpInT =
+    let nuStakingProvider = constants.AddressZero
+    let nuStake = ZERO
+
+    if (this._legacyNuStaking) {
+      const { stakingProvider: nuProvider, value: nuValue } =
+        await this._legacyNuStaking.stakerInfo(owner)
+      nuStakingProvider = nuProvider
+      nuStake = nuValue
+    }
+
+    const isNuStakingProviderValid =
       isAddress(nuStakingProvider) &&
       isSameETHAddress(stakingProvider, nuStakingProvider)
-        ? BigNumber.from(
-            (await this._vendingMachines.nu.convertToT(nuStake.toString()))
-              .tAmount
-          ).sub(BigNumber.from(nuInTStake.toString()))
-        : ZERO
 
-    const keepEligableStakeInT = (
+    const possibleNuTopUpInT = isNuStakingProviderValid
+      ? BigNumber.from(
+          (await this._vendingMachines.nu.convertToT(nuStake.toString()))
+            .tAmount
+        ).sub(BigNumber.from(nuInTStake.toString()))
+      : ZERO
+
+    const keepEligibleStakeInT = (
       await this._vendingMachines.keep.convertToT(eligibleKeepStake.toString())
     ).tAmount
-    const possibleKeepTopUpInT = BigNumber.from(keepEligableStakeInT).sub(
+    const possibleKeepTopUpInT = BigNumber.from(keepEligibleStakeInT).sub(
       BigNumber.from(keepInTStake)
     )
 
@@ -270,12 +317,24 @@ export class Staking implements IStaking {
     application: string,
     amount: BigNumberish
   ): Promise<ContractTransaction> => {
+    if (!this._staking) {
+      throw new Error(
+        "Staking contract is not available on the current network"
+      )
+    }
     return await this._staking[
       "requestAuthorizationDecrease(address,address,uint96)"
     ](stakingProvider, application, amount)
   }
 
   rolesOf = async (stakingProvider: string): Promise<RolesOf> => {
+    if (!this._staking) {
+      return {
+        owner: constants.AddressZero,
+        beneficiary: constants.AddressZero,
+        authorizer: constants.AddressZero,
+      }
+    }
     const rolesOf = await this._staking.rolesOf(stakingProvider)
     return {
       owner: rolesOf.owner,
@@ -285,13 +344,17 @@ export class Staking implements IStaking {
   }
 
   getOwnerStakes = async (owner: string): Promise<Array<Stake>> => {
-    const stakes = (
-      await getContractPastEvents(this._staking, {
-        eventName: "Staked",
-        fromBlock: this.STAKING_CONTRACT_DEPLOYMENT_BLOCK,
-        filterParams: [undefined, owner],
-      })
-    )
+    if (!this._staking) {
+      return []
+    }
+
+    const stakesEvents = await getContractPastEvents(this._staking, {
+      eventName: "Staked",
+      fromBlock: this.STAKING_CONTRACT_DEPLOYMENT_BLOCK,
+      filterParams: [undefined, owner],
+    })
+
+    const stakes = stakesEvents
       .map((event) => ({
         stakingProvider: event.args?.stakingProvider,
         stakeType: event.args?.stakeType,
@@ -319,6 +382,10 @@ export class Staking implements IStaking {
   findRefreshedKeepStakes = async (
     owner: string
   ): Promise<OwnerRefreshedResult> => {
+    if (!this._staking) {
+      return { current: [], outdated: [] }
+    }
+
     // Find all events where the `owner` was set as a new owner or old owner of
     // the stake.
     const ownerRefreshedEventsFilteredByNewOwner = await getContractPastEvents(
@@ -351,10 +418,14 @@ export class Staking implements IStaking {
       new Set(ownerRefreshedEvents.map((event) => event?.args?.stakingProvider))
     )
 
+    if (possibleStakingProviders.length === 0) {
+      return { current: [], outdated: [] }
+    }
+
     const multicalls: ContractCall[] = possibleStakingProviders.map(
       (stakingProvider) => ({
-        address: this._staking.address,
-        interface: this._staking.interface,
+        address: this._staking!.address,
+        interface: this._staking!.interface,
         method: "rolesOf",
         args: [stakingProvider],
       })
@@ -366,12 +437,14 @@ export class Staking implements IStaking {
     // iterating through the `OwnerRefreshed` events and comparing the
     // `oldOwner` and `newOwner` params from that event, we can just check the
     // current owner for a given staking provider by calling `rolesOf`.
-    const rolesOf: RolesOf[] = await this._multicall.aggregate(multicalls)
+    const rolesOfResults: RolesOf[] = await this._multicall.aggregate(
+      multicalls
+    )
 
     // The current staking providers for a given `owner` address.
-    const stakingProviders: string[] = rolesOf
-      .map((_, index) => ({
-        ..._,
+    const stakingProviders: string[] = rolesOfResults
+      .map((rolesOf, index) => ({
+        ...rolesOf,
         stakingProvider: possibleStakingProviders[index],
       }))
       .filter((rolesOf) => isSameETHAddress(rolesOf.owner, owner))
diff --git a/src/threshold-ts/tbtc/index.ts b/src/threshold-ts/tbtc/index.ts
index 742563e07..40b533ccd 100644
--- a/src/threshold-ts/tbtc/index.ts
+++ b/src/threshold-ts/tbtc/index.ts
@@ -207,13 +207,13 @@ export interface ITBTC {
    */
   readonly bitcoinNetwork: BitcoinNetwork
 
-  readonly bridgeContract: Contract
+  readonly bridgeContract: Contract | null
 
-  readonly vaultContract: Contract
+  readonly vaultContract: Contract | null
 
-  readonly tokenContract: Contract
+  readonly tokenContract: Contract | null
 
-  readonly l1BitcoinDepositorContract: Contract | undefined
+  readonly l1BitcoinDepositorContract: Contract | null
 
   readonly deposit: Deposit | undefined
 
@@ -464,10 +464,10 @@ export interface ITBTC {
 }
 
 export class TBTC implements ITBTC {
-  private _bridgeContract: Contract
-  private _tbtcVaultContract: Contract
-  private _tokenContract: Contract
-  private _l1BitcoinDepositorContract: Contract | undefined
+  private _bridgeContract: Contract | null
+  private _tbtcVaultContract: Contract | null
+  private _tokenContract: Contract | null
+  private _l1BitcoinDepositorContract: Contract | null = null
   private _multicall: IMulticall
   private _bitcoinClient: BitcoinClient
   private _ethereumConfig: EthereumConfig
@@ -519,13 +519,13 @@ export class TBTC implements ITBTC {
       mainnetOrTestnetEthereumChainId
     )
 
-    const tbtcVaultArtifact = getArtifact(
-      "TBTCVault",
+    const bridgeArtifact = getArtifact(
+      "Bridge",
       mainnetOrTestnetEthereumChainId,
       shouldUseTestnetDevelopmentContracts
     )
-    const bridgeArtifact = getArtifact(
-      "Bridge",
+    const tbtcVaultArtifact = getArtifact(
+      "TBTCVault",
       mainnetOrTestnetEthereumChainId,
       shouldUseTestnetDevelopmentContracts
     )
@@ -535,24 +535,30 @@ export class TBTC implements ITBTC {
       shouldUseTestnetDevelopmentContracts
     )
 
-    this._bridgeContract = getContract(
-      bridgeArtifact.address,
-      bridgeArtifact.abi,
-      defaultOrConnectedProvider,
-      account
-    )
-    this._tbtcVaultContract = getContract(
-      tbtcVaultArtifact.address,
-      tbtcVaultArtifact.abi,
-      defaultOrConnectedProvider,
-      account
-    )
-    this._tokenContract = getContract(
-      tbtcTokenArtifact.address,
-      tbtcTokenArtifact.abi,
-      defaultOrConnectedProvider,
-      account
-    )
+    this._bridgeContract = bridgeArtifact
+      ? getContract(
+          bridgeArtifact.address,
+          bridgeArtifact.abi,
+          defaultOrConnectedProvider,
+          account
+        )
+      : null
+    this._tbtcVaultContract = tbtcVaultArtifact
+      ? getContract(
+          tbtcVaultArtifact.address,
+          tbtcVaultArtifact.abi,
+          defaultOrConnectedProvider,
+          account
+        )
+      : null
+    this._tokenContract = tbtcTokenArtifact
+      ? getContract(
+          tbtcTokenArtifact.address,
+          tbtcTokenArtifact.abi,
+          defaultOrConnectedProvider,
+          account
+        )
+      : null
     this._multicall = new Multicall({
       ...ethereumConfig,
       providerOrSigner: defaultOrConnectedProvider,
@@ -563,15 +569,18 @@ export class TBTC implements ITBTC {
       const networkName = getChainIdToNetworkName(chainId)
       const l1BitcoinDepositorArtifact = getArtifact(
         `${networkName}L1BitcoinDepositor` as ArtifactNameType,
-        mainnetOrTestnetEthereumChainId
+        mainnetOrTestnetEthereumChainId,
+        shouldUseTestnetDevelopmentContracts
       )
 
-      this._l1BitcoinDepositorContract = getContract(
-        l1BitcoinDepositorArtifact.address,
-        l1BitcoinDepositorArtifact.abi,
-        defaultOrConnectedProvider,
-        account
-      )
+      this._l1BitcoinDepositorContract = l1BitcoinDepositorArtifact
+        ? getContract(
+            l1BitcoinDepositorArtifact.address,
+            l1BitcoinDepositorArtifact.abi,
+            defaultOrConnectedProvider,
+            account
+          )
+        : null
     }
 
     // @ts-ignore
@@ -1000,7 +1009,13 @@ export class TBTC implements ITBTC {
       chainId,
       this._ethereumConfig.shouldUseTestnetDevelopmentContracts
     )
-    const deposits = await getContractPastEvents(this._bridgeContract!, {
+
+    if (!bridgeArtifact || !this._bridgeContract) {
+      console.warn("Bridge contract is not initialized.")
+      return []
+    }
+
+    const deposits = await getContractPastEvents(this._bridgeContract, {
       fromBlock: bridgeArtifact.receipt.blockNumber,
       filterParams: [null, null, depositor],
       eventName: "DepositRevealed",
@@ -1173,7 +1188,13 @@ export class TBTC implements ITBTC {
       )}L1BitcoinDepositor` as ArtifactNameType,
       getMainnetOrTestnetChainId(this.ethereumChainId)
     )
-    return await getContractPastEvents(this._l1BitcoinDepositorContract!, {
+
+    if (!l1BitcoinDepositorArtifact || !this._l1BitcoinDepositorContract) {
+      console.warn("L1 Bitcoin Depositor contract is not initialized.")
+      return []
+    }
+
+    return await getContractPastEvents(this._l1BitcoinDepositorContract, {
       fromBlock: l1BitcoinDepositorArtifact.receipt.blockNumber,
       filterParams: [null, l2DepositOwner, l1Sender],
       eventName: "DepositFinalized",
@@ -1193,6 +1214,11 @@ export class TBTC implements ITBTC {
       getMainnetOrTestnetChainId(this.ethereumChainId)
     )
 
+    if (!l1BitcoinDepositorArtifact || !this._l1BitcoinDepositorContract) {
+      console.warn("L1 Bitcoin Depositor contract is not initialized.")
+      return []
+    }
+
     return await getContractPastEvents(this._l1BitcoinDepositorContract!, {
       fromBlock: l1BitcoinDepositorArtifact.receipt.blockNumber,
       filterParams: [null, l2DepositOwner, l1Sender],
@@ -1206,7 +1232,7 @@ export class TBTC implements ITBTC {
     const { optimisticMintingFeeDivisor } = await this._getDepositFees()
 
     const deposits = (
-      await this._multicall!.aggregate(
+      await this._multicall.aggregate(
         depositKeys.map((depositKey) => ({
           interface: this.bridgeContract!.interface,
           address: this.bridgeContract!.address,
@@ -1268,7 +1294,13 @@ export class TBTC implements ITBTC {
       chainId,
       this._ethereumConfig.shouldUseTestnetDevelopmentContracts
     )
-    return await getContractPastEvents(this._tbtcVaultContract!, {
+
+    if (!tbtcVaultArtifact || !this._tbtcVaultContract) {
+      console.warn("TBTC vault contract is not initialized.")
+      return []
+    }
+
+    return await getContractPastEvents(this._tbtcVaultContract, {
       fromBlock: tbtcVaultArtifact.receipt.blockNumber,
       filterParams: [null, depositKeys, depositor],
       eventName: "OptimisticMintingFinalized",
@@ -1285,7 +1317,13 @@ export class TBTC implements ITBTC {
       chainId,
       this._ethereumConfig.shouldUseTestnetDevelopmentContracts
     )
-    return getContractPastEvents(this._tbtcVaultContract!, {
+
+    if (!tbtcVaultArtifact || !this._tbtcVaultContract) {
+      console.warn("TBTC vault contract is not initialized.")
+      return []
+    }
+
+    return getContractPastEvents(this._tbtcVaultContract, {
       fromBlock: tbtcVaultArtifact.receipt.blockNumber,
       filterParams: [null, depositKeys],
       eventName: "OptimisticMintingCancelled",
diff --git a/src/threshold-ts/utils/contract.ts b/src/threshold-ts/utils/contract.ts
index 03e94eac8..887fbd972 100644
--- a/src/threshold-ts/utils/contract.ts
+++ b/src/threshold-ts/utils/contract.ts
@@ -73,52 +73,59 @@ type ArtifactType = {
   abi: ContractInterface
   [key: string]: any
 }
+type ContractArtifacts = {
+  [chainId in SupportedChainIds]?: {
+    [artifactName in ArtifactNameType]?: ArtifactType
+  }
+}
 
-const mainnetArtifacts = new Map<ArtifactNameType, ArtifactType>([
-  ["ArbitrumL1BitcoinDepositor", ArbitrumL1BitcoinDepositorArtifactMainnet],
-  ["TacoRegistry", TacoRegistryArtifactMainnet],
-  ["LegacyKeepStaking", LegacyKeepStakingArtifactMainnet],
-  ["RandomBeacon", RandomBeaconArtifactMainnet],
-  ["TokenStaking", StakingArtifactMainnet],
-  ["Bridge", BridgeArtifactMainnet],
-  ["NuCypherStakingEscrow", NuCypherStakingEscrowMainnet],
-  ["NuCypherToken", NuCypherTokenMainnet],
-  ["TBTCVault", TbtcVaultArtifactMainnet],
-  ["TBTC", TbtcTokenArtifactMainnet],
-  ["WalletRegistry", WalletRegistryArtifactMainnet],
-  ["VendingMachineKeep", VendingMachineKeepMainnet],
-  ["VendingMachineNuCypher", VendingMachineNuCypherMainnet],
-])
-const sepoliaArtifacts = new Map<ArtifactNameType, ArtifactType>([
-  ["ArbitrumL1BitcoinDepositor", ArbitrumL1BitcoinDepositorArtifactSepolia],
-  ["BaseL1BitcoinDepositor", BaseL1BitcoinDepositorArtifactSepolia],
-  ["TacoRegistry", TacoRegistryArtifactSepolia],
-  ["LegacyKeepStaking", LegacyKeepStakingArtifactSepolia],
-  ["RandomBeacon", RandomBeaconArtifactSepolia],
-  ["TokenStaking", StakingArtifactSepolia],
-  ["Bridge", BridgeArtifactSepolia],
-  ["NuCypherStakingEscrow", NuCypherStakingEscrowSepolia],
-  ["NuCypherToken", NuCypherTokenSepolia],
-  ["TBTCVault", TbtcVaultArtifactSepolia],
-  ["TBTC", TbtcTokenArtifactSepolia],
-  ["WalletRegistry", WalletRegistryArtifactSepolia],
-  ["VendingMachineKeep", VendingMachineKeepSepolia],
-  ["VendingMachineNuCypher", VendingMachineNuCypherSepolia],
-])
-const testnetDevelopmentArtifacts = new Map<ArtifactNameType, ArtifactType>([
-  ["TacoRegistry", TacoRegistryArtifactDappDevelopmentSepolia],
-  ["LegacyKeepStaking", LegacyKeepStakingArtifactDappDevelopmentSepolia],
-  ["RandomBeacon", RandomBeaconArtifactDappDevelopmentSepolia],
-  ["TokenStaking", StakingArtifactDappDevelopmentSepolia],
-  ["Bridge", BridgeArtifactDappDevelopmentSepolia],
-  ["NuCypherStakingEscrow", NuCypherStakingEscrowDappDevelopmentSepolia],
-  ["NuCypherToken", NuCypherTokenDappDevelopmentSepolia],
-  ["TBTCVault", TbtcVaultArtifactDappDevelopmentSepolia],
-  ["TBTC", TbtcTokenArtifactDappDevelopmentSepolia],
-  ["WalletRegistry", WalletRegistryArtifactDappDevelopmentSepolia],
-  ["VendingMachineKeep", VendingMachineKeepDappDevelopmentSepolia],
-  ["VendingMachineNuCypher", VendingMachineNuCypherDappDevelopmentSepolia],
-])
+const contractArtifacts: ContractArtifacts = {
+  [SupportedChainIds.Ethereum]: {
+    ArbitrumL1BitcoinDepositor: ArbitrumL1BitcoinDepositorArtifactMainnet,
+    TacoRegistry: TacoRegistryArtifactMainnet,
+    LegacyKeepStaking: LegacyKeepStakingArtifactMainnet,
+    RandomBeacon: RandomBeaconArtifactMainnet,
+    TokenStaking: StakingArtifactMainnet,
+    Bridge: BridgeArtifactMainnet,
+    NuCypherStakingEscrow: NuCypherStakingEscrowMainnet,
+    NuCypherToken: NuCypherTokenMainnet,
+    TBTCVault: TbtcVaultArtifactMainnet,
+    TBTC: TbtcTokenArtifactMainnet,
+    WalletRegistry: WalletRegistryArtifactMainnet,
+    VendingMachineKeep: VendingMachineKeepMainnet,
+    VendingMachineNuCypher: VendingMachineNuCypherMainnet,
+  },
+  [SupportedChainIds.Sepolia]: {
+    ArbitrumL1BitcoinDepositor: ArbitrumL1BitcoinDepositorArtifactSepolia,
+    BaseL1BitcoinDepositor: BaseL1BitcoinDepositorArtifactSepolia,
+    TacoRegistry: TacoRegistryArtifactSepolia,
+    LegacyKeepStaking: LegacyKeepStakingArtifactSepolia,
+    RandomBeacon: RandomBeaconArtifactSepolia,
+    TokenStaking: StakingArtifactSepolia,
+    Bridge: BridgeArtifactSepolia,
+    NuCypherStakingEscrow: NuCypherStakingEscrowSepolia,
+    NuCypherToken: NuCypherTokenSepolia,
+    TBTCVault: TbtcVaultArtifactSepolia,
+    TBTC: TbtcTokenArtifactSepolia,
+    WalletRegistry: WalletRegistryArtifactSepolia,
+    VendingMachineKeep: VendingMachineKeepSepolia,
+    VendingMachineNuCypher: VendingMachineNuCypherSepolia,
+  },
+  [SupportedChainIds.Localhost]: {
+    TacoRegistry: TacoRegistryArtifactDappDevelopmentSepolia,
+    LegacyKeepStaking: LegacyKeepStakingArtifactDappDevelopmentSepolia,
+    RandomBeacon: RandomBeaconArtifactDappDevelopmentSepolia,
+    TokenStaking: StakingArtifactDappDevelopmentSepolia,
+    Bridge: BridgeArtifactDappDevelopmentSepolia,
+    NuCypherStakingEscrow: NuCypherStakingEscrowDappDevelopmentSepolia,
+    NuCypherToken: NuCypherTokenDappDevelopmentSepolia,
+    TBTCVault: TbtcVaultArtifactDappDevelopmentSepolia,
+    TBTC: TbtcTokenArtifactDappDevelopmentSepolia,
+    WalletRegistry: WalletRegistryArtifactDappDevelopmentSepolia,
+    VendingMachineKeep: VendingMachineKeepDappDevelopmentSepolia,
+    VendingMachineNuCypher: VendingMachineNuCypherDappDevelopmentSepolia,
+  },
+}
 
 // account is not optional
 export function getSigner(
@@ -189,20 +196,18 @@ export function getContractAddressFromTruffleArtifact(
 
 export const getArtifact = (
   artifactName: ArtifactNameType,
-  chainId: string | number,
-  shouldUseTestnetDevelopmentContracts = false
-): ArtifactType => {
-  switch (Number(chainId)) {
-    case SupportedChainIds.Ethereum:
-      return mainnetArtifacts.get(artifactName)!
-    case SupportedChainIds.Sepolia:
-      const artifacts = shouldUseTestnetDevelopmentContracts
-        ? testnetDevelopmentArtifacts
-        : sepoliaArtifacts
-      return artifacts.get(artifactName)!
-    default:
-      throw new Error("Can't get the contract artifact!")
+  chainId: number | string,
+  shouldUseTestnetDevelopmentContracts?: boolean
+): ArtifactType | null => {
+  if (shouldUseTestnetDevelopmentContracts) {
+    return (
+      contractArtifacts[SupportedChainIds.Localhost]?.[artifactName] ?? null
+    )
   }
+  return (
+    contractArtifacts[Number(chainId) as SupportedChainIds]?.[artifactName] ??
+    null
+  )
 }
 
 export const getSepoliaDevelopmentContracts = (
diff --git a/src/threshold-ts/vending-machine/index.ts b/src/threshold-ts/vending-machine/index.ts
index f7bc51976..0f1564619 100644
--- a/src/threshold-ts/vending-machine/index.ts
+++ b/src/threshold-ts/vending-machine/index.ts
@@ -39,7 +39,7 @@ export interface IVendingMachine {
   /**
    * Ethers contract instance of the `VendingMachine` contract.
    */
-  contract: Contract
+  contract: Contract | null
 
   /**
    * Returns the T token amount that's obtained from `amount` wrapped tokens,
@@ -68,7 +68,7 @@ export interface IVendingMachines {
 }
 
 export class VendingMachine implements IVendingMachine {
-  private _vendingMachine: Contract
+  private _vendingMachine: Contract | null
   private _ratio?: BigNumber
   public readonly WRAPPED_TOKEN_CONVERSION_PRECISION = 3
   public readonly FLOATING_POINT_DIVISOR = BigNumber.from(10).pow(
@@ -77,13 +77,18 @@ export class VendingMachine implements IVendingMachine {
     )
   )
 
-  constructor(config: EthereumConfig, artifact: { abi: any; address: string }) {
-    this._vendingMachine = getContract(
-      artifact.address,
-      artifact.abi,
-      config.providerOrSigner,
-      config.account
-    )
+  constructor(
+    config: EthereumConfig,
+    artifact: { abi: any; address: string } | null
+  ) {
+    this._vendingMachine = artifact
+      ? getContract(
+          artifact.address,
+          artifact.abi,
+          config.providerOrSigner,
+          config.account
+        )
+      : null
   }
 
   get contract() {
@@ -92,7 +97,7 @@ export class VendingMachine implements IVendingMachine {
 
   ratio = async (): Promise<BigNumber> => {
     if (!this._ratio) {
-      this._ratio = await this._vendingMachine.ratio()
+      this._ratio = await this._vendingMachine!.ratio()
     }
 
     return this._ratio!
diff --git a/src/utils/getEnvVariable.ts b/src/utils/getEnvVariable.ts
index 91a5544e6..de54737df 100644
--- a/src/utils/getEnvVariable.ts
+++ b/src/utils/getEnvVariable.ts
@@ -1,4 +1,5 @@
 import { EnvVariable, EnvVariableKey } from "../enums"
+import { SupportedChainIds } from "../networks/enums/networks"
 
 type EnvMap = { [key in EnvVariableKey]: string }
 
@@ -14,8 +15,10 @@ export const getEnvVariable = (envVar: EnvVariableKey) => {
 }
 
 export const getDefaultProviderChainId = () => {
-  const chainIdInString = getEnvVariable(EnvVariable.DEFAULT_PROVIDER_CHAIN_ID)
-  return Number(chainIdInString)
+  const chainId =
+    getEnvVariable(EnvVariable.DEFAULT_PROVIDER_CHAIN_ID) ||
+    SupportedChainIds.Ethereum
+  return Number(chainId)
 }
 
 export const shouldUseTestnetDevelopmentContracts =
diff --git a/src/utils/getStakingAppLabel.ts b/src/utils/getStakingAppLabel.ts
index bbb1adf9a..3c592fcd1 100644
--- a/src/utils/getStakingAppLabel.ts
+++ b/src/utils/getStakingAppLabel.ts
@@ -8,16 +8,20 @@ const stakingAppNameToAppLabel: Record<StakingAppName, string> = {
 }
 
 export const getStakingAppNameFromAppAddress = (stakingAppAddress: string) => {
-  const { multiAppStaking } = useThreshold()
+  const threshold = useThreshold()
 
-  if (!multiAppStaking) {
+  if (
+    !threshold.multiAppStaking.ecdsa ||
+    !threshold.multiAppStaking.randomBeacon ||
+    !threshold.multiAppStaking.taco
+  ) {
     return null
   }
 
   const stakingAppAddressToAppName: Record<string, StakingAppName> = {
-    [multiAppStaking.ecdsa.address]: "tbtc",
-    [multiAppStaking.randomBeacon.address]: "randomBeacon",
-    [multiAppStaking.taco.address]: "taco",
+    [threshold.multiAppStaking.ecdsa.address]: "tbtc",
+    [threshold.multiAppStaking.randomBeacon.address]: "randomBeacon",
+    [threshold.multiAppStaking.taco.address]: "taco",
   }
 
   return stakingAppAddressToAppName[stakingAppAddress]
diff --git a/src/web3/hooks/useNu.ts b/src/web3/hooks/useNu.ts
index 8038ceb20..7927e184e 100644
--- a/src/web3/hooks/useNu.ts
+++ b/src/web3/hooks/useNu.ts
@@ -5,7 +5,7 @@ import { TransactionType } from "../../enums/transactionType"
 import { getArtifact } from "../../threshold-ts/utils"
 import { shouldUseTestnetDevelopmentContracts } from "../../utils/getEnvVariable"
 import { useIsActive } from "../../hooks/useIsActive"
-import { isL1Network } from "../../networks/utils"
+import { getMainnetOrTestnetChainId } from "../../networks/utils"
 import { SupportedChainIds } from "../../networks/enums/networks"
 export interface UseNu {
   (): {
@@ -17,9 +17,7 @@ export interface UseNu {
 
 export const useNu: UseNu = () => {
   const { chainId } = useIsActive()
-  const supportedChainId = isL1Network(chainId)
-    ? (chainId as number)
-    : SupportedChainIds.Ethereum
+  const supportedChainId = getMainnetOrTestnetChainId(chainId)
 
   const nuCupherTokenArtifact = getArtifact(
     "NuCypherToken",
@@ -28,9 +26,9 @@ export const useNu: UseNu = () => {
   )
 
   const { balanceOf, approve, contract } = useErc20TokenContract(
-    nuCupherTokenArtifact.address,
+    nuCupherTokenArtifact?.address!,
     undefined,
-    nuCupherTokenArtifact.abi
+    nuCupherTokenArtifact?.abi!
   )
 
   const approveNu = () => {
diff --git a/src/web3/hooks/useNuStakingEscrowContract.ts b/src/web3/hooks/useNuStakingEscrowContract.ts
index 976acadfe..df0755000 100644
--- a/src/web3/hooks/useNuStakingEscrowContract.ts
+++ b/src/web3/hooks/useNuStakingEscrowContract.ts
@@ -3,5 +3,5 @@ import { useThreshold } from "../../contexts/ThresholdContext"
 export const useNuStakingEscrowContract = () => {
   const threshold = useThreshold()
 
-  return threshold.staking!.legacyNuStakingContract
+  return threshold.staking.legacyNuStakingContract
 }

From c09a27356fcc876387c0493b3e704048f629c290 Mon Sep 17 00:00:00 2001
From: evandrosaturnino <evandro.saturnino@gmail.com>
Date: Wed, 27 Nov 2024 05:18:23 -0300
Subject: [PATCH 26/46] Improve redemption flow with multiple networks

---
 src/contexts/TokenContext.tsx                 |   6 +-
 .../useRequestBitcoinAccount.ts               |   7 +-
 .../useRequestEthereumAccount.ts              |   6 +-
 src/hooks/tbtc/useFetchRedemptionDetails.ts   |   3 +-
 src/hooks/useCheckBonusEligibility.ts         |   9 +-
 src/hooks/useFetchOwnerStakes.ts              |  15 +-
 src/hooks/useFetchStakingRewards.ts           |   2 -
 ...nId.ts => useConnectedOrDefaultChainId.ts} |   2 +-
 src/pages/tBTC/Bridge/UnmintDetails.tsx       | 222 +++++++++---------
 src/threshold-ts/utils/contract.ts            |   1 -
 src/utils/tBTC.ts                             |  14 +-
 .../hooks/useCheckDuplicateProviderAddress.ts |  44 +++-
 src/web3/hooks/useKeep.ts                     |   4 +-
 src/web3/hooks/useKeepBondingContract.ts      |   4 +-
 src/web3/hooks/useKeepTokenStakingContract.ts |   6 +-
 src/web3/hooks/useMerkleDropContract.ts       |  11 +-
 src/web3/hooks/useMulticallContract.ts        |   4 +-
 src/web3/hooks/useT.ts                        |   4 +-
 src/web3/hooks/useTBTCTokenContract.ts        |   4 +-
 src/web3/hooks/useTBTCv2TokenContract.ts      |   4 +-
 src/web3/hooks/useTStakingContract.ts         |  14 +-
 21 files changed, 210 insertions(+), 176 deletions(-)
 rename src/networks/hooks/{useDefaultOrConnectedChainId.ts => useConnectedOrDefaultChainId.ts} (84%)

diff --git a/src/contexts/TokenContext.tsx b/src/contexts/TokenContext.tsx
index f50aa41e1..b9d4a25dc 100644
--- a/src/contexts/TokenContext.tsx
+++ b/src/contexts/TokenContext.tsx
@@ -124,6 +124,8 @@ export const TokenContextProvider: React.FC = ({ children }) => {
         )
       })
     } else if (isActive && isL2Network(chainId)) {
+      tokens.forEach((token) => updateTokenState(token, 0))
+
       fetchtBTCBalance().then(([tbtcv2]) => {
         if (featureFlags.TBTC_V2) {
           updateTokenState(Token.TBTCV2, tbtcv2, true)
@@ -136,8 +138,8 @@ export const TokenContextProvider: React.FC = ({ children }) => {
 
   // fetch user stakes when they connect their wallet
   useEffect(() => {
-    fetchOwnerStakes(account!)
-  }, [fetchOwnerStakes, account])
+    fetchOwnerStakes(account!, chainId)
+  }, [fetchOwnerStakes, account, chainId])
 
   return (
     <TokenContext.Provider
diff --git a/src/hooks/ledger-live-app/useRequestBitcoinAccount.ts b/src/hooks/ledger-live-app/useRequestBitcoinAccount.ts
index 8e8dec2bb..f2891329c 100644
--- a/src/hooks/ledger-live-app/useRequestBitcoinAccount.ts
+++ b/src/hooks/ledger-live-app/useRequestBitcoinAccount.ts
@@ -5,7 +5,7 @@ import { useLedgerLiveApp } from "../../contexts/LedgerLiveAppContext"
 import { useWalletApiReactTransport } from "../../contexts/TransportProvider"
 import { useWeb3React } from "@web3-react/core"
 import { isTestnetNetwork } from "../../networks/utils"
-import { useDefaultOrConnectedChainId } from "../../networks/hooks/useDefaultOrConnectedChainId"
+import { useConnectedOrDefaultChainId } from "../../networks/hooks/useConnectedOrDefaultChainId"
 import { useIsEmbed } from "../useIsEmbed"
 
 type UseRequestAccountState = {
@@ -25,15 +25,14 @@ export function useRequestBitcoinAccount(): UseRequestAccountReturn {
   const { walletApiReactTransport } = useWalletApiReactTransport()
   const useRequestAccountReturn = useWalletApiRequestAccount()
   const { account, requestAccount } = useRequestAccountReturn
-  const { chainId } = useWeb3React()
   const { isEmbed } = useIsEmbed()
+  const defaultOrConnectedChainId = useConnectedOrDefaultChainId()
 
   useEffect(() => {
     if (isEmbed) setBtcAccount(account || undefined)
   }, [account, isEmbed])
 
   const requestBitcoinAccount = useCallback(async () => {
-    const defaultOrConnectedChainId = useDefaultOrConnectedChainId()
     const currencyId = isTestnetNetwork(defaultOrConnectedChainId)
       ? "bitcoin_testnet"
       : "bitcoin"
@@ -41,7 +40,7 @@ export function useRequestBitcoinAccount(): UseRequestAccountReturn {
     walletApiReactTransport.connect()
     await requestAccount({ currencyIds: [currencyId] })
     walletApiReactTransport.disconnect()
-  }, [requestAccount, walletApiReactTransport, chainId])
+  }, [requestAccount, walletApiReactTransport, defaultOrConnectedChainId])
 
   return { ...useRequestAccountReturn, requestAccount: requestBitcoinAccount }
 }
diff --git a/src/hooks/ledger-live-app/useRequestEthereumAccount.ts b/src/hooks/ledger-live-app/useRequestEthereumAccount.ts
index 44c0b5ed8..5cc34a1b4 100644
--- a/src/hooks/ledger-live-app/useRequestEthereumAccount.ts
+++ b/src/hooks/ledger-live-app/useRequestEthereumAccount.ts
@@ -5,7 +5,7 @@ import { useLedgerLiveApp } from "../../contexts/LedgerLiveAppContext"
 import { useWalletApiReactTransport } from "../../contexts/TransportProvider"
 import { walletConnected } from "../../store/account"
 import { isTestnetNetwork } from "../../networks/utils"
-import { useDefaultOrConnectedChainId } from "../../networks/hooks/useDefaultOrConnectedChainId"
+import { useConnectedOrDefaultChainId } from "../../networks/hooks/useConnectedOrDefaultChainId"
 import { useAppDispatch } from "../store/useAppDispatch"
 import { useIsEmbed } from "../useIsEmbed"
 import { useWeb3React } from "@web3-react/core"
@@ -30,6 +30,7 @@ export function useRequestEthereumAccount(): UseRequestAccountReturn {
   const { chainId } = useWeb3React()
   const dispatch = useAppDispatch()
   const { isEmbed } = useIsEmbed()
+  const defaultOrConnectedChainId = useConnectedOrDefaultChainId()
 
   useEffect(() => {
     // Setting the eth account in LedgerLiveAppContext through `setEthAccount`
@@ -46,7 +47,6 @@ export function useRequestEthereumAccount(): UseRequestAccountReturn {
   }, [ledgerLiveAccount, chainId, isEmbed])
 
   const requestEthereumAccount = useCallback(async () => {
-    const defaultOrConnectedChainId = useDefaultOrConnectedChainId()
     // The Goerli testnet become deprecated. However, we did not test Ledger
     // Live on Sepolia yet, so we're leaving the Goerli config for now in the
     // code.
@@ -56,7 +56,7 @@ export function useRequestEthereumAccount(): UseRequestAccountReturn {
     walletApiReactTransport.connect()
     await requestAccount({ currencyIds: [currencyId] })
     walletApiReactTransport.disconnect()
-  }, [requestAccount, walletApiReactTransport, chainId])
+  }, [requestAccount, walletApiReactTransport, defaultOrConnectedChainId])
 
   return { ...useRequestAccountReturn, requestAccount: requestEthereumAccount }
 }
diff --git a/src/hooks/tbtc/useFetchRedemptionDetails.ts b/src/hooks/tbtc/useFetchRedemptionDetails.ts
index d01c9371e..11fb23676 100644
--- a/src/hooks/tbtc/useFetchRedemptionDetails.ts
+++ b/src/hooks/tbtc/useFetchRedemptionDetails.ts
@@ -42,6 +42,7 @@ export const useFetchRedemptionDetails = (
   >()
 
   useEffect(() => {
+    setError("")
     if (!redeemer || isEmptyOrZeroAddress(redeemer)) {
       setError("Invalid redeemer value.")
       return
@@ -111,7 +112,7 @@ export const useFetchRedemptionDetails = (
           )
         })
         if (!redemptionRequestedEvent) {
-          throw new Error("Redemption not found...")
+          throw new Error("Redemption not found in this network...")
         }
 
         const { timestamp: redemptionRequestedEventTimestamp } = await getBlock(
diff --git a/src/hooks/useCheckBonusEligibility.ts b/src/hooks/useCheckBonusEligibility.ts
index fe3d00148..82a614ad4 100644
--- a/src/hooks/useCheckBonusEligibility.ts
+++ b/src/hooks/useCheckBonusEligibility.ts
@@ -45,7 +45,7 @@ export const useCheckBonusEligibility = () => {
         (
           await getContractPastEvents(merkleDropContract, {
             eventName: "Claimed",
-            fromBlock: getMerkleDropDeploymentBlock(),
+            fromBlock: getMerkleDropDeploymentBlock(chainId),
             filterParams: [stakingProviders],
           })
         ).map((_) => getAddress(_.args?.stakingProvider as string))
@@ -53,19 +53,19 @@ export const useCheckBonusEligibility = () => {
 
       const stakedEvents = await getContractPastEvents(tStakingContract, {
         eventName: "Staked",
-        fromBlock: getTStakingDeploymentBlock(),
+        fromBlock: getTStakingDeploymentBlock(chainId),
         filterParams: [null, null, stakingProviders],
       })
 
       const toppedUpEvents = await getContractPastEvents(tStakingContract, {
         eventName: "ToppedUp",
-        fromBlock: getTStakingDeploymentBlock(),
+        fromBlock: getTStakingDeploymentBlock(chainId),
         filterParams: [stakingProviders],
       })
 
       const unstakedEvents = await getContractPastEvents(tStakingContract, {
         eventName: "Unstaked",
-        fromBlock: getTStakingDeploymentBlock(),
+        fromBlock: getTStakingDeploymentBlock(chainId),
         filterParams: [stakingProviders],
       })
 
@@ -117,6 +117,7 @@ export const useCheckBonusEligibility = () => {
     }
     fetch()
   }, [
+    chainId,
     stakingProviders,
     tStakingContract,
     merkleDropContract,
diff --git a/src/hooks/useFetchOwnerStakes.ts b/src/hooks/useFetchOwnerStakes.ts
index f4cfd1349..ddcff5061 100644
--- a/src/hooks/useFetchOwnerStakes.ts
+++ b/src/hooks/useFetchOwnerStakes.ts
@@ -3,14 +3,23 @@ import { StakeData } from "../types/staking"
 import { setStakes } from "../store/staking"
 import { useThreshold } from "../contexts/ThresholdContext"
 import { useAppDispatch } from "./store"
+import { isSameChainId } from "../networks/utils"
 
 export const useFetchOwnerStakes = () => {
   const threshold = useThreshold()
   const dispatch = useAppDispatch()
 
   return useCallback(
-    async (address?: string): Promise<StakeData[]> => {
-      if (!address || !threshold.staking) {
+    async (
+      address?: string,
+      chainId?: string | number
+    ): Promise<StakeData[]> => {
+      if (
+        !address ||
+        !threshold.staking ||
+        !chainId ||
+        !isSameChainId(threshold.config.ethereum.chainId, chainId)
+      ) {
         return []
       }
 
@@ -32,6 +41,6 @@ export const useFetchOwnerStakes = () => {
 
       return _stakes
     },
-    [threshold, dispatch]
+    [threshold.config.ethereum, dispatch]
   )
 }
diff --git a/src/hooks/useFetchStakingRewards.ts b/src/hooks/useFetchStakingRewards.ts
index da89f919f..e6f03e0e5 100644
--- a/src/hooks/useFetchStakingRewards.ts
+++ b/src/hooks/useFetchStakingRewards.ts
@@ -12,14 +12,12 @@ import { setInterimRewards } from "../store/rewards"
 import { selectStakingProviders } from "../store/staking"
 import { BigNumber } from "ethers"
 import { Zero } from "@ethersproject/constants"
-import { useIsActive } from "./useIsActive"
 
 interface StakingRewards {
   [stakingProvider: string]: string
 }
 
 export const useFetchStakingRewards = () => {
-  const { chainId } = useIsActive()
   const merkleDropContract = useMerkleDropContract()
   const stakingProviders = useSelector(selectStakingProviders)
   const { hasFetched, isFetching } = useSelector(
diff --git a/src/networks/hooks/useDefaultOrConnectedChainId.ts b/src/networks/hooks/useConnectedOrDefaultChainId.ts
similarity index 84%
rename from src/networks/hooks/useDefaultOrConnectedChainId.ts
rename to src/networks/hooks/useConnectedOrDefaultChainId.ts
index fe023a21f..bc28a945f 100644
--- a/src/networks/hooks/useDefaultOrConnectedChainId.ts
+++ b/src/networks/hooks/useConnectedOrDefaultChainId.ts
@@ -1,7 +1,7 @@
 import { useIsActive } from "../../hooks/useIsActive"
 import { getDefaultProviderChainId } from "../../utils/getEnvVariable"
 
-export const useDefaultOrConnectedChainId = () => {
+export const useConnectedOrDefaultChainId = () => {
   const { chainId } = useIsActive()
   const defaultOrConnectedChainId = chainId ?? getDefaultProviderChainId()
 
diff --git a/src/pages/tBTC/Bridge/UnmintDetails.tsx b/src/pages/tBTC/Bridge/UnmintDetails.tsx
index 1dabcf867..3fde6970f 100644
--- a/src/pages/tBTC/Bridge/UnmintDetails.tsx
+++ b/src/pages/tBTC/Bridge/UnmintDetails.tsx
@@ -114,8 +114,8 @@ export const UnmintDetails: PageComponent = () => {
   const [shouldDisplaySuccessStep, setShouldDisplaySuccessStep] =
     useState(false)
 
-  const _isFetching = (isFetching || !data) && !error
-  const wasDataFetched = !isFetching && !!data && !error
+  const _isFetching = isFetching || !data
+  const wasDataFetched = !isFetching && !!data
 
   const isProcessCompleted = !!redemptionFromBitcoinTx?.bitcoinTxHash
   const shouldForceIsProcessCompleted =
@@ -192,78 +192,54 @@ export const UnmintDetails: PageComponent = () => {
         shouldDisplaySuccessStep || shouldForceIsProcessCompleted
       }
     >
-      <BridgeLayoutMainSection>
-        {_isFetching && <BridgeProcessDetailsPageSkeleton />}
-        {error && <>{error}</>}
-        {wasDataFetched && (
-          <>
-            <BridgeProcessCardTitle bridgeProcess="unmint" />
-            <BridgeProcessCardSubTitle
-              display="flex"
-              stepText={
-                shouldDisplaySuccessStep || shouldForceIsProcessCompleted
-                  ? "Unminted"
-                  : "Unminting"
-              }
-            >
-              {!(shouldDisplaySuccessStep || shouldForceIsProcessCompleted) && (
-                <Box as="span" ml="2">
-                  {" "}
-                  - In progress...
-                </Box>
-              )}
-              <InlineTokenBalance
-                tokenAmount={requestedAmount}
-                withSymbol
-                tokenSymbol="tBTC"
-                ml="auto"
-                precision={6}
-                higherPrecision={8}
-              />
-            </BridgeProcessCardSubTitle>
-            <Timeline>
-              <Badge
-                variant="subtle"
-                size="sm"
-                bg={timelineBadgeBgColor}
-                position="absolute"
-                bottom="10px"
-                left="50%"
-                transform="translateX(-50%)"
-              >
-                usual duration - 3-5 hours
-              </Badge>
-              <TimelineItem status="active">
-                <TimelineBreakpoint>
-                  <TimelineDot position="relative">
-                    <Icon
-                      as={IoCheckmarkSharp}
-                      position="absolute"
-                      color="white"
-                      w="22px"
-                      h="22px"
-                      m="auto"
-                      left="0"
-                      right="0"
-                      textAlign="center"
-                    />
-                  </TimelineDot>
-                  <TimelineConnector />
-                </TimelineBreakpoint>
-                <TimelineContent>
-                  <BodyXs whiteSpace="pre-line">tBTC unwrapped</BodyXs>
-                </TimelineContent>
-              </TimelineItem>
-              <TimelineItem
-                status={
-                  isProcessCompleted || shouldForceIsProcessCompleted
-                    ? "active"
-                    : "semi-active"
+      {error ? (
+        <Box w="full">{error}</Box>
+      ) : (
+        <BridgeLayoutMainSection>
+          {_isFetching && <BridgeProcessDetailsPageSkeleton />}
+          {wasDataFetched && (
+            <>
+              <BridgeProcessCardTitle bridgeProcess="unmint" />
+              <BridgeProcessCardSubTitle
+                display="flex"
+                stepText={
+                  shouldDisplaySuccessStep || shouldForceIsProcessCompleted
+                    ? "Unminted"
+                    : "Unminting"
                 }
               >
-                <TimelineBreakpoint>
-                  <TimelineDot position="relative">
-                    {(isProcessCompleted || shouldForceIsProcessCompleted) && (
+                {!(
+                  shouldDisplaySuccessStep || shouldForceIsProcessCompleted
+                ) && (
+                  <Box as="span" ml="2">
+                    {" "}
+                    - In progress...
+                  </Box>
+                )}
+                <InlineTokenBalance
+                  tokenAmount={requestedAmount}
+                  withSymbol
+                  tokenSymbol="tBTC"
+                  ml="auto"
+                  precision={6}
+                  higherPrecision={8}
+                />
+              </BridgeProcessCardSubTitle>
+              <Timeline>
+                <Badge
+                  variant="subtle"
+                  size="sm"
+                  bg={timelineBadgeBgColor}
+                  position="absolute"
+                  bottom="10px"
+                  left="50%"
+                  transform="translateX(-50%)"
+                >
+                  usual duration - 3-5 hours
+                </Badge>
+                <TimelineItem status="active">
+                  <TimelineBreakpoint>
+                    <TimelineDot position="relative">
                       <Icon
                         as={IoCheckmarkSharp}
                         position="absolute"
@@ -275,42 +251,72 @@ export const UnmintDetails: PageComponent = () => {
                         right="0"
                         textAlign="center"
                       />
-                    )}
-                  </TimelineDot>
-                  <TimelineConnector />
-                </TimelineBreakpoint>
-                <TimelineContent>
-                  <BodyXs whiteSpace="pre-line">BTC sent</BodyXs>
-                </TimelineContent>
-              </TimelineItem>
-            </Timeline>
-            {shouldDisplaySuccessStep || shouldForceIsProcessCompleted ? (
-              <SuccessStep
-                requestedAmount={requestedAmount}
-                receivedAmount={receivedAmount}
-                thresholdNetworkFee={thresholdNetworkFee}
-                btcAddress={btcAddress!}
-              />
-            ) : (
-              <BridgeProcessStep
-                title="Unminting in progress"
-                chain="ethereum"
-                txHash={redemptionRequestedTxHash}
-                progressBarColor="brand.500"
-                isCompleted={isProcessCompleted}
-                icon={<ProcessCompletedBrandGradientIcon />}
-                onComplete={() => setShouldDisplaySuccessStep(true)}
-                isIndeterminate
-              >
-                <BodyMd mt="6" px="3.5" mb="10" alignSelf="flex-start">
-                  Your redemption request is being processed. This will take
-                  around 3-5 hours.
-                </BodyMd>
-              </BridgeProcessStep>
-            )}
-          </>
-        )}
-      </BridgeLayoutMainSection>
+                    </TimelineDot>
+                    <TimelineConnector />
+                  </TimelineBreakpoint>
+                  <TimelineContent>
+                    <BodyXs whiteSpace="pre-line">tBTC unwrapped</BodyXs>
+                  </TimelineContent>
+                </TimelineItem>
+                <TimelineItem
+                  status={
+                    isProcessCompleted || shouldForceIsProcessCompleted
+                      ? "active"
+                      : "semi-active"
+                  }
+                >
+                  <TimelineBreakpoint>
+                    <TimelineDot position="relative">
+                      {(isProcessCompleted ||
+                        shouldForceIsProcessCompleted) && (
+                        <Icon
+                          as={IoCheckmarkSharp}
+                          position="absolute"
+                          color="white"
+                          w="22px"
+                          h="22px"
+                          m="auto"
+                          left="0"
+                          right="0"
+                          textAlign="center"
+                        />
+                      )}
+                    </TimelineDot>
+                    <TimelineConnector />
+                  </TimelineBreakpoint>
+                  <TimelineContent>
+                    <BodyXs whiteSpace="pre-line">BTC sent</BodyXs>
+                  </TimelineContent>
+                </TimelineItem>
+              </Timeline>
+              {shouldDisplaySuccessStep || shouldForceIsProcessCompleted ? (
+                <SuccessStep
+                  requestedAmount={requestedAmount}
+                  receivedAmount={receivedAmount}
+                  thresholdNetworkFee={thresholdNetworkFee}
+                  btcAddress={btcAddress!}
+                />
+              ) : (
+                <BridgeProcessStep
+                  title="Unminting in progress"
+                  chain="ethereum"
+                  txHash={redemptionRequestedTxHash}
+                  progressBarColor="brand.500"
+                  isCompleted={isProcessCompleted}
+                  icon={<ProcessCompletedBrandGradientIcon />}
+                  onComplete={() => setShouldDisplaySuccessStep(true)}
+                  isIndeterminate
+                >
+                  <BodyMd mt="6" px="3.5" mb="10" alignSelf="flex-start">
+                    Your redemption request is being processed. This will take
+                    around 3-5 hours.
+                  </BodyMd>
+                </BridgeProcessStep>
+              )}
+            </>
+          )}
+        </BridgeLayoutMainSection>
+      )}
       <BridgeLayoutAsideSection
         alignSelf="stretch"
         display="flex"
diff --git a/src/threshold-ts/utils/contract.ts b/src/threshold-ts/utils/contract.ts
index 887fbd972..b5920cd9b 100644
--- a/src/threshold-ts/utils/contract.ts
+++ b/src/threshold-ts/utils/contract.ts
@@ -99,7 +99,6 @@ const contractArtifacts: ContractArtifacts = {
     ArbitrumL1BitcoinDepositor: ArbitrumL1BitcoinDepositorArtifactSepolia,
     BaseL1BitcoinDepositor: BaseL1BitcoinDepositorArtifactSepolia,
     TacoRegistry: TacoRegistryArtifactSepolia,
-    LegacyKeepStaking: LegacyKeepStakingArtifactSepolia,
     RandomBeacon: RandomBeaconArtifactSepolia,
     TokenStaking: StakingArtifactSepolia,
     Bridge: BridgeArtifactSepolia,
diff --git a/src/utils/tBTC.ts b/src/utils/tBTC.ts
index 78b3eea80..6e7aae583 100644
--- a/src/utils/tBTC.ts
+++ b/src/utils/tBTC.ts
@@ -7,11 +7,15 @@ import {
 } from "../threshold-ts/utils"
 import { BigNumberish, BigNumber } from "ethers"
 
-const MINTING_MAINNET_BTC_RECOVERY_ADDRESS_PREFIXES = ["1", "bc1"] as const
-const MINTING_TESTNET_BTC_RECOVERY_ADDRESS_PREFIXES = ["m", "n", "tb1"] as const
-
-const UNMINTING_MAINNET_BTC_ADDRESS_PREFIXES = ["1", "bc1", "3"] as const
-const UNMINTING_TESTNET_BTC_ADDRESS_PREFIXES = ["m", "n", "tb1", "2"] as const
+const MINTING_MAINNET_BTC_RECOVERY_ADDRESS_PREFIXES = ["1", "bc1q"] as const
+const MINTING_TESTNET_BTC_RECOVERY_ADDRESS_PREFIXES = [
+  "m",
+  "n",
+  "tb1q",
+] as const
+
+const UNMINTING_MAINNET_BTC_ADDRESS_PREFIXES = ["1", "bc1q", "3"] as const
+const UNMINTING_TESTNET_BTC_ADDRESS_PREFIXES = ["m", "n", "tb1q", "2"] as const
 
 type SupportedBitcoinNetworks = Exclude<BitcoinNetwork, "unknown">
 
diff --git a/src/web3/hooks/useCheckDuplicateProviderAddress.ts b/src/web3/hooks/useCheckDuplicateProviderAddress.ts
index a40d8a31d..83cd0d4da 100644
--- a/src/web3/hooks/useCheckDuplicateProviderAddress.ts
+++ b/src/web3/hooks/useCheckDuplicateProviderAddress.ts
@@ -2,8 +2,9 @@ import { useCallback } from "react"
 import { BigNumber } from "ethers"
 import { useTStakingContract } from "./useTStakingContract"
 import { useKeepTokenStakingContract } from "./useKeepTokenStakingContract"
-import { isAddressZero } from "../../web3/utils"
+import { AddressZero, isAddressZero } from "../../web3/utils"
 import { useThreshold } from "../../contexts/ThresholdContext"
+import { ContractCall } from "../../threshold-ts/multicall"
 
 const useCheckDuplicateProviderAddress = (): ((
   stakingProvider: string
@@ -18,32 +19,53 @@ const useCheckDuplicateProviderAddress = (): ((
   const checkIfProviderUsed = useCallback(
     async (stakingProvider) => {
       const multicall = threshold.multicall
-      if (!tStakingContract || !keepStakingContract || !multicall) {
+      if (!multicall) {
         return {
           isProviderUsedForKeep: false,
           isProviderUsedForT: false,
         }
       }
 
-      const [{ owner }, [, createdAt]] = await multicall.aggregate([
-        {
+      const calls: ContractCall[] = []
+
+      if (tStakingContract?.interface && tStakingContract.address) {
+        calls.push({
           interface: tStakingContract.interface,
           address: tStakingContract.address,
           method: "rolesOf",
           args: [stakingProvider],
-        },
-        {
+        })
+      }
+
+      if (keepStakingContract?.interface && keepStakingContract.address) {
+        calls.push({
           interface: keepStakingContract.interface,
           address: keepStakingContract.address,
           method: "getDelegationInfo",
           args: [stakingProvider],
-        },
-      ])
+        })
+      }
+      try {
+        const results = await multicall.aggregate(calls)
+
+        const tRolesResult = results[0] || {}
+        const owner = tRolesResult?.owner || AddressZero
+
+        const keepDelegationResult = results[1] || {}
+        const createdAt = keepDelegationResult?.createdAt || BigNumber.from(0)
 
-      const isProviderUsedForKeep = createdAt.gt(BigNumber.from(0))
-      const isProviderUsedForT = !isAddressZero(owner)
+        const isProviderUsedForKeep =
+          BigNumber.isBigNumber(createdAt) && createdAt.gt(0)
+        const isProviderUsedForT = !isAddressZero(owner)
 
-      return { isProviderUsedForKeep, isProviderUsedForT }
+        return { isProviderUsedForKeep, isProviderUsedForT }
+      } catch (error) {
+        console.error("Multicall failed:", error)
+        return {
+          isProviderUsedForKeep: false,
+          isProviderUsedForT: false,
+        }
+      }
     },
     [tStakingContract, keepStakingContract, threshold]
   )
diff --git a/src/web3/hooks/useKeep.ts b/src/web3/hooks/useKeep.ts
index 32156040f..05859e91a 100644
--- a/src/web3/hooks/useKeep.ts
+++ b/src/web3/hooks/useKeep.ts
@@ -5,7 +5,7 @@ import { TransactionType } from "../../enums/transactionType"
 import { Contract } from "@ethersproject/contracts"
 import { AddressZero } from "@ethersproject/constants"
 import { SupportedChainIds } from "../../networks/enums/networks"
-import { useDefaultOrConnectedChainId } from "../../networks/hooks/useDefaultOrConnectedChainId"
+import { useConnectedOrDefaultChainId } from "../../networks/hooks/useConnectedOrDefaultChainId"
 
 export const KEEP_ADDRESSES = {
   // https://etherscan.io/address/0x85Eee30c52B0b379b046Fb0F85F4f3Dc3009aFEC
@@ -24,7 +24,7 @@ export interface UseKeep {
 }
 
 export const useKeep: UseKeep = () => {
-  const defaultOrConnectedChainId = useDefaultOrConnectedChainId()
+  const defaultOrConnectedChainId = useConnectedOrDefaultChainId()
 
   const { balanceOf, approve, contract } = useErc20TokenContract(
     KEEP_ADDRESSES[Number(defaultOrConnectedChainId)],
diff --git a/src/web3/hooks/useKeepBondingContract.ts b/src/web3/hooks/useKeepBondingContract.ts
index 9e96aec1b..ef0c5bfce 100644
--- a/src/web3/hooks/useKeepBondingContract.ts
+++ b/src/web3/hooks/useKeepBondingContract.ts
@@ -2,7 +2,7 @@ import { AddressZero } from "@ethersproject/constants"
 import { SupportedChainIds } from "../../networks/enums/networks"
 import { useContract } from "./useContract"
 import KeepBonding from "@keep-network/keep-ecdsa/artifacts/KeepBonding.json"
-import { useDefaultOrConnectedChainId } from "../../networks/hooks/useDefaultOrConnectedChainId"
+import { useConnectedOrDefaultChainId } from "../../networks/hooks/useConnectedOrDefaultChainId"
 
 const KEEP_BONDING_ADDRESSES = {
   // https://etherscan.io/address/0x27321f84704a599aB740281E285cc4463d89A3D5
@@ -12,7 +12,7 @@ const KEEP_BONDING_ADDRESSES = {
 } as Record<number, string>
 
 export const useKeepBondingContract = () => {
-  const defaultOrConnectedChainId = useDefaultOrConnectedChainId()
+  const defaultOrConnectedChainId = useConnectedOrDefaultChainId()
 
   return useContract(
     KEEP_BONDING_ADDRESSES[Number(defaultOrConnectedChainId)],
diff --git a/src/web3/hooks/useKeepTokenStakingContract.ts b/src/web3/hooks/useKeepTokenStakingContract.ts
index 5a47f456f..7cd0b1b54 100644
--- a/src/web3/hooks/useKeepTokenStakingContract.ts
+++ b/src/web3/hooks/useKeepTokenStakingContract.ts
@@ -2,18 +2,16 @@ import KeepTokenStaking from "@keep-network/keep-core/artifacts/TokenStaking.jso
 import { useContract } from "./useContract"
 import { SupportedChainIds } from "../../networks/enums/networks"
 import { AddressZero } from "@ethersproject/constants"
-import { useDefaultOrConnectedChainId } from "../../networks/hooks/useDefaultOrConnectedChainId"
+import { useConnectedOrDefaultChainId } from "../../networks/hooks/useConnectedOrDefaultChainId"
 
 const KEEP_STAKING_ADDRESSES = {
   // https://etherscan.io/address/0x1293a54e160D1cd7075487898d65266081A15458
   [SupportedChainIds.Ethereum]: "0x1293a54e160D1cd7075487898d65266081A15458",
-  // https://sepolia.etherscan.io/address/0xa07f4E37C2E7089Ea3AFffbe51A6A281833a4D14
-  [SupportedChainIds.Sepolia]: "0xa07f4E37C2E7089Ea3AFffbe51A6A281833a4D14",
   [SupportedChainIds.Localhost]: AddressZero,
 } as Record<number, string>
 
 export const useKeepTokenStakingContract = () => {
-  const defaultOrConnectedChainId = useDefaultOrConnectedChainId()
+  const defaultOrConnectedChainId = useConnectedOrDefaultChainId()
 
   return useContract(
     KEEP_STAKING_ADDRESSES[Number(defaultOrConnectedChainId)],
diff --git a/src/web3/hooks/useMerkleDropContract.ts b/src/web3/hooks/useMerkleDropContract.ts
index 1ea386fcc..d08c594e6 100644
--- a/src/web3/hooks/useMerkleDropContract.ts
+++ b/src/web3/hooks/useMerkleDropContract.ts
@@ -2,7 +2,7 @@ import CumulativeMerkleDropABI from "../abi/CumulativeMerkleDrop.json"
 import { useContract } from "./useContract"
 import { AddressZero } from "../utils"
 import { SupportedChainIds } from "../../networks/enums/networks"
-import { useDefaultOrConnectedChainId } from "../../networks/hooks/useDefaultOrConnectedChainId"
+import { useWeb3React } from "@web3-react/core"
 
 const DEPLOYMENT_BLOCKS: { [key: number]: number } = {
   [SupportedChainIds.Ethereum]: 15146501,
@@ -18,15 +18,14 @@ const MERKLE_DROP_ADDRESSES = {
   [SupportedChainIds.Localhost]: AddressZero,
 } as Record<number, string>
 
-export const getMerkleDropDeploymentBlock = () => {
-  const defaultOrConnectedChainId = useDefaultOrConnectedChainId()
-  return DEPLOYMENT_BLOCKS[Number(defaultOrConnectedChainId)] || 0
+export const getMerkleDropDeploymentBlock = (chainId?: string | number) => {
+  return DEPLOYMENT_BLOCKS[Number(chainId)] || 0
 }
 
 export const useMerkleDropContract = () => {
-  const defaultOrConnectedChainId = useDefaultOrConnectedChainId()
+  const { chainId } = useWeb3React()
   return useContract(
-    MERKLE_DROP_ADDRESSES[Number(defaultOrConnectedChainId)],
+    MERKLE_DROP_ADDRESSES[Number(chainId)],
     CumulativeMerkleDropABI
   )
 }
diff --git a/src/web3/hooks/useMulticallContract.ts b/src/web3/hooks/useMulticallContract.ts
index 5315dc05d..f383768c9 100644
--- a/src/web3/hooks/useMulticallContract.ts
+++ b/src/web3/hooks/useMulticallContract.ts
@@ -1,6 +1,6 @@
 import { useContract } from "./useContract"
 import { MULTICALL_ADDRESSES } from "../../threshold-ts/multicall"
-import { useDefaultOrConnectedChainId } from "../../networks/hooks/useDefaultOrConnectedChainId"
+import { useConnectedOrDefaultChainId } from "../../networks/hooks/useConnectedOrDefaultChainId"
 
 const MULTICALL_ABI = [
   "function aggregate(tuple(address target, bytes callData)[] calls) view returns (uint256 blockNumber, bytes[] returnData)",
@@ -8,7 +8,7 @@ const MULTICALL_ABI = [
 ]
 
 export const useMulticallContract = () => {
-  const defaultOrConnectedChainId = useDefaultOrConnectedChainId()
+  const defaultOrConnectedChainId = useConnectedOrDefaultChainId()
 
   return useContract(
     MULTICALL_ADDRESSES[Number(defaultOrConnectedChainId)],
diff --git a/src/web3/hooks/useT.ts b/src/web3/hooks/useT.ts
index 6f6e33eb9..96981d84d 100644
--- a/src/web3/hooks/useT.ts
+++ b/src/web3/hooks/useT.ts
@@ -4,7 +4,7 @@ import { useErc20TokenContract } from "./useERC20"
 import { Token, TransactionType } from "../../enums"
 import { AddressZero } from "@ethersproject/constants"
 import { SupportedChainIds } from "../../networks/enums/networks"
-import { useDefaultOrConnectedChainId } from "../../networks/hooks/useDefaultOrConnectedChainId"
+import { useConnectedOrDefaultChainId } from "../../networks/hooks/useConnectedOrDefaultChainId"
 
 export const T_ADDRESSES = {
   // https://etherscan.io/address/0xCdF7028ceAB81fA0C6971208e83fa7872994beE5
@@ -23,7 +23,7 @@ export interface UseT {
 }
 
 export const useT: UseT = () => {
-  const defaultOrConnectedChainId = useDefaultOrConnectedChainId()
+  const defaultOrConnectedChainId = useConnectedOrDefaultChainId()
   const { balanceOf, approve, contract } = useErc20TokenContract(
     T_ADDRESSES[Number(defaultOrConnectedChainId)],
     undefined,
diff --git a/src/web3/hooks/useTBTCTokenContract.ts b/src/web3/hooks/useTBTCTokenContract.ts
index df2e7e2e1..7a91e0cd7 100644
--- a/src/web3/hooks/useTBTCTokenContract.ts
+++ b/src/web3/hooks/useTBTCTokenContract.ts
@@ -1,7 +1,7 @@
 import { useErc20TokenContract } from "./useERC20"
 import { AddressZero } from "@ethersproject/constants"
 import { SupportedChainIds } from "../../networks/enums/networks"
-import { useDefaultOrConnectedChainId } from "../../networks/hooks/useDefaultOrConnectedChainId"
+import { useConnectedOrDefaultChainId } from "../../networks/hooks/useConnectedOrDefaultChainId"
 
 export const TBTC_ADDRESSES = {
   // https://etherscan.io/address/0x8dAEBADE922dF735c38C80C7eBD708Af50815fAa
@@ -10,7 +10,7 @@ export const TBTC_ADDRESSES = {
 } as Record<number | string, string>
 
 export const useTBTCTokenContract = () => {
-  const defaultOrConnectedChainId = useDefaultOrConnectedChainId()
+  const defaultOrConnectedChainId = useConnectedOrDefaultChainId()
   return useErc20TokenContract(
     TBTC_ADDRESSES[Number(defaultOrConnectedChainId)]
   )
diff --git a/src/web3/hooks/useTBTCv2TokenContract.ts b/src/web3/hooks/useTBTCv2TokenContract.ts
index 64e9f1ccb..91e20a7b2 100644
--- a/src/web3/hooks/useTBTCv2TokenContract.ts
+++ b/src/web3/hooks/useTBTCv2TokenContract.ts
@@ -1,7 +1,7 @@
 import { useErc20TokenContract } from "./useERC20"
 import { AddressZero } from "@ethersproject/constants"
 import { SupportedChainIds } from "../../networks/enums/networks"
-import { useDefaultOrConnectedChainId } from "../../networks/hooks/useDefaultOrConnectedChainId"
+import { useConnectedOrDefaultChainId } from "../../networks/hooks/useConnectedOrDefaultChainId"
 
 export const TBTCV2_ADDRESSES = {
   // https://etherscan.io/address/0x18084fbA666a33d37592fA2633fD49a74DD93a88
@@ -20,7 +20,7 @@ export const TBTCV2_ADDRESSES = {
 // Threshold class instance. A separate, independent instance for the TBTC v2 token is needed to
 // handle network changes smoothly within the app's lifecycle.
 export const useTBTCv2TokenContract = () => {
-  const defaultOrConnectedChainId = useDefaultOrConnectedChainId()
+  const defaultOrConnectedChainId = useConnectedOrDefaultChainId()
   return useErc20TokenContract(
     TBTCV2_ADDRESSES[Number(defaultOrConnectedChainId)]
   )
diff --git a/src/web3/hooks/useTStakingContract.ts b/src/web3/hooks/useTStakingContract.ts
index 52e3b2550..82340222a 100644
--- a/src/web3/hooks/useTStakingContract.ts
+++ b/src/web3/hooks/useTStakingContract.ts
@@ -2,7 +2,7 @@ import TokenStakingABI from "../abi/TokenStaking.json"
 import { useContract } from "./useContract"
 import { SupportedChainIds } from "../../networks/enums/networks"
 import { AddressZero } from "@ethersproject/constants"
-import { useDefaultOrConnectedChainId } from "../../networks/hooks/useDefaultOrConnectedChainId"
+import { useWeb3React } from "@web3-react/core"
 
 const DEPLOYMENT_BLOCKS: { [key: number]: number } = {
   [SupportedChainIds.Ethereum]: 14113768,
@@ -18,15 +18,11 @@ const T_STAKING_ADDRESSES = {
   [SupportedChainIds.Localhost]: AddressZero,
 } as Record<number, string>
 
-export const getTStakingDeploymentBlock = () => {
-  const defaultOrConnectedChainId = useDefaultOrConnectedChainId()
-  return DEPLOYMENT_BLOCKS[Number(defaultOrConnectedChainId)] || 0
+export const getTStakingDeploymentBlock = (chainId?: number | string) => {
+  return DEPLOYMENT_BLOCKS[Number(chainId)] || 0
 }
 
 export const useTStakingContract = () => {
-  const defaultOrConnectedChainId = useDefaultOrConnectedChainId()
-  return useContract(
-    T_STAKING_ADDRESSES[Number(defaultOrConnectedChainId)],
-    TokenStakingABI
-  )
+  const { chainId } = useWeb3React()
+  return useContract(T_STAKING_ADDRESSES[Number(chainId)], TokenStakingABI)
 }

From 95916a1d0c3fd56f5ca403fed38613ee4d5be144 Mon Sep 17 00:00:00 2001
From: evandrosaturnino <evandro.saturnino@gmail.com>
Date: Thu, 28 Nov 2024 06:04:51 -0300
Subject: [PATCH 27/46] Add crosschain fee for arbitrum

---
 src/hooks/tbtc/useFetchDepositDetails.ts      |  4 +-
 src/hooks/tbtc/useFetchTBTCFees.ts            | 60 +++++++++++++++++++
 src/hooks/useTbtcState.ts                     |  1 +
 src/pages/tBTC/Bridge/DepositDetails.tsx      | 20 ++++++-
 .../tBTC/Bridge/Minting/InitiateMinting.tsx   |  3 +-
 src/pages/tBTC/Bridge/Minting/ProvideData.tsx |  2 +
 .../components/MintingTransactionDetails.tsx  | 22 ++++++-
 src/pages/tBTC/Bridge/components/TbtcFees.tsx | 43 +++++++++++++
 src/threshold-ts/tbtc/index.ts                | 34 +++++++++--
 src/types/tbtc.ts                             |  1 +
 10 files changed, 179 insertions(+), 11 deletions(-)
 create mode 100644 src/hooks/tbtc/useFetchTBTCFees.ts
 create mode 100644 src/pages/tBTC/Bridge/components/TbtcFees.tsx

diff --git a/src/hooks/tbtc/useFetchDepositDetails.ts b/src/hooks/tbtc/useFetchDepositDetails.ts
index ab21c1fa8..83252d496 100644
--- a/src/hooks/tbtc/useFetchDepositDetails.ts
+++ b/src/hooks/tbtc/useFetchDepositDetails.ts
@@ -15,6 +15,7 @@ export type DepositData = {
   treasuryFee: string
   optimisticMintFee: string
   isCrossChainDeposit: boolean
+  crossChainFee: string
   l1BitcoinDepositorDepositStatus?: DepositState
 }
 
@@ -97,7 +98,7 @@ export const useFetchDepositDetails = (depositKey: string | undefined) => {
         const requiredConfirmations =
           threshold.tbtc.minimumNumberOfConfirmationsNeeded(deposit.amount)
 
-        const { treasuryFee, optimisticMintFee, amountToMint } =
+        const { treasuryFee, optimisticMintFee, amountToMint, crossChainFee } =
           await threshold.tbtc.getEstimatedDepositFees(deposit.amount)
 
         if (isMounted.current) {
@@ -114,6 +115,7 @@ export const useFetchDepositDetails = (depositKey: string | undefined) => {
             requiredConfirmations,
             confirmations,
             isCrossChainDeposit,
+            crossChainFee,
             l1BitcoinDepositorDepositStatus,
           })
         }
diff --git a/src/hooks/tbtc/useFetchTBTCFees.ts b/src/hooks/tbtc/useFetchTBTCFees.ts
new file mode 100644
index 000000000..3abf88f68
--- /dev/null
+++ b/src/hooks/tbtc/useFetchTBTCFees.ts
@@ -0,0 +1,60 @@
+import { useEffect, useState } from "react"
+import { useThreshold } from "../../contexts/ThresholdContext"
+import { fromSatoshiToTokenPrecision } from "../../threshold-ts/utils"
+
+export type DepositData = {
+  depositTreasuryFeeDivisor: string
+  depositRevealedTxHash: string
+  depositTxMaxFee: string
+}
+
+export const useFetchTBTCFees = () => {
+  const threshold = useThreshold()
+  const [isFetching, setIsFetching] = useState(false)
+  const [error, setError] = useState("")
+  const [tbtcFees, setTbtcFees] = useState<DepositData>({
+    depositTreasuryFeeDivisor: "",
+    depositRevealedTxHash: "",
+    depositTxMaxFee: "",
+  })
+
+  useEffect(() => {
+    const isMounted = { current: true }
+
+    const fetch = async () => {
+      setIsFetching(true)
+      try {
+        if (!isMounted.current) return
+
+        const {
+          depositTreasuryFeeDivisor,
+          optimisticMintingFeeDivisor,
+          depositTxMaxFee,
+        } = await threshold.tbtc.getDepositFees()
+
+        const crossChainDepositTxFee =
+          fromSatoshiToTokenPrecision(depositTxMaxFee)
+
+        if (isMounted.current) {
+          setTbtcFees({
+            depositTreasuryFeeDivisor: depositTreasuryFeeDivisor.toString(),
+            depositRevealedTxHash: optimisticMintingFeeDivisor.toString(),
+            depositTxMaxFee: crossChainDepositTxFee.toString(),
+          })
+        }
+      } catch (error) {
+        if (isMounted.current) setError((error as Error).toString())
+      } finally {
+        if (isMounted.current) setIsFetching(false)
+      }
+    }
+
+    fetch()
+
+    return () => {
+      isMounted.current = false
+    }
+  }, [threshold.tbtc])
+
+  return { isFetching, data: tbtcFees, error }
+}
diff --git a/src/hooks/useTbtcState.ts b/src/hooks/useTbtcState.ts
index 934694c16..326e6e185 100644
--- a/src/hooks/useTbtcState.ts
+++ b/src/hooks/useTbtcState.ts
@@ -32,6 +32,7 @@ export const useTbtcState: UseTbtcState = () => {
     updateState("optimisticMintingRequestedTxHash", undefined)
     updateState("optimisticMintingFinalizedTxHash", undefined)
     updateState("extraData", undefined)
+    updateState("crossChainFee", undefined)
     updateState("chainName", undefined)
   }, [updateState])
 
diff --git a/src/pages/tBTC/Bridge/DepositDetails.tsx b/src/pages/tBTC/Bridge/DepositDetails.tsx
index 98dd9bb53..033e10daf 100644
--- a/src/pages/tBTC/Bridge/DepositDetails.tsx
+++ b/src/pages/tBTC/Bridge/DepositDetails.tsx
@@ -63,7 +63,10 @@ import {
   useSubscribeToOptimisticMintingFinalizedEventBase,
 } from "../../../hooks/tbtc"
 import { tbtcSlice } from "../../../store/tbtc"
-import { ExplorerDataType } from "../../../networks/enums/networks"
+import {
+  ExplorerDataType,
+  SupportedChainIds,
+} from "../../../networks/enums/networks"
 import { PageComponent } from "../../../types"
 import { CurveFactoryPoolId, ExternalHref } from "../../../enums"
 import { ExternalPool } from "../../../components/tBTC/ExternalPool"
@@ -118,6 +121,7 @@ export const DepositDetails: PageComponent = () => {
     data?.optimisticMintingFinalizedTxHash
   const l1BitcoinDepositorDepositStatus = data?.l1BitcoinDepositorDepositStatus
   const isCrossChainDeposit = !!data?.isCrossChainDeposit
+  const crossChainFee = data?.crossChainFee
   const thresholdNetworkFee = data?.treasuryFee
   const mintingFee = data?.optimisticMintFee
 
@@ -196,6 +200,7 @@ export const DepositDetails: PageComponent = () => {
         thresholdNetworkFee,
         mintingFee,
         isCrossChainDeposit: !!data?.isCrossChainDeposit,
+        crossChainFee,
       }}
     >
       <BridgeProcessDetailsCard
@@ -353,6 +358,7 @@ const DepositDetailsPageContext = createContext<
       amount?: string
       mintingFee?: string
       thresholdNetworkFee?: string
+      crossChainFee?: string
     })
   | undefined
 >(undefined)
@@ -467,6 +473,7 @@ const getMintingProgressStep = (
     | "amount"
     | "optimisticMintFee"
     | "treasuryFee"
+    | "crossChainFee"
   >
 ): DepositDetailsTimelineStep => {
   if (!depositDetails) return "bitcoin-confirmations"
@@ -515,6 +522,7 @@ const StepSwitcher: FC = () => {
     updateStep,
     amount,
     thresholdNetworkFee,
+    crossChainFee,
     mintingFee,
     isCrossChainDeposit,
   } = useDepositDetailsPageContext()
@@ -599,6 +607,16 @@ const StepSwitcher: FC = () => {
               precision={6}
               higherPrecision={8}
             />
+            {(chainId === SupportedChainIds.Arbitrum ||
+              chainId === SupportedChainIds.ArbitrumSepolia) && (
+              <TransactionDetailsAmountItem
+                label="Cross Chain Fee"
+                tokenAmount={crossChainFee}
+                tokenSymbol="tBTC"
+                precision={6}
+                higherPrecision={8}
+              />
+            )}
           </List>
           <ButtonLink size="lg" mt="8" mb="8" to="/tBTC" isFullWidth>
             New mint
diff --git a/src/pages/tBTC/Bridge/Minting/InitiateMinting.tsx b/src/pages/tBTC/Bridge/Minting/InitiateMinting.tsx
index 9546c0859..d632d4dbf 100644
--- a/src/pages/tBTC/Bridge/Minting/InitiateMinting.tsx
+++ b/src/pages/tBTC/Bridge/Minting/InitiateMinting.tsx
@@ -40,12 +40,13 @@ const InitiateMintingComponent: FC<{
 
   useEffect(() => {
     const getEstimatedDepositFees = async () => {
-      const { treasuryFee, optimisticMintFee, amountToMint } =
+      const { treasuryFee, optimisticMintFee, amountToMint, crossChainFee } =
         await threshold.tbtc.getEstimatedDepositFees(depositedAmount)
 
       updateState("mintingFee", optimisticMintFee)
       updateState("thresholdNetworkFee", treasuryFee)
       updateState("tBTCMintAmount", amountToMint)
+      updateState("crossChainFee", crossChainFee)
     }
 
     getEstimatedDepositFees()
diff --git a/src/pages/tBTC/Bridge/Minting/ProvideData.tsx b/src/pages/tBTC/Bridge/Minting/ProvideData.tsx
index 06433ccea..74624e51e 100644
--- a/src/pages/tBTC/Bridge/Minting/ProvideData.tsx
+++ b/src/pages/tBTC/Bridge/Minting/ProvideData.tsx
@@ -29,6 +29,7 @@ import { getBridgeBTCSupportedAddressPrefixesText } from "../../../../utils/tBTC
 import { downloadFile, isSameETHAddress } from "../../../../web3/utils"
 import { BridgeProcessCardSubTitle } from "../components/BridgeProcessCardSubTitle"
 import { BridgeProcessCardTitle } from "../components/BridgeProcessCardTitle"
+import TbtcFees from "../components/TbtcFees"
 import { useIsActive } from "../../../../hooks/useIsActive"
 import { PosthogButtonId } from "../../../../types/posthog"
 import SubmitTxButton from "../../../../components/SubmitTxButton"
@@ -259,6 +260,7 @@ export const ProvideDataComponent: FC<{
       >
         Download Deposit Receipt (recommended)
       </Checkbox>
+      <TbtcFees />
       {/* Although the following button doesn't trigger an on-chain transaction, the 
       SubmitTxButton is used here for its built-in TRM Wallet screening validation logic. */}
       <SubmitTxButton
diff --git a/src/pages/tBTC/Bridge/components/MintingTransactionDetails.tsx b/src/pages/tBTC/Bridge/components/MintingTransactionDetails.tsx
index 607db7b50..0b2247d1a 100644
--- a/src/pages/tBTC/Bridge/components/MintingTransactionDetails.tsx
+++ b/src/pages/tBTC/Bridge/components/MintingTransactionDetails.tsx
@@ -5,10 +5,18 @@ import {
 } from "../../../../components/TransactionDetails"
 import { useTbtcState } from "../../../../hooks/useTbtcState"
 import shortenAddress from "../../../../utils/shortenAddress"
+import { useIsActive } from "../../../../hooks/useIsActive"
+import { SupportedChainIds } from "../../../../networks/enums/networks"
 
 const MintingTransactionDetails = () => {
-  const { tBTCMintAmount, mintingFee, thresholdNetworkFee, ethAddress } =
-    useTbtcState()
+  const {
+    tBTCMintAmount,
+    mintingFee,
+    thresholdNetworkFee,
+    ethAddress,
+    crossChainFee,
+  } = useTbtcState()
+  const { chainId } = useIsActive()
 
   return (
     <List spacing="2" mb="6">
@@ -31,6 +39,16 @@ const MintingTransactionDetails = () => {
         precision={6}
         higherPrecision={8}
       />
+      {(chainId === SupportedChainIds.Arbitrum ||
+        chainId === SupportedChainIds.ArbitrumSepolia) && (
+        <TransactionDetailsAmountItem
+          label="Cross Chain Fee"
+          tokenAmount={crossChainFee}
+          tokenSymbol="tBTC"
+          precision={6}
+          higherPrecision={8}
+        />
+      )}
       <TransactionDetailsItem
         label="ETH address"
         value={shortenAddress(ethAddress)}
diff --git a/src/pages/tBTC/Bridge/components/TbtcFees.tsx b/src/pages/tBTC/Bridge/components/TbtcFees.tsx
new file mode 100644
index 000000000..2c8134ef4
--- /dev/null
+++ b/src/pages/tBTC/Bridge/components/TbtcFees.tsx
@@ -0,0 +1,43 @@
+import { List } from "@threshold-network/components"
+import { TransactionDetailsAmountItem } from "../../../../components/TransactionDetails"
+
+import { useFetchTBTCFees } from "../../../../hooks/tbtc/useFetchTBTCFees"
+import { useIsActive } from "../../../../hooks/useIsActive"
+import { SupportedChainIds } from "../../../../networks/enums/networks"
+
+const TbtcFees = () => {
+  const {
+    data: { depositTreasuryFeeDivisor, depositRevealedTxHash, depositTxMaxFee },
+  } = useFetchTBTCFees()
+
+  const { chainId } = useIsActive()
+
+  return (
+    <List spacing="2" mb="6">
+      <TransactionDetailsAmountItem
+        label="Treasury Fee"
+        tokenAmount={depositTreasuryFeeDivisor}
+        tokenSymbol="tBTC"
+      />
+      <TransactionDetailsAmountItem
+        label="Revealed Tx Hash"
+        tokenAmount={depositRevealedTxHash}
+        tokenSymbol="tBTC"
+        precision={6}
+        higherPrecision={8}
+      />
+      {(chainId === SupportedChainIds.Arbitrum ||
+        chainId === SupportedChainIds.ArbitrumSepolia) && (
+        <TransactionDetailsAmountItem
+          label="Cross Chain Fee"
+          tokenAmount={depositTxMaxFee}
+          tokenSymbol="tBTC"
+          precision={6}
+          higherPrecision={8}
+        />
+      )}
+    </List>
+  )
+}
+
+export default TbtcFees
diff --git a/src/threshold-ts/tbtc/index.ts b/src/threshold-ts/tbtc/index.ts
index 40b533ccd..8a7de996c 100644
--- a/src/threshold-ts/tbtc/index.ts
+++ b/src/threshold-ts/tbtc/index.ts
@@ -304,6 +304,19 @@ export interface ITBTC {
     treasuryFee: string
     optimisticMintFee: string
     amountToMint: string
+    crossChainFee: string
+  }>
+
+  /**
+   * Gets the deposit fees divisors and deposit max fee from the tBTC bridge
+   * contract.
+   * @returns depositTreasuryFeeDivisor, optimisticMintingFeeDivisor and
+   * depositTxMaxFee of the tBTC bridge contract
+   */
+  getDepositFees(): Promise<{
+    depositTreasuryFeeDivisor: BigNumber
+    optimisticMintingFeeDivisor: BigNumber
+    depositTxMaxFee: BigNumber
   }>
 
   /**
@@ -848,7 +861,7 @@ export class TBTC implements ITBTC {
       depositTreasuryFeeDivisor,
       optimisticMintingFeeDivisor,
       depositTxMaxFee,
-    } = await this._getDepositFees()
+    } = await this.getDepositFees()
 
     const crossChainTxFee = this.isCrossChain
       ? BigNumber.from(depositTxMaxFee)
@@ -863,7 +876,8 @@ export class TBTC implements ITBTC {
       this._calculateOptimisticMintingAmountAndFee(
         BigNumber.from(depositAmount),
         treasuryFee,
-        optimisticMintingFeeDivisor
+        optimisticMintingFeeDivisor,
+        depositTxMaxFee
       )
 
     return {
@@ -874,7 +888,7 @@ export class TBTC implements ITBTC {
     }
   }
 
-  private _getDepositFees = async (): Promise<{
+  getDepositFees = async (): Promise<{
     depositTreasuryFeeDivisor: BigNumber
     optimisticMintingFeeDivisor: BigNumber
     depositTxMaxFee: BigNumber
@@ -915,9 +929,15 @@ export class TBTC implements ITBTC {
   private _calculateOptimisticMintingAmountAndFee = (
     depositAmount: BigNumber,
     treasuryFee: BigNumber,
-    optimisticMintingFeeDivisor: BigNumber
+    optimisticMintingFeeDivisor: BigNumber,
+    depositTxMaxFee: BigNumber
   ) => {
+    const isArbitrumNetworkConnected =
+      this.ethereumChainId === SupportedChainIds.Arbitrum ||
+      this.ethereumChainId === SupportedChainIds.ArbitrumSepolia
+
     const amountToMint = depositAmount
+      .sub(isArbitrumNetworkConnected ? depositTxMaxFee : ZERO)
       .sub(treasuryFee)
       .mul(this._satoshiMultiplier)
 
@@ -1229,7 +1249,8 @@ export class TBTC implements ITBTC {
   private _calculateEstimatedAmountToMintForRevealedDeposits = async (
     depositKeys: string[]
   ): Promise<Map<string, BigNumber>> => {
-    const { optimisticMintingFeeDivisor } = await this._getDepositFees()
+    const { optimisticMintingFeeDivisor, depositTxMaxFee } =
+      await this.getDepositFees()
 
     const deposits = (
       await this._multicall.aggregate(
@@ -1253,7 +1274,8 @@ export class TBTC implements ITBTC {
           this._calculateOptimisticMintingAmountAndFee(
             deposit.amount,
             deposit.treasuryFee,
-            optimisticMintingFeeDivisor
+            optimisticMintingFeeDivisor,
+            depositTxMaxFee
           ).amountToMint,
         ]
       })
diff --git a/src/types/tbtc.ts b/src/types/tbtc.ts
index 764ac1991..3e0c04257 100644
--- a/src/types/tbtc.ts
+++ b/src/types/tbtc.ts
@@ -22,6 +22,7 @@ export interface TbtcState {
   optimisticMintingFinalizedTxHash?: string
   tBTCMintAmount: string
   thresholdNetworkFee: string
+  crossChainFee: string
   mintingFee: string
   chainName: NetworkName
   extraData?: string

From b249a87f569939e08eb6dee4ad2605d25e4727da Mon Sep 17 00:00:00 2001
From: evandrosaturnino <evandro.saturnino@gmail.com>
Date: Thu, 28 Nov 2024 06:23:20 -0300
Subject: [PATCH 28/46] Handle multicall absence in unsupported networks

---
 src/threshold-ts/multicall/index.ts | 28 ++++++++++++++++++----------
 1 file changed, 18 insertions(+), 10 deletions(-)

diff --git a/src/threshold-ts/multicall/index.ts b/src/threshold-ts/multicall/index.ts
index 65b0df661..1127b57d4 100644
--- a/src/threshold-ts/multicall/index.ts
+++ b/src/threshold-ts/multicall/index.ts
@@ -52,23 +52,27 @@ export const MULTICALL_ADDRESSES = {
 } as Record<number | string, string>
 
 export class Multicall implements IMulticall {
-  private _multicall: Contract
+  private _multicall: Contract | null
 
   constructor(config: EthereumConfig) {
     const address = MULTICALL_ADDRESSES[config.chainId]
-    if (!address) {
-      throw new Error("Unsupported chain id")
-    }
 
-    this._multicall = getContract(
-      address,
-      MULTICALL_ABI,
-      config.providerOrSigner,
-      config.account
-    )
+    this._multicall = address
+      ? getContract(
+          address,
+          MULTICALL_ABI,
+          config.providerOrSigner,
+          config.account
+        )
+      : null
   }
 
   async aggregate(calls: ContractCall[]): Promise<any[]> {
+    if (!this._multicall) {
+      console.warn("Multicall contract is not available on this network.")
+      return []
+    }
+
     const callRequests = calls.map((_) => [
       _.address,
       _.interface.encodeFunctionData(_.method, _.args),
@@ -83,6 +87,10 @@ export class Multicall implements IMulticall {
   }
 
   getCurrentBlockTimestampCallObj = () => {
+    if (!this._multicall) {
+      throw new Error("Multicall contract is not available on this network.")
+    }
+
     return {
       interface: this._multicall.interface,
       address: this._multicall.address,

From 3f8c23793278784eddbbe4746f3f4a7a694a0543 Mon Sep 17 00:00:00 2001
From: evandrosaturnino <evandro.saturnino@gmail.com>
Date: Thu, 28 Nov 2024 20:38:31 -0300
Subject: [PATCH 29/46] Fix tbtc minting percentage fees formats

---
 .../Modal/tBTC/InitiateUnminting.tsx          |  8 ++---
 src/components/TransactionDetails/index.tsx   | 17 ++++++----
 src/constants/web3.ts                         |  4 +++
 src/hooks/tbtc/useFetchTBTCFees.ts            | 33 ++++++++++++++-----
 src/pages/tBTC/Bridge/DepositDetails.tsx      | 16 ++++-----
 src/pages/tBTC/Bridge/UnmintDetails.tsx       | 12 +++----
 .../components/MintingTransactionDetails.tsx  | 16 ++++-----
 src/pages/tBTC/Bridge/components/TbtcFees.tsx | 22 +++++++------
 8 files changed, 78 insertions(+), 50 deletions(-)

diff --git a/src/components/Modal/tBTC/InitiateUnminting.tsx b/src/components/Modal/tBTC/InitiateUnminting.tsx
index 40d4d211d..d86050215 100644
--- a/src/components/Modal/tBTC/InitiateUnminting.tsx
+++ b/src/components/Modal/tBTC/InitiateUnminting.tsx
@@ -101,17 +101,17 @@ const InitiateUnmintingBase: FC<InitiateUnmintingProps> = ({
         <List mt="6" spacing="2">
           <TransactionDetailsAmountItem
             label="Unminted Amount"
-            tokenAmount={unmintAmount}
-            tokenSymbol="tBTC"
+            amount={unmintAmount}
+            suffixItem="tBTC"
             precision={6}
             higherPrecision={8}
           />
           <TransactionDetailsAmountItem
             label="Threshold Network Fee"
-            tokenSymbol="tBTC"
+            amount={thresholdNetworkFee}
+            suffixItem="tBTC"
             precision={6}
             higherPrecision={8}
-            tokenAmount={thresholdNetworkFee}
           />
           <TransactionDetailsItem
             label="BTC address"
diff --git a/src/components/TransactionDetails/index.tsx b/src/components/TransactionDetails/index.tsx
index bdb9ee7ed..c881ce1b2 100644
--- a/src/components/TransactionDetails/index.tsx
+++ b/src/components/TransactionDetails/index.tsx
@@ -31,20 +31,25 @@ type TransactionDetailsAmountItemProps = Omit<
   ComponentProps<typeof InlineTokenBalance>,
   "tokenAmount"
 > &
-  Pick<TransactionDetailsItemProps, "label"> & { tokenAmount?: string }
+  Pick<TransactionDetailsItemProps, "label"> & {
+    amount?: string
+    suffixItem?: string
+    isFetching?: boolean
+  }
 
 export const TransactionDetailsAmountItem: FC<
   TransactionDetailsAmountItemProps
-> = ({ label, tokenAmount, ...restProps }) => {
-  const tokenBalanceTextColor = useColorModeValue("gray.700", "gray.300")
+> = ({ label, amount, suffixItem, isFetching = false, ...restProps }) => {
+  const textColor = useColorModeValue("gray.700", "gray.300")
 
   return (
     <TransactionDetailsItem label={label}>
-      <Skeleton isLoaded={!!tokenAmount}>
-        <BodySm color={tokenBalanceTextColor}>
+      <Skeleton isLoaded={!isFetching && !!amount}>
+        <BodySm color={textColor}>
           <InlineTokenBalance
             withSymbol
-            tokenAmount={tokenAmount || "0"}
+            tokenAmount={amount || "0"}
+            tokenSymbol={suffixItem || ""}
             {...restProps}
           />
         </BodySm>
diff --git a/src/constants/web3.ts b/src/constants/web3.ts
index fce9d7b94..b4cf0b187 100644
--- a/src/constants/web3.ts
+++ b/src/constants/web3.ts
@@ -1 +1,5 @@
+import { BigNumber } from "ethers"
+
 export const STANDARD_ERC20_DECIMALS = 18
+export const SATOSHI_MULTIPLIER = BigNumber.from(10).pow(8)
+export const ONE_HUNDRED = BigNumber.from(100)
diff --git a/src/hooks/tbtc/useFetchTBTCFees.ts b/src/hooks/tbtc/useFetchTBTCFees.ts
index 3abf88f68..ae0bdf7cc 100644
--- a/src/hooks/tbtc/useFetchTBTCFees.ts
+++ b/src/hooks/tbtc/useFetchTBTCFees.ts
@@ -1,10 +1,12 @@
 import { useEffect, useState } from "react"
 import { useThreshold } from "../../contexts/ThresholdContext"
-import { fromSatoshiToTokenPrecision } from "../../threshold-ts/utils"
+import { fromSatoshiToTokenPrecision, ZERO } from "../../threshold-ts/utils"
+import { BigNumber } from "ethers"
+import { ONE_HUNDRED, SATOSHI_MULTIPLIER } from "../../constants/web3"
 
 export type DepositData = {
-  depositTreasuryFeeDivisor: string
-  depositRevealedTxHash: string
+  depositTreasuryFee: string
+  optimisticMintingFee: string
   depositTxMaxFee: string
 }
 
@@ -13,8 +15,8 @@ export const useFetchTBTCFees = () => {
   const [isFetching, setIsFetching] = useState(false)
   const [error, setError] = useState("")
   const [tbtcFees, setTbtcFees] = useState<DepositData>({
-    depositTreasuryFeeDivisor: "",
-    depositRevealedTxHash: "",
+    depositTreasuryFee: "",
+    optimisticMintingFee: "",
     depositTxMaxFee: "",
   })
 
@@ -32,13 +34,28 @@ export const useFetchTBTCFees = () => {
           depositTxMaxFee,
         } = await threshold.tbtc.getDepositFees()
 
+        const oneHundredInSatoshi = ONE_HUNDRED.mul(SATOSHI_MULTIPLIER)
+
+        const depositTreasuryFee = depositTreasuryFeeDivisor.gt(ZERO)
+          ? oneHundredInSatoshi.div(depositTreasuryFeeDivisor)
+          : ZERO
+        const optimisticMintingFee = optimisticMintingFeeDivisor.gt(ZERO)
+          ? oneHundredInSatoshi.div(optimisticMintingFeeDivisor)
+          : ZERO
+
+        const depositTreasuryFeeToTokenPrecision =
+          fromSatoshiToTokenPrecision(depositTreasuryFee)
+
+        const optimisticMintingFeeToTokenPrecision =
+          fromSatoshiToTokenPrecision(optimisticMintingFee)
         const crossChainDepositTxFee =
           fromSatoshiToTokenPrecision(depositTxMaxFee)
 
         if (isMounted.current) {
           setTbtcFees({
-            depositTreasuryFeeDivisor: depositTreasuryFeeDivisor.toString(),
-            depositRevealedTxHash: optimisticMintingFeeDivisor.toString(),
+            depositTreasuryFee: depositTreasuryFeeToTokenPrecision.toString(),
+            optimisticMintingFee:
+              optimisticMintingFeeToTokenPrecision.toString(),
             depositTxMaxFee: crossChainDepositTxFee.toString(),
           })
         }
@@ -54,7 +71,7 @@ export const useFetchTBTCFees = () => {
     return () => {
       isMounted.current = false
     }
-  }, [threshold.tbtc])
+  }, [threshold.tbtc.ethereumChainId])
 
   return { isFetching, data: tbtcFees, error }
 }
diff --git a/src/pages/tBTC/Bridge/DepositDetails.tsx b/src/pages/tBTC/Bridge/DepositDetails.tsx
index 033e10daf..662b9c18d 100644
--- a/src/pages/tBTC/Bridge/DepositDetails.tsx
+++ b/src/pages/tBTC/Bridge/DepositDetails.tsx
@@ -590,20 +590,20 @@ const StepSwitcher: FC = () => {
           <List spacing="2">
             <TransactionDetailsAmountItem
               label="Minted Amount"
-              tokenAmount={amount}
-              tokenSymbol="tBTC"
+              amount={amount}
+              suffixItem="tBTC"
             />
             <TransactionDetailsAmountItem
               label="Minting Fee"
-              tokenAmount={mintingFee}
-              tokenSymbol="tBTC"
+              amount={mintingFee}
+              suffixItem="tBTC"
               precision={6}
               higherPrecision={8}
             />
             <TransactionDetailsAmountItem
               label="Threshold Network Fee"
-              tokenAmount={thresholdNetworkFee}
-              tokenSymbol="tBTC"
+              amount={thresholdNetworkFee}
+              suffixItem="tBTC"
               precision={6}
               higherPrecision={8}
             />
@@ -611,8 +611,8 @@ const StepSwitcher: FC = () => {
               chainId === SupportedChainIds.ArbitrumSepolia) && (
               <TransactionDetailsAmountItem
                 label="Cross Chain Fee"
-                tokenAmount={crossChainFee}
-                tokenSymbol="tBTC"
+                amount={crossChainFee}
+                suffixItem="tBTC"
                 precision={6}
                 higherPrecision={8}
               />
diff --git a/src/pages/tBTC/Bridge/UnmintDetails.tsx b/src/pages/tBTC/Bridge/UnmintDetails.tsx
index 3fde6970f..25310cc0c 100644
--- a/src/pages/tBTC/Bridge/UnmintDetails.tsx
+++ b/src/pages/tBTC/Bridge/UnmintDetails.tsx
@@ -380,15 +380,15 @@ const SuccessStep: FC<{
       <List spacing="4">
         <TransactionDetailsAmountItem
           label="Unminted Amount"
-          tokenAmount={requestedAmount}
-          tokenSymbol="tBTC"
+          amount={requestedAmount}
+          suffixItem="tBTC"
           precision={6}
           higherPrecision={8}
         />
         <TransactionDetailsAmountItem
           label="Received Amount"
-          tokenAmount={receivedAmount}
-          tokenSymbol="BTC"
+          amount={receivedAmount}
+          suffixItem="BTC"
           tokenDecimals={8}
           precision={6}
           higherPrecision={8}
@@ -396,8 +396,8 @@ const SuccessStep: FC<{
         />
         <TransactionDetailsAmountItem
           label="Threshold Network Fee"
-          tokenAmount={thresholdNetworkFee}
-          tokenSymbol="tBTC"
+          amount={thresholdNetworkFee}
+          suffixItem="tBTC"
           precision={6}
           higherPrecision={8}
         />
diff --git a/src/pages/tBTC/Bridge/components/MintingTransactionDetails.tsx b/src/pages/tBTC/Bridge/components/MintingTransactionDetails.tsx
index 0b2247d1a..fe0af5151 100644
--- a/src/pages/tBTC/Bridge/components/MintingTransactionDetails.tsx
+++ b/src/pages/tBTC/Bridge/components/MintingTransactionDetails.tsx
@@ -22,20 +22,20 @@ const MintingTransactionDetails = () => {
     <List spacing="2" mb="6">
       <TransactionDetailsAmountItem
         label="Amount To Be Minted"
-        tokenAmount={tBTCMintAmount}
-        tokenSymbol="tBTC"
+        amount={tBTCMintAmount}
+        suffixItem="tBTC"
       />
       <TransactionDetailsAmountItem
         label="Minting Fee"
-        tokenAmount={mintingFee}
-        tokenSymbol="tBTC"
+        amount={mintingFee}
+        suffixItem="tBTC"
         precision={6}
         higherPrecision={8}
       />
       <TransactionDetailsAmountItem
         label="Threshold Network Fee"
-        tokenAmount={thresholdNetworkFee}
-        tokenSymbol="tBTC"
+        amount={thresholdNetworkFee}
+        suffixItem="tBTC"
         precision={6}
         higherPrecision={8}
       />
@@ -43,8 +43,8 @@ const MintingTransactionDetails = () => {
         chainId === SupportedChainIds.ArbitrumSepolia) && (
         <TransactionDetailsAmountItem
           label="Cross Chain Fee"
-          tokenAmount={crossChainFee}
-          tokenSymbol="tBTC"
+          amount={crossChainFee}
+          suffixItem="tBTC"
           precision={6}
           higherPrecision={8}
         />
diff --git a/src/pages/tBTC/Bridge/components/TbtcFees.tsx b/src/pages/tBTC/Bridge/components/TbtcFees.tsx
index 2c8134ef4..74c6b7d78 100644
--- a/src/pages/tBTC/Bridge/components/TbtcFees.tsx
+++ b/src/pages/tBTC/Bridge/components/TbtcFees.tsx
@@ -7,7 +7,8 @@ import { SupportedChainIds } from "../../../../networks/enums/networks"
 
 const TbtcFees = () => {
   const {
-    data: { depositTreasuryFeeDivisor, depositRevealedTxHash, depositTxMaxFee },
+    data: { depositTreasuryFee, optimisticMintingFee, depositTxMaxFee },
+    isFetching,
   } = useFetchTBTCFees()
 
   const { chainId } = useIsActive()
@@ -16,24 +17,25 @@ const TbtcFees = () => {
     <List spacing="2" mb="6">
       <TransactionDetailsAmountItem
         label="Treasury Fee"
-        tokenAmount={depositTreasuryFeeDivisor}
-        tokenSymbol="tBTC"
+        amount={depositTreasuryFee}
+        suffixItem="%"
+        isFetching={isFetching}
       />
       <TransactionDetailsAmountItem
-        label="Revealed Tx Hash"
-        tokenAmount={depositRevealedTxHash}
-        tokenSymbol="tBTC"
-        precision={6}
-        higherPrecision={8}
+        label="Optimistic Minting Fee"
+        amount={optimisticMintingFee}
+        suffixItem="%"
+        isFetching={isFetching}
       />
       {(chainId === SupportedChainIds.Arbitrum ||
         chainId === SupportedChainIds.ArbitrumSepolia) && (
         <TransactionDetailsAmountItem
           label="Cross Chain Fee"
-          tokenAmount={depositTxMaxFee}
-          tokenSymbol="tBTC"
+          amount={depositTxMaxFee}
+          suffixItem="tBTC"
           precision={6}
           higherPrecision={8}
+          isFetching={isFetching}
         />
       )}
     </List>

From 3eca3d31240425b3e0951a9c59f012a68185b11a Mon Sep 17 00:00:00 2001
From: evandrosaturnino <evandro.saturnino@gmail.com>
Date: Fri, 29 Nov 2024 00:04:21 -0300
Subject: [PATCH 30/46] Fix staking app name variable

---
 .../StakingApplications/ConfirmDeauthorization.tsx    | 11 +++++------
 1 file changed, 5 insertions(+), 6 deletions(-)

diff --git a/src/components/Modal/StakingApplications/ConfirmDeauthorization.tsx b/src/components/Modal/StakingApplications/ConfirmDeauthorization.tsx
index d1aa967bf..38f7077dd 100644
--- a/src/components/Modal/StakingApplications/ConfirmDeauthorization.tsx
+++ b/src/components/Modal/StakingApplications/ConfirmDeauthorization.tsx
@@ -29,22 +29,21 @@ import { useThreshold } from "../../../contexts/ThresholdContext"
 
 export type ConfirmDeauthorizationProps = BaseModalProps & {
   stakingProvider: string
-  stakingAppName: StakingAppName
+  appName: StakingAppName
   decreaseAmount: string
 }
 
 const ConfirmDeauthorizationBase: FC<ConfirmDeauthorizationProps> = ({
   stakingProvider,
-  stakingAppName,
+  appName,
   decreaseAmount,
   closeModal,
 }) => {
   const threshold = useThreshold()
   const stakingAppContract =
-    threshold.multiAppStaking[appNameToThresholdApp[stakingAppName]]?.contract
+    threshold.multiAppStaking[appNameToThresholdApp[appName]]?.contract
 
-  const { sendTransaction } =
-    useConfirmDeauthorizationTransaction(stakingAppName)
+  const { sendTransaction } = useConfirmDeauthorizationTransaction(appName)
 
   const onDeauthorize = async () => {
     await sendTransaction(stakingProvider)
@@ -60,7 +59,7 @@ const ConfirmDeauthorizationBase: FC<ConfirmDeauthorizationProps> = ({
           <BodyLg mt="4">Confirm your deauthorization.</BodyLg>
         </InfoBox>
         <StakingApplicationOperationIcon
-          stakingApplication={stakingAppName}
+          stakingApplication={appName}
           operation="decrease"
           w="88px"
           h="88px"

From adbe05e0e7cbb519e00bcd3304947eb543e54d66 Mon Sep 17 00:00:00 2001
From: evandrosaturnino <evandro.saturnino@gmail.com>
Date: Tue, 10 Dec 2024 17:53:11 -0300
Subject: [PATCH 31/46] Fix typos in app pages

---
 .../HowItWorks/StakingOverview/AuthorizingApplicationsCard.tsx  | 2 +-
 src/pages/tBTC/Bridge/Minting/ProvideData.tsx                   | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/pages/Staking/HowItWorks/StakingOverview/AuthorizingApplicationsCard.tsx b/src/pages/Staking/HowItWorks/StakingOverview/AuthorizingApplicationsCard.tsx
index 84897e385..b7b75fdc5 100644
--- a/src/pages/Staking/HowItWorks/StakingOverview/AuthorizingApplicationsCard.tsx
+++ b/src/pages/Staking/HowItWorks/StakingOverview/AuthorizingApplicationsCard.tsx
@@ -62,7 +62,7 @@ export const AuthorizingApplicationsCard: FC<ComponentProps<typeof Card>> = (
           size="sm"
         >
           There is a deauthorization cooldown period of 45 days for tBTC and
-          Random Beacon apps and 6 months for TACo.
+          Random Beacon, and 6 months for TACo.
         </FlowStep>
       </Stack>
     </Card>
diff --git a/src/pages/tBTC/Bridge/Minting/ProvideData.tsx b/src/pages/tBTC/Bridge/Minting/ProvideData.tsx
index 74624e51e..646a5b9d3 100644
--- a/src/pages/tBTC/Bridge/Minting/ProvideData.tsx
+++ b/src/pages/tBTC/Bridge/Minting/ProvideData.tsx
@@ -150,7 +150,7 @@ export const ProvideDataComponent: FC<{
 
       if (!isSupportedNetwork(chainId)) {
         throw new Error(
-          "Your wallet is on an unsupported network. Switch to a supported network"
+          "You are currently connected to an unsupported network. Switch to a supported network"
         )
       }
 

From 0d796b56f3179ce61a3d5c22a46d6bedcc15b3e4 Mon Sep 17 00:00:00 2001
From: evandrosaturnino <evandro.saturnino@gmail.com>
Date: Tue, 10 Dec 2024 17:55:06 -0300
Subject: [PATCH 32/46] Fix memory leak in use send transaction hook

---
 src/web3/hooks/useSendTransaction.ts | 85 ++++++++++++++++++----------
 1 file changed, 56 insertions(+), 29 deletions(-)

diff --git a/src/web3/hooks/useSendTransaction.ts b/src/web3/hooks/useSendTransaction.ts
index 4352f74e7..16146cd7d 100644
--- a/src/web3/hooks/useSendTransaction.ts
+++ b/src/web3/hooks/useSendTransaction.ts
@@ -1,4 +1,4 @@
-import { useCallback, useState } from "react"
+import { useCallback, useEffect, useRef, useState } from "react"
 import { useWeb3React } from "@web3-react/core"
 import { Contract, ContractTransaction } from "@ethersproject/contracts"
 import { ModalType, TransactionStatus } from "../../enums"
@@ -60,6 +60,13 @@ export const useSendTransactionFromFn = <
   const { ledgerLiveAppEthereumSigner: signer } = useLedgerLiveApp()
   const { isEmbed } = useIsEmbed()
 
+  const isMounted = useRef(true)
+  useEffect(() => {
+    return () => {
+      isMounted.current = false
+    }
+  }, [])
+
   const sendTransaction = useCallback(
     async (...args: Parameters<typeof fn>) => {
       try {
@@ -74,15 +81,20 @@ export const useSendTransactionFromFn = <
           throw new Error(errorMessage)
         }
 
-        setTransactionStatus(TransactionStatus.PendingWallet)
-        openModal(ModalType.TransactionIsWaitingForConfirmation)
+        if (isMounted.current) {
+          setTransactionStatus(TransactionStatus.PendingWallet)
+          openModal(ModalType.TransactionIsWaitingForConfirmation)
+        }
         const tx = await fn(...args)
 
         const txHash = typeof tx === "string" ? tx : tx.hash
-        openModal(ModalType.TransactionIsPending, {
-          transactionHash: txHash,
-        })
-        setTransactionStatus(TransactionStatus.PendingOnChain)
+
+        if (isMounted.current) {
+          openModal(ModalType.TransactionIsPending, {
+            transactionHash: txHash,
+          })
+          setTransactionStatus(TransactionStatus.PendingOnChain)
+        }
 
         let txReceipt: TransactionReceipt
         if (isEmbed) {
@@ -96,34 +108,49 @@ export const useSendTransactionFromFn = <
             : library.waitForTransaction(txHash))
         }
 
-        setTransactionStatus(TransactionStatus.Succeeded)
-        if (onSuccess) {
-          const additionalParams = isTransactionHashWithAdditionalParams(tx)
-            ? (tx as TransactionHashWithAdditionalParams).additionalParams
-            : null
-          onSuccess(txReceipt, additionalParams)
+        if (isMounted.current) {
+          setTransactionStatus(TransactionStatus.Succeeded)
+          if (onSuccess) {
+            const additionalParams = isTransactionHashWithAdditionalParams(tx)
+              ? (tx as TransactionHashWithAdditionalParams).additionalParams
+              : null
+            await onSuccess(txReceipt, additionalParams)
+          }
         }
         return txReceipt
       } catch (error: any) {
-        setTransactionStatus(
-          isWalletRejectionError(error)
-            ? TransactionStatus.Rejected
-            : TransactionStatus.Failed
-        )
-
-        if (onError) {
-          onError(error)
-        } else {
-          openModal(ModalType.TransactionFailed, {
-            transactionHash: error?.transaction?.hash,
-            error: error?.message,
-            // TODO: how to check if an error is expandable?
-            isExpandableError: true,
-          })
+        if (isMounted.current) {
+          setTransactionStatus(
+            isWalletRejectionError(error)
+              ? TransactionStatus.Rejected
+              : TransactionStatus.Failed
+          )
+
+          if (onError) {
+            await onError(error)
+          } else {
+            openModal(ModalType.TransactionFailed, {
+              transactionHash: error?.transaction?.hash,
+              error: error?.message,
+              // TODO: how to check if an error is expandable?
+              isExpandableError: true,
+            })
+          }
         }
       }
     },
-    [fn, account, onError, onSuccess, openModal]
+    [
+      fn,
+      account,
+      onError,
+      onSuccess,
+      openModal,
+      isEmbed,
+      isBlocked,
+      isFetching,
+      library,
+      signer,
+    ]
   )
 
   return { sendTransaction, status: transactionStatus }

From 29e0f38cb5730ce34208a9fc2494476fb8d7d572 Mon Sep 17 00:00:00 2001
From: evandrosaturnino <evandro.saturnino@gmail.com>
Date: Mon, 16 Dec 2024 21:43:40 -0300
Subject: [PATCH 33/46] update mainnet taco application artifact source

---
 .../mas/mainnet-artifacts/TacoRegistry.json   | 1646 -----------------
 src/threshold-ts/utils/contract.ts            |    5 +-
 2 files changed, 3 insertions(+), 1648 deletions(-)
 delete mode 100644 src/threshold-ts/mas/mainnet-artifacts/TacoRegistry.json

diff --git a/src/threshold-ts/mas/mainnet-artifacts/TacoRegistry.json b/src/threshold-ts/mas/mainnet-artifacts/TacoRegistry.json
deleted file mode 100644
index 681f5b44a..000000000
--- a/src/threshold-ts/mas/mainnet-artifacts/TacoRegistry.json
+++ /dev/null
@@ -1,1646 +0,0 @@
-{
-  "address": "0x347CC7ede7e5517bD47D20620B2CF1b406edcF07",
-  "abi": [
-    {
-      "type": "constructor",
-      "stateMutability": "nonpayable",
-      "inputs": [
-        {
-          "name": "_token",
-          "type": "address",
-          "internalType": "contract IERC20"
-        },
-        {
-          "name": "_tStaking",
-          "type": "address",
-          "internalType": "contract IStaking"
-        },
-        {
-          "name": "_minimumAuthorization",
-          "type": "uint96",
-          "internalType": "uint96"
-        },
-        {
-          "name": "_minOperatorSeconds",
-          "type": "uint256",
-          "internalType": "uint256"
-        },
-        {
-          "name": "_rewardDuration",
-          "type": "uint256",
-          "internalType": "uint256"
-        },
-        {
-          "name": "_deauthorizationDuration",
-          "type": "uint256",
-          "internalType": "uint256"
-        },
-        {
-          "name": "_commitmentDurationOptions",
-          "type": "uint64[]",
-          "internalType": "uint64[]"
-        },
-        {
-          "name": "_commitmentDeadline",
-          "type": "uint64",
-          "internalType": "uint64"
-        },
-        {
-          "name": "_penaltyDefault",
-          "type": "uint192",
-          "internalType": "uint192"
-        },
-        {
-          "name": "_penaltyDuration",
-          "type": "uint256",
-          "internalType": "uint256"
-        },
-        {
-          "name": "_penaltyIncrement",
-          "type": "uint192",
-          "internalType": "uint192"
-        }
-      ]
-    },
-    {
-      "type": "error",
-      "name": "AddressEmptyCode",
-      "inputs": [
-        {
-          "name": "target",
-          "type": "address",
-          "internalType": "address"
-        }
-      ]
-    },
-    {
-      "type": "error",
-      "name": "AddressInsufficientBalance",
-      "inputs": [
-        {
-          "name": "account",
-          "type": "address",
-          "internalType": "address"
-        }
-      ]
-    },
-    {
-      "type": "error",
-      "name": "FailedInnerCall",
-      "inputs": []
-    },
-    {
-      "type": "error",
-      "name": "InvalidInitialization",
-      "inputs": []
-    },
-    {
-      "type": "error",
-      "name": "NotInitializing",
-      "inputs": []
-    },
-    {
-      "type": "error",
-      "name": "OwnableInvalidOwner",
-      "inputs": [
-        {
-          "name": "owner",
-          "type": "address",
-          "internalType": "address"
-        }
-      ]
-    },
-    {
-      "type": "error",
-      "name": "OwnableUnauthorizedAccount",
-      "inputs": [
-        {
-          "name": "account",
-          "type": "address",
-          "internalType": "address"
-        }
-      ]
-    },
-    {
-      "type": "error",
-      "name": "SafeCastOverflowedUintDowncast",
-      "inputs": [
-        {
-          "name": "bits",
-          "type": "uint8",
-          "internalType": "uint8"
-        },
-        {
-          "name": "value",
-          "type": "uint256",
-          "internalType": "uint256"
-        }
-      ]
-    },
-    {
-      "type": "error",
-      "name": "SafeERC20FailedOperation",
-      "inputs": [
-        {
-          "name": "token",
-          "type": "address",
-          "internalType": "address"
-        }
-      ]
-    },
-    {
-      "type": "event",
-      "name": "AuthorizationDecreaseApproved",
-      "inputs": [
-        {
-          "name": "stakingProvider",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        },
-        {
-          "name": "fromAmount",
-          "type": "uint96",
-          "internalType": "uint96",
-          "indexed": false
-        },
-        {
-          "name": "toAmount",
-          "type": "uint96",
-          "internalType": "uint96",
-          "indexed": false
-        }
-      ],
-      "anonymous": false
-    },
-    {
-      "type": "event",
-      "name": "AuthorizationDecreaseRequested",
-      "inputs": [
-        {
-          "name": "stakingProvider",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        },
-        {
-          "name": "fromAmount",
-          "type": "uint96",
-          "internalType": "uint96",
-          "indexed": false
-        },
-        {
-          "name": "toAmount",
-          "type": "uint96",
-          "internalType": "uint96",
-          "indexed": false
-        }
-      ],
-      "anonymous": false
-    },
-    {
-      "type": "event",
-      "name": "AuthorizationIncreased",
-      "inputs": [
-        {
-          "name": "stakingProvider",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        },
-        {
-          "name": "fromAmount",
-          "type": "uint96",
-          "internalType": "uint96",
-          "indexed": false
-        },
-        {
-          "name": "toAmount",
-          "type": "uint96",
-          "internalType": "uint96",
-          "indexed": false
-        }
-      ],
-      "anonymous": false
-    },
-    {
-      "type": "event",
-      "name": "AuthorizationInvoluntaryDecreased",
-      "inputs": [
-        {
-          "name": "stakingProvider",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        },
-        {
-          "name": "fromAmount",
-          "type": "uint96",
-          "internalType": "uint96",
-          "indexed": false
-        },
-        {
-          "name": "toAmount",
-          "type": "uint96",
-          "internalType": "uint96",
-          "indexed": false
-        }
-      ],
-      "anonymous": false
-    },
-    {
-      "type": "event",
-      "name": "AuthorizationReSynchronized",
-      "inputs": [
-        {
-          "name": "stakingProvider",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        },
-        {
-          "name": "fromAmount",
-          "type": "uint96",
-          "internalType": "uint96",
-          "indexed": false
-        },
-        {
-          "name": "toAmount",
-          "type": "uint96",
-          "internalType": "uint96",
-          "indexed": false
-        }
-      ],
-      "anonymous": false
-    },
-    {
-      "type": "event",
-      "name": "CommitmentMade",
-      "inputs": [
-        {
-          "name": "stakingProvider",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        },
-        {
-          "name": "endCommitment",
-          "type": "uint256",
-          "internalType": "uint256",
-          "indexed": false
-        }
-      ],
-      "anonymous": false
-    },
-    {
-      "type": "event",
-      "name": "Initialized",
-      "inputs": [
-        {
-          "name": "version",
-          "type": "uint64",
-          "internalType": "uint64",
-          "indexed": false
-        }
-      ],
-      "anonymous": false
-    },
-    {
-      "type": "event",
-      "name": "ManualChildSynchronizationSent",
-      "inputs": [
-        {
-          "name": "stakingProvider",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        },
-        {
-          "name": "authorized",
-          "type": "uint96",
-          "internalType": "uint96",
-          "indexed": false
-        },
-        {
-          "name": "deauthorizing",
-          "type": "uint96",
-          "internalType": "uint96",
-          "indexed": false
-        },
-        {
-          "name": "endDeauthorization",
-          "type": "uint64",
-          "internalType": "uint64",
-          "indexed": false
-        },
-        {
-          "name": "operator",
-          "type": "address",
-          "internalType": "address",
-          "indexed": false
-        }
-      ],
-      "anonymous": false
-    },
-    {
-      "type": "event",
-      "name": "OperatorBonded",
-      "inputs": [
-        {
-          "name": "stakingProvider",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        },
-        {
-          "name": "operator",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        },
-        {
-          "name": "previousOperator",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        },
-        {
-          "name": "startTimestamp",
-          "type": "uint256",
-          "internalType": "uint256",
-          "indexed": false
-        }
-      ],
-      "anonymous": false
-    },
-    {
-      "type": "event",
-      "name": "OperatorConfirmed",
-      "inputs": [
-        {
-          "name": "stakingProvider",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        },
-        {
-          "name": "operator",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        }
-      ],
-      "anonymous": false
-    },
-    {
-      "type": "event",
-      "name": "OwnershipTransferred",
-      "inputs": [
-        {
-          "name": "previousOwner",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        },
-        {
-          "name": "newOwner",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        }
-      ],
-      "anonymous": false
-    },
-    {
-      "type": "event",
-      "name": "Penalized",
-      "inputs": [
-        {
-          "name": "stakingProvider",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        },
-        {
-          "name": "penaltyPercent",
-          "type": "uint256",
-          "internalType": "uint256",
-          "indexed": false
-        },
-        {
-          "name": "endPenalty",
-          "type": "uint64",
-          "internalType": "uint64",
-          "indexed": false
-        }
-      ],
-      "anonymous": false
-    },
-    {
-      "type": "event",
-      "name": "RewardAdded",
-      "inputs": [
-        {
-          "name": "reward",
-          "type": "uint256",
-          "internalType": "uint256",
-          "indexed": false
-        }
-      ],
-      "anonymous": false
-    },
-    {
-      "type": "event",
-      "name": "RewardContractSet",
-      "inputs": [
-        {
-          "name": "rewardContract",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        }
-      ],
-      "anonymous": false
-    },
-    {
-      "type": "event",
-      "name": "RewardDistributorSet",
-      "inputs": [
-        {
-          "name": "distributor",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        }
-      ],
-      "anonymous": false
-    },
-    {
-      "type": "event",
-      "name": "RewardPaid",
-      "inputs": [
-        {
-          "name": "sender",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        },
-        {
-          "name": "stakingProvider",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        },
-        {
-          "name": "beneficiary",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        },
-        {
-          "name": "reward",
-          "type": "uint256",
-          "internalType": "uint256",
-          "indexed": false
-        }
-      ],
-      "anonymous": false
-    },
-    {
-      "type": "event",
-      "name": "RewardReset",
-      "inputs": [
-        {
-          "name": "stakingProvider",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        }
-      ],
-      "anonymous": false
-    },
-    {
-      "type": "event",
-      "name": "RewardsWithdrawn",
-      "inputs": [
-        {
-          "name": "stakingProvider",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        },
-        {
-          "name": "amount",
-          "type": "uint96",
-          "internalType": "uint96",
-          "indexed": false
-        }
-      ],
-      "anonymous": false
-    },
-    {
-      "type": "event",
-      "name": "Slashed",
-      "inputs": [
-        {
-          "name": "stakingProvider",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        },
-        {
-          "name": "penalty",
-          "type": "uint256",
-          "internalType": "uint256",
-          "indexed": false
-        },
-        {
-          "name": "investigator",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        },
-        {
-          "name": "reward",
-          "type": "uint256",
-          "internalType": "uint256",
-          "indexed": false
-        }
-      ],
-      "anonymous": false
-    },
-    {
-      "type": "function",
-      "name": "PENALTY_BASE",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint192",
-          "internalType": "uint192"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "REWARD_PER_TOKEN_MULTIPLIER",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint256",
-          "internalType": "uint256"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "adjudicator",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "address",
-          "internalType": "address"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "approveAuthorizationDecrease",
-      "stateMutability": "nonpayable",
-      "inputs": [
-        {
-          "name": "_stakingProvider",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": []
-    },
-    {
-      "type": "function",
-      "name": "authorizationDecreaseRequested",
-      "stateMutability": "nonpayable",
-      "inputs": [
-        {
-          "name": "_stakingProvider",
-          "type": "address",
-          "internalType": "address"
-        },
-        {
-          "name": "_fromAmount",
-          "type": "uint96",
-          "internalType": "uint96"
-        },
-        {
-          "name": "_toAmount",
-          "type": "uint96",
-          "internalType": "uint96"
-        }
-      ],
-      "outputs": []
-    },
-    {
-      "type": "function",
-      "name": "authorizationIncreased",
-      "stateMutability": "nonpayable",
-      "inputs": [
-        {
-          "name": "_stakingProvider",
-          "type": "address",
-          "internalType": "address"
-        },
-        {
-          "name": "_fromAmount",
-          "type": "uint96",
-          "internalType": "uint96"
-        },
-        {
-          "name": "_toAmount",
-          "type": "uint96",
-          "internalType": "uint96"
-        }
-      ],
-      "outputs": []
-    },
-    {
-      "type": "function",
-      "name": "authorizationParameters",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "_minimumAuthorization",
-          "type": "uint96",
-          "internalType": "uint96"
-        },
-        {
-          "name": "authorizationDecreaseDelay",
-          "type": "uint64",
-          "internalType": "uint64"
-        },
-        {
-          "name": "authorizationDecreaseChangePeriod",
-          "type": "uint64",
-          "internalType": "uint64"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "authorizedOverall",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint96",
-          "internalType": "uint96"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "authorizedStake",
-      "stateMutability": "view",
-      "inputs": [
-        {
-          "name": "_stakingProvider",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint96",
-          "internalType": "uint96"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "availableRewards",
-      "stateMutability": "view",
-      "inputs": [
-        {
-          "name": "_stakingProvider",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint96",
-          "internalType": "uint96"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "bondOperator",
-      "stateMutability": "nonpayable",
-      "inputs": [
-        {
-          "name": "_stakingProvider",
-          "type": "address",
-          "internalType": "address"
-        },
-        {
-          "name": "_operator",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": []
-    },
-    {
-      "type": "function",
-      "name": "childApplication",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "address",
-          "internalType": "contract ITACoRootToChild"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "commitmentDeadline",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint64",
-          "internalType": "uint64"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "commitmentDurationOption1",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint64",
-          "internalType": "uint64"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "commitmentDurationOption2",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint64",
-          "internalType": "uint64"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "commitmentDurationOption3",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint64",
-          "internalType": "uint64"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "commitmentDurationOption4",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint64",
-          "internalType": "uint64"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "confirmOperatorAddress",
-      "stateMutability": "nonpayable",
-      "inputs": [
-        {
-          "name": "_operator",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": []
-    },
-    {
-      "type": "function",
-      "name": "deauthorizationDuration",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint256",
-          "internalType": "uint256"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "eligibleStake",
-      "stateMutability": "view",
-      "inputs": [
-        {
-          "name": "_stakingProvider",
-          "type": "address",
-          "internalType": "address"
-        },
-        {
-          "name": "_endDate",
-          "type": "uint256",
-          "internalType": "uint256"
-        }
-      ],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint96",
-          "internalType": "uint96"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "getActiveStakingProviders",
-      "stateMutability": "view",
-      "inputs": [
-        {
-          "name": "_startIndex",
-          "type": "uint256",
-          "internalType": "uint256"
-        },
-        {
-          "name": "_maxStakingProviders",
-          "type": "uint256",
-          "internalType": "uint256"
-        },
-        {
-          "name": "_cohortDuration",
-          "type": "uint32",
-          "internalType": "uint32"
-        }
-      ],
-      "outputs": [
-        {
-          "name": "allAuthorizedTokens",
-          "type": "uint256",
-          "internalType": "uint256"
-        },
-        {
-          "name": "activeStakingProviders",
-          "type": "bytes32[]",
-          "internalType": "bytes32[]"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "getBeneficiary",
-      "stateMutability": "view",
-      "inputs": [
-        {
-          "name": "_stakingProvider",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": [
-        {
-          "name": "beneficiary",
-          "type": "address",
-          "internalType": "address payable"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "getPenalty",
-      "stateMutability": "view",
-      "inputs": [
-        {
-          "name": "_stakingProvider",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": [
-        {
-          "name": "penalty",
-          "type": "uint192",
-          "internalType": "uint192"
-        },
-        {
-          "name": "endPenalty",
-          "type": "uint64",
-          "internalType": "uint64"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "getStakingProvidersLength",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint256",
-          "internalType": "uint256"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "initialize",
-      "stateMutability": "nonpayable",
-      "inputs": [],
-      "outputs": []
-    },
-    {
-      "type": "function",
-      "name": "involuntaryAuthorizationDecrease",
-      "stateMutability": "nonpayable",
-      "inputs": [
-        {
-          "name": "_stakingProvider",
-          "type": "address",
-          "internalType": "address"
-        },
-        {
-          "name": "_fromAmount",
-          "type": "uint96",
-          "internalType": "uint96"
-        },
-        {
-          "name": "_toAmount",
-          "type": "uint96",
-          "internalType": "uint96"
-        }
-      ],
-      "outputs": []
-    },
-    {
-      "type": "function",
-      "name": "isAuthorized",
-      "stateMutability": "view",
-      "inputs": [
-        {
-          "name": "_stakingProvider",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": [
-        {
-          "name": "",
-          "type": "bool",
-          "internalType": "bool"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "isOperatorConfirmed",
-      "stateMutability": "view",
-      "inputs": [
-        {
-          "name": "_operator",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": [
-        {
-          "name": "",
-          "type": "bool",
-          "internalType": "bool"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "lastTimeRewardApplicable",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint256",
-          "internalType": "uint256"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "lastUpdateTime",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint256",
-          "internalType": "uint256"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "makeCommitment",
-      "stateMutability": "nonpayable",
-      "inputs": [
-        {
-          "name": "_stakingProvider",
-          "type": "address",
-          "internalType": "address"
-        },
-        {
-          "name": "_commitmentDuration",
-          "type": "uint64",
-          "internalType": "uint64"
-        }
-      ],
-      "outputs": []
-    },
-    {
-      "type": "function",
-      "name": "manualChildSynchronization",
-      "stateMutability": "nonpayable",
-      "inputs": [
-        {
-          "name": "_stakingProvider",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": []
-    },
-    {
-      "type": "function",
-      "name": "minOperatorSeconds",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint256",
-          "internalType": "uint256"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "minimumAuthorization",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint96",
-          "internalType": "uint96"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "operatorToStakingProvider",
-      "stateMutability": "view",
-      "inputs": [
-        {
-          "name": "_operator",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": [
-        {
-          "name": "",
-          "type": "address",
-          "internalType": "address"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "owner",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "address",
-          "internalType": "address"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "penalize",
-      "stateMutability": "nonpayable",
-      "inputs": [
-        {
-          "name": "_stakingProvider",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": []
-    },
-    {
-      "type": "function",
-      "name": "penaltyDefault",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint192",
-          "internalType": "uint192"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "penaltyDuration",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint256",
-          "internalType": "uint256"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "penaltyIncrement",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint192",
-          "internalType": "uint192"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "pendingAuthorizationDecrease",
-      "stateMutability": "view",
-      "inputs": [
-        {
-          "name": "_stakingProvider",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint96",
-          "internalType": "uint96"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "periodFinish",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint256",
-          "internalType": "uint256"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "pushReward",
-      "stateMutability": "nonpayable",
-      "inputs": [
-        {
-          "name": "_reward",
-          "type": "uint96",
-          "internalType": "uint96"
-        }
-      ],
-      "outputs": []
-    },
-    {
-      "type": "function",
-      "name": "registerOperator",
-      "stateMutability": "nonpayable",
-      "inputs": [
-        {
-          "name": "_operator",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": []
-    },
-    {
-      "type": "function",
-      "name": "remainingAuthorizationDecreaseDelay",
-      "stateMutability": "view",
-      "inputs": [
-        {
-          "name": "_stakingProvider",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint64",
-          "internalType": "uint64"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "renounceOwnership",
-      "stateMutability": "nonpayable",
-      "inputs": [],
-      "outputs": []
-    },
-    {
-      "type": "function",
-      "name": "resetReward",
-      "stateMutability": "nonpayable",
-      "inputs": [
-        {
-          "name": "_stakingProvider",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": []
-    },
-    {
-      "type": "function",
-      "name": "resynchronizeAuthorization",
-      "stateMutability": "nonpayable",
-      "inputs": [
-        {
-          "name": "_stakingProvider",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": []
-    },
-    {
-      "type": "function",
-      "name": "rewardContract",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "address",
-          "internalType": "address"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "rewardDistributor",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "address",
-          "internalType": "address"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "rewardDuration",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint256",
-          "internalType": "uint256"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "rewardPerToken",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint160",
-          "internalType": "uint160"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "rewardPerTokenStored",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint160",
-          "internalType": "uint160"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "rewardRateDecimals",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint256",
-          "internalType": "uint256"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "setAdjudicator",
-      "stateMutability": "nonpayable",
-      "inputs": [
-        {
-          "name": "_adjudicator",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": []
-    },
-    {
-      "type": "function",
-      "name": "setChildApplication",
-      "stateMutability": "nonpayable",
-      "inputs": [
-        {
-          "name": "_childApplication",
-          "type": "address",
-          "internalType": "contract ITACoRootToChild"
-        }
-      ],
-      "outputs": []
-    },
-    {
-      "type": "function",
-      "name": "setRewardContract",
-      "stateMutability": "nonpayable",
-      "inputs": [
-        {
-          "name": "_rewardContract",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": []
-    },
-    {
-      "type": "function",
-      "name": "setRewardDistributor",
-      "stateMutability": "nonpayable",
-      "inputs": [
-        {
-          "name": "_rewardDistributor",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": []
-    },
-    {
-      "type": "function",
-      "name": "slash",
-      "stateMutability": "nonpayable",
-      "inputs": [
-        {
-          "name": "_stakingProvider",
-          "type": "address",
-          "internalType": "address"
-        },
-        {
-          "name": "_penalty",
-          "type": "uint96",
-          "internalType": "uint96"
-        },
-        {
-          "name": "_investigator",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": []
-    },
-    {
-      "type": "function",
-      "name": "stakingProviderInfo",
-      "stateMutability": "view",
-      "inputs": [
-        {
-          "name": "",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": [
-        {
-          "name": "operator",
-          "type": "address",
-          "internalType": "address"
-        },
-        {
-          "name": "operatorConfirmed",
-          "type": "bool",
-          "internalType": "bool"
-        },
-        {
-          "name": "operatorStartTimestamp",
-          "type": "uint64",
-          "internalType": "uint64"
-        },
-        {
-          "name": "authorized",
-          "type": "uint96",
-          "internalType": "uint96"
-        },
-        {
-          "name": "deauthorizing",
-          "type": "uint96",
-          "internalType": "uint96"
-        },
-        {
-          "name": "endDeauthorization",
-          "type": "uint64",
-          "internalType": "uint64"
-        },
-        {
-          "name": "tReward",
-          "type": "uint96",
-          "internalType": "uint96"
-        },
-        {
-          "name": "rewardPerTokenPaid",
-          "type": "uint160",
-          "internalType": "uint160"
-        },
-        {
-          "name": "endCommitment",
-          "type": "uint64",
-          "internalType": "uint64"
-        },
-        {
-          "name": "stub",
-          "type": "uint256",
-          "internalType": "uint256"
-        },
-        {
-          "name": "penaltyPercent",
-          "type": "uint192",
-          "internalType": "uint192"
-        },
-        {
-          "name": "endPenalty",
-          "type": "uint64",
-          "internalType": "uint64"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "stakingProviderToOperator",
-      "stateMutability": "view",
-      "inputs": [
-        {
-          "name": "_stakingProvider",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": [
-        {
-          "name": "",
-          "type": "address",
-          "internalType": "address"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "stakingProviders",
-      "stateMutability": "view",
-      "inputs": [
-        {
-          "name": "",
-          "type": "uint256",
-          "internalType": "uint256"
-        }
-      ],
-      "outputs": [
-        {
-          "name": "",
-          "type": "address",
-          "internalType": "address"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "tStaking",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "address",
-          "internalType": "contract IStaking"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "token",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "address",
-          "internalType": "contract IERC20"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "transferOwnership",
-      "stateMutability": "nonpayable",
-      "inputs": [
-        {
-          "name": "newOwner",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": []
-    },
-    {
-      "type": "function",
-      "name": "withdrawRewards",
-      "stateMutability": "nonpayable",
-      "inputs": [
-        {
-          "name": "_stakingProvider",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": []
-    }
-  ],
-  "tx_hash": "0x178f50155caea7bb32dab5cd79280c66d19a52aa2d303174fa9f5d843ba2ea91",
-  "block_number": 20410589,
-  "deployer": "0xFfFd7092685bDeeBD121D1A0FEA3c349114Cce50"
-}
diff --git a/src/threshold-ts/utils/contract.ts b/src/threshold-ts/utils/contract.ts
index b5920cd9b..e01210cb4 100644
--- a/src/threshold-ts/utils/contract.ts
+++ b/src/threshold-ts/utils/contract.ts
@@ -23,7 +23,7 @@ import WalletRegistryArtifactMainnet from "@keep-network/tbtc-v2.ts/src/lib/ethe
 import StakingArtifactMainnet from "../staking/mainnet-artifacts/TokenStaking.json"
 import RandomBeaconArtifactMainnet from "../tbtc/mainnet-artifacts/RandomBeacon.json"
 import LegacyKeepStakingArtifactMainnet from "../staking/mainnet-artifacts/LegacyKeepStaking.json"
-import TacoRegistryArtifactMainnet from "../mas/mainnet-artifacts/TacoRegistry.json"
+import TacoRegistryArtifactMainnet from "@nucypher/nucypher-contracts/deployment/artifacts/mainnet.json"
 
 import ArbitrumL1BitcoinDepositorArtifactSepolia from "../tbtc/sepolia-artifacts/ArbitrumL1BitcoinDepositor.json"
 import BaseL1BitcoinDepositorArtifactSepolia from "../tbtc/sepolia-artifacts/BaseL1BitcoinDepositor.json"
@@ -82,7 +82,8 @@ type ContractArtifacts = {
 const contractArtifacts: ContractArtifacts = {
   [SupportedChainIds.Ethereum]: {
     ArbitrumL1BitcoinDepositor: ArbitrumL1BitcoinDepositorArtifactMainnet,
-    TacoRegistry: TacoRegistryArtifactMainnet,
+    TacoRegistry:
+      TacoRegistryArtifactMainnet[SupportedChainIds.Ethereum].TACoApplication,
     LegacyKeepStaking: LegacyKeepStakingArtifactMainnet,
     RandomBeacon: RandomBeaconArtifactMainnet,
     TokenStaking: StakingArtifactMainnet,

From 97ec4dc8e6092bb533227296d3b5f47ea60a0cc9 Mon Sep 17 00:00:00 2001
From: evandrosaturnino <evandro.saturnino@gmail.com>
Date: Mon, 6 Jan 2025 19:01:34 -0300
Subject: [PATCH 34/46] update testnet taco registry artifacts import

---
 .../TacoRegistry.json                         | 1352 ----------------
 .../mas/sepolia-artifacts/TacoRegistry.json   | 1431 -----------------
 src/threshold-ts/utils/contract.ts            |    4 +-
 3 files changed, 2 insertions(+), 2785 deletions(-)
 delete mode 100644 src/threshold-ts/mas/dapp-development-sepolia-artifacts/TacoRegistry.json
 delete mode 100644 src/threshold-ts/mas/sepolia-artifacts/TacoRegistry.json

diff --git a/src/threshold-ts/mas/dapp-development-sepolia-artifacts/TacoRegistry.json b/src/threshold-ts/mas/dapp-development-sepolia-artifacts/TacoRegistry.json
deleted file mode 100644
index 1e5bcbf03..000000000
--- a/src/threshold-ts/mas/dapp-development-sepolia-artifacts/TacoRegistry.json
+++ /dev/null
@@ -1,1352 +0,0 @@
-{
-  "address": "0xE9Eb81F72cDBE9fE82f61EA527e8a3A39f5B023a",
-  "abi": [
-    {
-      "type": "constructor",
-      "stateMutability": "nonpayable",
-      "inputs": [
-        {
-          "name": "_token",
-          "type": "address",
-          "internalType": "contract IERC20"
-        },
-        {
-          "name": "_tStaking",
-          "type": "address",
-          "internalType": "contract IStaking"
-        },
-        {
-          "name": "_minimumAuthorization",
-          "type": "uint96",
-          "internalType": "uint96"
-        },
-        {
-          "name": "_minOperatorSeconds",
-          "type": "uint256",
-          "internalType": "uint256"
-        },
-        {
-          "name": "_rewardDuration",
-          "type": "uint256",
-          "internalType": "uint256"
-        },
-        {
-          "name": "_deauthorizationDuration",
-          "type": "uint256",
-          "internalType": "uint256"
-        },
-        {
-          "name": "_commitmentDurationOptions",
-          "type": "uint64[]",
-          "internalType": "uint64[]"
-        },
-        {
-          "name": "_commitmentDeadline",
-          "type": "uint64",
-          "internalType": "uint64"
-        }
-      ]
-    },
-    {
-      "type": "error",
-      "name": "AddressEmptyCode",
-      "inputs": [
-        {
-          "name": "target",
-          "type": "address",
-          "internalType": "address"
-        }
-      ]
-    },
-    {
-      "type": "error",
-      "name": "AddressInsufficientBalance",
-      "inputs": [
-        {
-          "name": "account",
-          "type": "address",
-          "internalType": "address"
-        }
-      ]
-    },
-    {
-      "type": "error",
-      "name": "FailedInnerCall",
-      "inputs": []
-    },
-    {
-      "type": "error",
-      "name": "InvalidInitialization",
-      "inputs": []
-    },
-    {
-      "type": "error",
-      "name": "NotInitializing",
-      "inputs": []
-    },
-    {
-      "type": "error",
-      "name": "OwnableInvalidOwner",
-      "inputs": [
-        {
-          "name": "owner",
-          "type": "address",
-          "internalType": "address"
-        }
-      ]
-    },
-    {
-      "type": "error",
-      "name": "OwnableUnauthorizedAccount",
-      "inputs": [
-        {
-          "name": "account",
-          "type": "address",
-          "internalType": "address"
-        }
-      ]
-    },
-    {
-      "type": "error",
-      "name": "SafeCastOverflowedUintDowncast",
-      "inputs": [
-        {
-          "name": "bits",
-          "type": "uint8",
-          "internalType": "uint8"
-        },
-        {
-          "name": "value",
-          "type": "uint256",
-          "internalType": "uint256"
-        }
-      ]
-    },
-    {
-      "type": "error",
-      "name": "SafeERC20FailedOperation",
-      "inputs": [
-        {
-          "name": "token",
-          "type": "address",
-          "internalType": "address"
-        }
-      ]
-    },
-    {
-      "type": "event",
-      "name": "AuthorizationDecreaseApproved",
-      "inputs": [
-        {
-          "name": "stakingProvider",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        },
-        {
-          "name": "fromAmount",
-          "type": "uint96",
-          "internalType": "uint96",
-          "indexed": false
-        },
-        {
-          "name": "toAmount",
-          "type": "uint96",
-          "internalType": "uint96",
-          "indexed": false
-        }
-      ],
-      "anonymous": false
-    },
-    {
-      "type": "event",
-      "name": "AuthorizationDecreaseRequested",
-      "inputs": [
-        {
-          "name": "stakingProvider",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        },
-        {
-          "name": "fromAmount",
-          "type": "uint96",
-          "internalType": "uint96",
-          "indexed": false
-        },
-        {
-          "name": "toAmount",
-          "type": "uint96",
-          "internalType": "uint96",
-          "indexed": false
-        }
-      ],
-      "anonymous": false
-    },
-    {
-      "type": "event",
-      "name": "AuthorizationIncreased",
-      "inputs": [
-        {
-          "name": "stakingProvider",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        },
-        {
-          "name": "fromAmount",
-          "type": "uint96",
-          "internalType": "uint96",
-          "indexed": false
-        },
-        {
-          "name": "toAmount",
-          "type": "uint96",
-          "internalType": "uint96",
-          "indexed": false
-        }
-      ],
-      "anonymous": false
-    },
-    {
-      "type": "event",
-      "name": "AuthorizationInvoluntaryDecreased",
-      "inputs": [
-        {
-          "name": "stakingProvider",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        },
-        {
-          "name": "fromAmount",
-          "type": "uint96",
-          "internalType": "uint96",
-          "indexed": false
-        },
-        {
-          "name": "toAmount",
-          "type": "uint96",
-          "internalType": "uint96",
-          "indexed": false
-        }
-      ],
-      "anonymous": false
-    },
-    {
-      "type": "event",
-      "name": "AuthorizationReSynchronized",
-      "inputs": [
-        {
-          "name": "stakingProvider",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        },
-        {
-          "name": "fromAmount",
-          "type": "uint96",
-          "internalType": "uint96",
-          "indexed": false
-        },
-        {
-          "name": "toAmount",
-          "type": "uint96",
-          "internalType": "uint96",
-          "indexed": false
-        }
-      ],
-      "anonymous": false
-    },
-    {
-      "type": "event",
-      "name": "CommitmentMade",
-      "inputs": [
-        {
-          "name": "stakingProvider",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        },
-        {
-          "name": "endCommitment",
-          "type": "uint256",
-          "internalType": "uint256",
-          "indexed": false
-        }
-      ],
-      "anonymous": false
-    },
-    {
-      "type": "event",
-      "name": "Initialized",
-      "inputs": [
-        {
-          "name": "version",
-          "type": "uint64",
-          "internalType": "uint64",
-          "indexed": false
-        }
-      ],
-      "anonymous": false
-    },
-    {
-      "type": "event",
-      "name": "OperatorBonded",
-      "inputs": [
-        {
-          "name": "stakingProvider",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        },
-        {
-          "name": "operator",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        },
-        {
-          "name": "previousOperator",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        },
-        {
-          "name": "startTimestamp",
-          "type": "uint256",
-          "internalType": "uint256",
-          "indexed": false
-        }
-      ],
-      "anonymous": false
-    },
-    {
-      "type": "event",
-      "name": "OperatorConfirmed",
-      "inputs": [
-        {
-          "name": "stakingProvider",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        },
-        {
-          "name": "operator",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        }
-      ],
-      "anonymous": false
-    },
-    {
-      "type": "event",
-      "name": "OwnershipTransferred",
-      "inputs": [
-        {
-          "name": "previousOwner",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        },
-        {
-          "name": "newOwner",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        }
-      ],
-      "anonymous": false
-    },
-    {
-      "type": "event",
-      "name": "RewardAdded",
-      "inputs": [
-        {
-          "name": "reward",
-          "type": "uint256",
-          "internalType": "uint256",
-          "indexed": false
-        }
-      ],
-      "anonymous": false
-    },
-    {
-      "type": "event",
-      "name": "RewardDistributorSet",
-      "inputs": [
-        {
-          "name": "distributor",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        }
-      ],
-      "anonymous": false
-    },
-    {
-      "type": "event",
-      "name": "RewardPaid",
-      "inputs": [
-        {
-          "name": "stakingProvider",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        },
-        {
-          "name": "beneficiary",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        },
-        {
-          "name": "reward",
-          "type": "uint256",
-          "internalType": "uint256",
-          "indexed": false
-        }
-      ],
-      "anonymous": false
-    },
-    {
-      "type": "event",
-      "name": "RewardsWithdrawn",
-      "inputs": [
-        {
-          "name": "stakingProvider",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        },
-        {
-          "name": "amount",
-          "type": "uint96",
-          "internalType": "uint96",
-          "indexed": false
-        }
-      ],
-      "anonymous": false
-    },
-    {
-      "type": "event",
-      "name": "Slashed",
-      "inputs": [
-        {
-          "name": "stakingProvider",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        },
-        {
-          "name": "penalty",
-          "type": "uint256",
-          "internalType": "uint256",
-          "indexed": false
-        },
-        {
-          "name": "investigator",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        },
-        {
-          "name": "reward",
-          "type": "uint256",
-          "internalType": "uint256",
-          "indexed": false
-        }
-      ],
-      "anonymous": false
-    },
-    {
-      "type": "function",
-      "name": "REWARD_PER_TOKEN_MULTIPLIER",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint256",
-          "internalType": "uint256"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "adjudicator",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "address",
-          "internalType": "address"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "approveAuthorizationDecrease",
-      "stateMutability": "nonpayable",
-      "inputs": [
-        {
-          "name": "_stakingProvider",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": []
-    },
-    {
-      "type": "function",
-      "name": "authorizationDecreaseRequested",
-      "stateMutability": "nonpayable",
-      "inputs": [
-        {
-          "name": "_stakingProvider",
-          "type": "address",
-          "internalType": "address"
-        },
-        {
-          "name": "_fromAmount",
-          "type": "uint96",
-          "internalType": "uint96"
-        },
-        {
-          "name": "_toAmount",
-          "type": "uint96",
-          "internalType": "uint96"
-        }
-      ],
-      "outputs": []
-    },
-    {
-      "type": "function",
-      "name": "authorizationIncreased",
-      "stateMutability": "nonpayable",
-      "inputs": [
-        {
-          "name": "_stakingProvider",
-          "type": "address",
-          "internalType": "address"
-        },
-        {
-          "name": "_fromAmount",
-          "type": "uint96",
-          "internalType": "uint96"
-        },
-        {
-          "name": "_toAmount",
-          "type": "uint96",
-          "internalType": "uint96"
-        }
-      ],
-      "outputs": []
-    },
-    {
-      "type": "function",
-      "name": "authorizationParameters",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "_minimumAuthorization",
-          "type": "uint96",
-          "internalType": "uint96"
-        },
-        {
-          "name": "authorizationDecreaseDelay",
-          "type": "uint64",
-          "internalType": "uint64"
-        },
-        {
-          "name": "authorizationDecreaseChangePeriod",
-          "type": "uint64",
-          "internalType": "uint64"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "authorizedOverall",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint96",
-          "internalType": "uint96"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "authorizedStake",
-      "stateMutability": "view",
-      "inputs": [
-        {
-          "name": "_stakingProvider",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint96",
-          "internalType": "uint96"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "availableRewards",
-      "stateMutability": "view",
-      "inputs": [
-        {
-          "name": "_stakingProvider",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint96",
-          "internalType": "uint96"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "bondOperator",
-      "stateMutability": "nonpayable",
-      "inputs": [
-        {
-          "name": "_stakingProvider",
-          "type": "address",
-          "internalType": "address"
-        },
-        {
-          "name": "_operator",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": []
-    },
-    {
-      "type": "function",
-      "name": "childApplication",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "address",
-          "internalType": "contract ITACoRootToChild"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "commitmentDeadline",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint64",
-          "internalType": "uint64"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "commitmentDurationOption1",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint64",
-          "internalType": "uint64"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "commitmentDurationOption2",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint64",
-          "internalType": "uint64"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "commitmentDurationOption3",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint64",
-          "internalType": "uint64"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "commitmentDurationOption4",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint64",
-          "internalType": "uint64"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "confirmOperatorAddress",
-      "stateMutability": "nonpayable",
-      "inputs": [
-        {
-          "name": "_operator",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": []
-    },
-    {
-      "type": "function",
-      "name": "deauthorizationDuration",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint256",
-          "internalType": "uint256"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "getActiveStakingProviders",
-      "stateMutability": "view",
-      "inputs": [
-        {
-          "name": "_startIndex",
-          "type": "uint256",
-          "internalType": "uint256"
-        },
-        {
-          "name": "_maxStakingProviders",
-          "type": "uint256",
-          "internalType": "uint256"
-        }
-      ],
-      "outputs": [
-        {
-          "name": "allAuthorizedTokens",
-          "type": "uint256",
-          "internalType": "uint256"
-        },
-        {
-          "name": "activeStakingProviders",
-          "type": "bytes32[]",
-          "internalType": "bytes32[]"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "getBeneficiary",
-      "stateMutability": "view",
-      "inputs": [
-        {
-          "name": "_stakingProvider",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": [
-        {
-          "name": "beneficiary",
-          "type": "address",
-          "internalType": "address payable"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "getStakingProvidersLength",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint256",
-          "internalType": "uint256"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "initialize",
-      "stateMutability": "nonpayable",
-      "inputs": [],
-      "outputs": []
-    },
-    {
-      "type": "function",
-      "name": "involuntaryAuthorizationDecrease",
-      "stateMutability": "nonpayable",
-      "inputs": [
-        {
-          "name": "_stakingProvider",
-          "type": "address",
-          "internalType": "address"
-        },
-        {
-          "name": "_fromAmount",
-          "type": "uint96",
-          "internalType": "uint96"
-        },
-        {
-          "name": "_toAmount",
-          "type": "uint96",
-          "internalType": "uint96"
-        }
-      ],
-      "outputs": []
-    },
-    {
-      "type": "function",
-      "name": "isAuthorized",
-      "stateMutability": "view",
-      "inputs": [
-        {
-          "name": "_stakingProvider",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": [
-        {
-          "name": "",
-          "type": "bool",
-          "internalType": "bool"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "isOperatorConfirmed",
-      "stateMutability": "view",
-      "inputs": [
-        {
-          "name": "_operator",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": [
-        {
-          "name": "",
-          "type": "bool",
-          "internalType": "bool"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "lastTimeRewardApplicable",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint256",
-          "internalType": "uint256"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "lastUpdateTime",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint256",
-          "internalType": "uint256"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "makeCommitment",
-      "stateMutability": "nonpayable",
-      "inputs": [
-        {
-          "name": "_stakingProvider",
-          "type": "address",
-          "internalType": "address"
-        },
-        {
-          "name": "_commitmentDuration",
-          "type": "uint64",
-          "internalType": "uint64"
-        }
-      ],
-      "outputs": []
-    },
-    {
-      "type": "function",
-      "name": "minOperatorSeconds",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint256",
-          "internalType": "uint256"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "minimumAuthorization",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint96",
-          "internalType": "uint96"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "operatorToStakingProvider",
-      "stateMutability": "view",
-      "inputs": [
-        {
-          "name": "_operator",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": [
-        {
-          "name": "",
-          "type": "address",
-          "internalType": "address"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "owner",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "address",
-          "internalType": "address"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "pendingAuthorizationDecrease",
-      "stateMutability": "view",
-      "inputs": [
-        {
-          "name": "_stakingProvider",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint96",
-          "internalType": "uint96"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "periodFinish",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint256",
-          "internalType": "uint256"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "pushReward",
-      "stateMutability": "nonpayable",
-      "inputs": [
-        {
-          "name": "_reward",
-          "type": "uint96",
-          "internalType": "uint96"
-        }
-      ],
-      "outputs": []
-    },
-    {
-      "type": "function",
-      "name": "registerOperator",
-      "stateMutability": "nonpayable",
-      "inputs": [
-        {
-          "name": "_operator",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": []
-    },
-    {
-      "type": "function",
-      "name": "remainingAuthorizationDecreaseDelay",
-      "stateMutability": "view",
-      "inputs": [
-        {
-          "name": "_stakingProvider",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint64",
-          "internalType": "uint64"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "renounceOwnership",
-      "stateMutability": "nonpayable",
-      "inputs": [],
-      "outputs": []
-    },
-    {
-      "type": "function",
-      "name": "resynchronizeAuthorization",
-      "stateMutability": "nonpayable",
-      "inputs": [
-        {
-          "name": "_stakingProvider",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": []
-    },
-    {
-      "type": "function",
-      "name": "rewardDistributor",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "address",
-          "internalType": "address"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "rewardDuration",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint256",
-          "internalType": "uint256"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "rewardPerToken",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint160",
-          "internalType": "uint160"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "rewardPerTokenStored",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint160",
-          "internalType": "uint160"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "rewardRateDecimals",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint256",
-          "internalType": "uint256"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "setAdjudicator",
-      "stateMutability": "nonpayable",
-      "inputs": [
-        {
-          "name": "_adjudicator",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": []
-    },
-    {
-      "type": "function",
-      "name": "setChildApplication",
-      "stateMutability": "nonpayable",
-      "inputs": [
-        {
-          "name": "_childApplication",
-          "type": "address",
-          "internalType": "contract ITACoRootToChild"
-        }
-      ],
-      "outputs": []
-    },
-    {
-      "type": "function",
-      "name": "setRewardDistributor",
-      "stateMutability": "nonpayable",
-      "inputs": [
-        {
-          "name": "_rewardDistributor",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": []
-    },
-    {
-      "type": "function",
-      "name": "slash",
-      "stateMutability": "nonpayable",
-      "inputs": [
-        {
-          "name": "_stakingProvider",
-          "type": "address",
-          "internalType": "address"
-        },
-        {
-          "name": "_penalty",
-          "type": "uint96",
-          "internalType": "uint96"
-        },
-        {
-          "name": "_investigator",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": []
-    },
-    {
-      "type": "function",
-      "name": "stakingProviderInfo",
-      "stateMutability": "view",
-      "inputs": [
-        {
-          "name": "",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": [
-        {
-          "name": "operator",
-          "type": "address",
-          "internalType": "address"
-        },
-        {
-          "name": "operatorConfirmed",
-          "type": "bool",
-          "internalType": "bool"
-        },
-        {
-          "name": "operatorStartTimestamp",
-          "type": "uint64",
-          "internalType": "uint64"
-        },
-        {
-          "name": "authorized",
-          "type": "uint96",
-          "internalType": "uint96"
-        },
-        {
-          "name": "deauthorizing",
-          "type": "uint96",
-          "internalType": "uint96"
-        },
-        {
-          "name": "endDeauthorization",
-          "type": "uint64",
-          "internalType": "uint64"
-        },
-        {
-          "name": "tReward",
-          "type": "uint96",
-          "internalType": "uint96"
-        },
-        {
-          "name": "rewardPerTokenPaid",
-          "type": "uint160",
-          "internalType": "uint160"
-        },
-        {
-          "name": "endCommitment",
-          "type": "uint64",
-          "internalType": "uint64"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "stakingProviderToOperator",
-      "stateMutability": "view",
-      "inputs": [
-        {
-          "name": "_stakingProvider",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": [
-        {
-          "name": "",
-          "type": "address",
-          "internalType": "address"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "stakingProviders",
-      "stateMutability": "view",
-      "inputs": [
-        {
-          "name": "",
-          "type": "uint256",
-          "internalType": "uint256"
-        }
-      ],
-      "outputs": [
-        {
-          "name": "",
-          "type": "address",
-          "internalType": "address"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "tStaking",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "address",
-          "internalType": "contract IStaking"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "token",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "address",
-          "internalType": "contract IERC20"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "transferOwnership",
-      "stateMutability": "nonpayable",
-      "inputs": [
-        {
-          "name": "newOwner",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": []
-    },
-    {
-      "type": "function",
-      "name": "withdrawRewards",
-      "stateMutability": "nonpayable",
-      "inputs": [
-        {
-          "name": "_stakingProvider",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": []
-    }
-  ],
-  "tx_hash": "0xb9cd5deb857d4e74e45bcd9dd435f3fccf08cdb8c91ac0ca9da36c47210eb149",
-  "block_number": 4776043,
-  "deployer": "0x24dbb0BEE134C3773D2C1791d65d99e307Fe86CF"
-}
diff --git a/src/threshold-ts/mas/sepolia-artifacts/TacoRegistry.json b/src/threshold-ts/mas/sepolia-artifacts/TacoRegistry.json
deleted file mode 100644
index 968c9536e..000000000
--- a/src/threshold-ts/mas/sepolia-artifacts/TacoRegistry.json
+++ /dev/null
@@ -1,1431 +0,0 @@
-{
-  "address": "0xCcFf527698E78a536d80695D9Af4F4f3265ADA05",
-  "abi": [
-    {
-      "type": "constructor",
-      "stateMutability": "nonpayable",
-      "inputs": [
-        {
-          "name": "_token",
-          "type": "address",
-          "internalType": "contract IERC20"
-        },
-        {
-          "name": "_tStaking",
-          "type": "address",
-          "internalType": "contract IStaking"
-        },
-        {
-          "name": "_minimumAuthorization",
-          "type": "uint96",
-          "internalType": "uint96"
-        },
-        {
-          "name": "_minOperatorSeconds",
-          "type": "uint256",
-          "internalType": "uint256"
-        },
-        {
-          "name": "_rewardDuration",
-          "type": "uint256",
-          "internalType": "uint256"
-        },
-        {
-          "name": "_deauthorizationDuration",
-          "type": "uint256",
-          "internalType": "uint256"
-        },
-        {
-          "name": "_commitmentDurationOptions",
-          "type": "uint64[]",
-          "internalType": "uint64[]"
-        },
-        {
-          "name": "_commitmentDeadline",
-          "type": "uint64",
-          "internalType": "uint64"
-        }
-      ]
-    },
-    {
-      "type": "error",
-      "name": "AddressEmptyCode",
-      "inputs": [
-        {
-          "name": "target",
-          "type": "address",
-          "internalType": "address"
-        }
-      ]
-    },
-    {
-      "type": "error",
-      "name": "AddressInsufficientBalance",
-      "inputs": [
-        {
-          "name": "account",
-          "type": "address",
-          "internalType": "address"
-        }
-      ]
-    },
-    {
-      "type": "error",
-      "name": "FailedInnerCall",
-      "inputs": []
-    },
-    {
-      "type": "error",
-      "name": "InvalidInitialization",
-      "inputs": []
-    },
-    {
-      "type": "error",
-      "name": "NotInitializing",
-      "inputs": []
-    },
-    {
-      "type": "error",
-      "name": "OwnableInvalidOwner",
-      "inputs": [
-        {
-          "name": "owner",
-          "type": "address",
-          "internalType": "address"
-        }
-      ]
-    },
-    {
-      "type": "error",
-      "name": "OwnableUnauthorizedAccount",
-      "inputs": [
-        {
-          "name": "account",
-          "type": "address",
-          "internalType": "address"
-        }
-      ]
-    },
-    {
-      "type": "error",
-      "name": "SafeCastOverflowedUintDowncast",
-      "inputs": [
-        {
-          "name": "bits",
-          "type": "uint8",
-          "internalType": "uint8"
-        },
-        {
-          "name": "value",
-          "type": "uint256",
-          "internalType": "uint256"
-        }
-      ]
-    },
-    {
-      "type": "error",
-      "name": "SafeERC20FailedOperation",
-      "inputs": [
-        {
-          "name": "token",
-          "type": "address",
-          "internalType": "address"
-        }
-      ]
-    },
-    {
-      "type": "event",
-      "name": "AuthorizationDecreaseApproved",
-      "inputs": [
-        {
-          "name": "stakingProvider",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        },
-        {
-          "name": "fromAmount",
-          "type": "uint96",
-          "internalType": "uint96",
-          "indexed": false
-        },
-        {
-          "name": "toAmount",
-          "type": "uint96",
-          "internalType": "uint96",
-          "indexed": false
-        }
-      ],
-      "anonymous": false
-    },
-    {
-      "type": "event",
-      "name": "AuthorizationDecreaseRequested",
-      "inputs": [
-        {
-          "name": "stakingProvider",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        },
-        {
-          "name": "fromAmount",
-          "type": "uint96",
-          "internalType": "uint96",
-          "indexed": false
-        },
-        {
-          "name": "toAmount",
-          "type": "uint96",
-          "internalType": "uint96",
-          "indexed": false
-        }
-      ],
-      "anonymous": false
-    },
-    {
-      "type": "event",
-      "name": "AuthorizationIncreased",
-      "inputs": [
-        {
-          "name": "stakingProvider",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        },
-        {
-          "name": "fromAmount",
-          "type": "uint96",
-          "internalType": "uint96",
-          "indexed": false
-        },
-        {
-          "name": "toAmount",
-          "type": "uint96",
-          "internalType": "uint96",
-          "indexed": false
-        }
-      ],
-      "anonymous": false
-    },
-    {
-      "type": "event",
-      "name": "AuthorizationInvoluntaryDecreased",
-      "inputs": [
-        {
-          "name": "stakingProvider",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        },
-        {
-          "name": "fromAmount",
-          "type": "uint96",
-          "internalType": "uint96",
-          "indexed": false
-        },
-        {
-          "name": "toAmount",
-          "type": "uint96",
-          "internalType": "uint96",
-          "indexed": false
-        }
-      ],
-      "anonymous": false
-    },
-    {
-      "type": "event",
-      "name": "AuthorizationReSynchronized",
-      "inputs": [
-        {
-          "name": "stakingProvider",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        },
-        {
-          "name": "fromAmount",
-          "type": "uint96",
-          "internalType": "uint96",
-          "indexed": false
-        },
-        {
-          "name": "toAmount",
-          "type": "uint96",
-          "internalType": "uint96",
-          "indexed": false
-        }
-      ],
-      "anonymous": false
-    },
-    {
-      "type": "event",
-      "name": "CommitmentMade",
-      "inputs": [
-        {
-          "name": "stakingProvider",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        },
-        {
-          "name": "endCommitment",
-          "type": "uint256",
-          "internalType": "uint256",
-          "indexed": false
-        }
-      ],
-      "anonymous": false
-    },
-    {
-      "type": "event",
-      "name": "Initialized",
-      "inputs": [
-        {
-          "name": "version",
-          "type": "uint64",
-          "internalType": "uint64",
-          "indexed": false
-        }
-      ],
-      "anonymous": false
-    },
-    {
-      "type": "event",
-      "name": "ManualChildSynchronizationSent",
-      "inputs": [
-        {
-          "name": "stakingProvider",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        },
-        {
-          "name": "authorized",
-          "type": "uint96",
-          "internalType": "uint96",
-          "indexed": false
-        },
-        {
-          "name": "deauthorizing",
-          "type": "uint96",
-          "internalType": "uint96",
-          "indexed": false
-        },
-        {
-          "name": "endDeauthorization",
-          "type": "uint64",
-          "internalType": "uint64",
-          "indexed": false
-        },
-        {
-          "name": "operator",
-          "type": "address",
-          "internalType": "address",
-          "indexed": false
-        }
-      ],
-      "anonymous": false
-    },
-    {
-      "type": "event",
-      "name": "OperatorBonded",
-      "inputs": [
-        {
-          "name": "stakingProvider",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        },
-        {
-          "name": "operator",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        },
-        {
-          "name": "previousOperator",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        },
-        {
-          "name": "startTimestamp",
-          "type": "uint256",
-          "internalType": "uint256",
-          "indexed": false
-        }
-      ],
-      "anonymous": false
-    },
-    {
-      "type": "event",
-      "name": "OperatorConfirmed",
-      "inputs": [
-        {
-          "name": "stakingProvider",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        },
-        {
-          "name": "operator",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        }
-      ],
-      "anonymous": false
-    },
-    {
-      "type": "event",
-      "name": "OwnershipTransferred",
-      "inputs": [
-        {
-          "name": "previousOwner",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        },
-        {
-          "name": "newOwner",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        }
-      ],
-      "anonymous": false
-    },
-    {
-      "type": "event",
-      "name": "RewardAdded",
-      "inputs": [
-        {
-          "name": "reward",
-          "type": "uint256",
-          "internalType": "uint256",
-          "indexed": false
-        }
-      ],
-      "anonymous": false
-    },
-    {
-      "type": "event",
-      "name": "RewardDistributorSet",
-      "inputs": [
-        {
-          "name": "distributor",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        }
-      ],
-      "anonymous": false
-    },
-    {
-      "type": "event",
-      "name": "RewardPaid",
-      "inputs": [
-        {
-          "name": "stakingProvider",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        },
-        {
-          "name": "beneficiary",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        },
-        {
-          "name": "reward",
-          "type": "uint256",
-          "internalType": "uint256",
-          "indexed": false
-        }
-      ],
-      "anonymous": false
-    },
-    {
-      "type": "event",
-      "name": "RewardsWithdrawn",
-      "inputs": [
-        {
-          "name": "stakingProvider",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        },
-        {
-          "name": "amount",
-          "type": "uint96",
-          "internalType": "uint96",
-          "indexed": false
-        }
-      ],
-      "anonymous": false
-    },
-    {
-      "type": "event",
-      "name": "Slashed",
-      "inputs": [
-        {
-          "name": "stakingProvider",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        },
-        {
-          "name": "penalty",
-          "type": "uint256",
-          "internalType": "uint256",
-          "indexed": false
-        },
-        {
-          "name": "investigator",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        },
-        {
-          "name": "reward",
-          "type": "uint256",
-          "internalType": "uint256",
-          "indexed": false
-        }
-      ],
-      "anonymous": false
-    },
-    {
-      "type": "function",
-      "name": "REWARD_PER_TOKEN_MULTIPLIER",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint256",
-          "internalType": "uint256"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "adjudicator",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "address",
-          "internalType": "address"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "approveAuthorizationDecrease",
-      "stateMutability": "nonpayable",
-      "inputs": [
-        {
-          "name": "_stakingProvider",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": []
-    },
-    {
-      "type": "function",
-      "name": "authorizationDecreaseRequested",
-      "stateMutability": "nonpayable",
-      "inputs": [
-        {
-          "name": "_stakingProvider",
-          "type": "address",
-          "internalType": "address"
-        },
-        {
-          "name": "_fromAmount",
-          "type": "uint96",
-          "internalType": "uint96"
-        },
-        {
-          "name": "_toAmount",
-          "type": "uint96",
-          "internalType": "uint96"
-        }
-      ],
-      "outputs": []
-    },
-    {
-      "type": "function",
-      "name": "authorizationIncreased",
-      "stateMutability": "nonpayable",
-      "inputs": [
-        {
-          "name": "_stakingProvider",
-          "type": "address",
-          "internalType": "address"
-        },
-        {
-          "name": "_fromAmount",
-          "type": "uint96",
-          "internalType": "uint96"
-        },
-        {
-          "name": "_toAmount",
-          "type": "uint96",
-          "internalType": "uint96"
-        }
-      ],
-      "outputs": []
-    },
-    {
-      "type": "function",
-      "name": "authorizationParameters",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "_minimumAuthorization",
-          "type": "uint96",
-          "internalType": "uint96"
-        },
-        {
-          "name": "authorizationDecreaseDelay",
-          "type": "uint64",
-          "internalType": "uint64"
-        },
-        {
-          "name": "authorizationDecreaseChangePeriod",
-          "type": "uint64",
-          "internalType": "uint64"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "authorizedOverall",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint96",
-          "internalType": "uint96"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "authorizedStake",
-      "stateMutability": "view",
-      "inputs": [
-        {
-          "name": "_stakingProvider",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint96",
-          "internalType": "uint96"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "availableRewards",
-      "stateMutability": "view",
-      "inputs": [
-        {
-          "name": "_stakingProvider",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint96",
-          "internalType": "uint96"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "bondOperator",
-      "stateMutability": "nonpayable",
-      "inputs": [
-        {
-          "name": "_stakingProvider",
-          "type": "address",
-          "internalType": "address"
-        },
-        {
-          "name": "_operator",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": []
-    },
-    {
-      "type": "function",
-      "name": "childApplication",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "address",
-          "internalType": "contract ITACoRootToChild"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "commitmentDeadline",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint64",
-          "internalType": "uint64"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "commitmentDurationOption1",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint64",
-          "internalType": "uint64"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "commitmentDurationOption2",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint64",
-          "internalType": "uint64"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "commitmentDurationOption3",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint64",
-          "internalType": "uint64"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "commitmentDurationOption4",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint64",
-          "internalType": "uint64"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "confirmOperatorAddress",
-      "stateMutability": "nonpayable",
-      "inputs": [
-        {
-          "name": "_operator",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": []
-    },
-    {
-      "type": "function",
-      "name": "deauthorizationDuration",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint256",
-          "internalType": "uint256"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "eligibleStake",
-      "stateMutability": "view",
-      "inputs": [
-        {
-          "name": "_stakingProvider",
-          "type": "address",
-          "internalType": "address"
-        },
-        {
-          "name": "_endDate",
-          "type": "uint256",
-          "internalType": "uint256"
-        }
-      ],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint96",
-          "internalType": "uint96"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "getActiveStakingProviders",
-      "stateMutability": "view",
-      "inputs": [
-        {
-          "name": "_startIndex",
-          "type": "uint256",
-          "internalType": "uint256"
-        },
-        {
-          "name": "_maxStakingProviders",
-          "type": "uint256",
-          "internalType": "uint256"
-        },
-        {
-          "name": "_cohortDuration",
-          "type": "uint32",
-          "internalType": "uint32"
-        }
-      ],
-      "outputs": [
-        {
-          "name": "allAuthorizedTokens",
-          "type": "uint256",
-          "internalType": "uint256"
-        },
-        {
-          "name": "activeStakingProviders",
-          "type": "bytes32[]",
-          "internalType": "bytes32[]"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "getBeneficiary",
-      "stateMutability": "view",
-      "inputs": [
-        {
-          "name": "_stakingProvider",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": [
-        {
-          "name": "beneficiary",
-          "type": "address",
-          "internalType": "address payable"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "getStakingProvidersLength",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint256",
-          "internalType": "uint256"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "initialize",
-      "stateMutability": "nonpayable",
-      "inputs": [],
-      "outputs": []
-    },
-    {
-      "type": "function",
-      "name": "involuntaryAuthorizationDecrease",
-      "stateMutability": "nonpayable",
-      "inputs": [
-        {
-          "name": "_stakingProvider",
-          "type": "address",
-          "internalType": "address"
-        },
-        {
-          "name": "_fromAmount",
-          "type": "uint96",
-          "internalType": "uint96"
-        },
-        {
-          "name": "_toAmount",
-          "type": "uint96",
-          "internalType": "uint96"
-        }
-      ],
-      "outputs": []
-    },
-    {
-      "type": "function",
-      "name": "isAuthorized",
-      "stateMutability": "view",
-      "inputs": [
-        {
-          "name": "_stakingProvider",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": [
-        {
-          "name": "",
-          "type": "bool",
-          "internalType": "bool"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "isOperatorConfirmed",
-      "stateMutability": "view",
-      "inputs": [
-        {
-          "name": "_operator",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": [
-        {
-          "name": "",
-          "type": "bool",
-          "internalType": "bool"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "lastTimeRewardApplicable",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint256",
-          "internalType": "uint256"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "lastUpdateTime",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint256",
-          "internalType": "uint256"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "makeCommitment",
-      "stateMutability": "nonpayable",
-      "inputs": [
-        {
-          "name": "_stakingProvider",
-          "type": "address",
-          "internalType": "address"
-        },
-        {
-          "name": "_commitmentDuration",
-          "type": "uint64",
-          "internalType": "uint64"
-        }
-      ],
-      "outputs": []
-    },
-    {
-      "type": "function",
-      "name": "manualChildSynchronization",
-      "stateMutability": "nonpayable",
-      "inputs": [
-        {
-          "name": "_stakingProvider",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": []
-    },
-    {
-      "type": "function",
-      "name": "minOperatorSeconds",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint256",
-          "internalType": "uint256"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "minimumAuthorization",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint96",
-          "internalType": "uint96"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "operatorToStakingProvider",
-      "stateMutability": "view",
-      "inputs": [
-        {
-          "name": "_operator",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": [
-        {
-          "name": "",
-          "type": "address",
-          "internalType": "address"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "owner",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "address",
-          "internalType": "address"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "pendingAuthorizationDecrease",
-      "stateMutability": "view",
-      "inputs": [
-        {
-          "name": "_stakingProvider",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint96",
-          "internalType": "uint96"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "periodFinish",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint256",
-          "internalType": "uint256"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "pushReward",
-      "stateMutability": "nonpayable",
-      "inputs": [
-        {
-          "name": "_reward",
-          "type": "uint96",
-          "internalType": "uint96"
-        }
-      ],
-      "outputs": []
-    },
-    {
-      "type": "function",
-      "name": "registerOperator",
-      "stateMutability": "nonpayable",
-      "inputs": [
-        {
-          "name": "_operator",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": []
-    },
-    {
-      "type": "function",
-      "name": "remainingAuthorizationDecreaseDelay",
-      "stateMutability": "view",
-      "inputs": [
-        {
-          "name": "_stakingProvider",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint64",
-          "internalType": "uint64"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "renounceOwnership",
-      "stateMutability": "nonpayable",
-      "inputs": [],
-      "outputs": []
-    },
-    {
-      "type": "function",
-      "name": "resynchronizeAuthorization",
-      "stateMutability": "nonpayable",
-      "inputs": [
-        {
-          "name": "_stakingProvider",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": []
-    },
-    {
-      "type": "function",
-      "name": "rewardDistributor",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "address",
-          "internalType": "address"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "rewardDuration",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint256",
-          "internalType": "uint256"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "rewardPerToken",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint160",
-          "internalType": "uint160"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "rewardPerTokenStored",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint160",
-          "internalType": "uint160"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "rewardRateDecimals",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint256",
-          "internalType": "uint256"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "setAdjudicator",
-      "stateMutability": "nonpayable",
-      "inputs": [
-        {
-          "name": "_adjudicator",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": []
-    },
-    {
-      "type": "function",
-      "name": "setChildApplication",
-      "stateMutability": "nonpayable",
-      "inputs": [
-        {
-          "name": "_childApplication",
-          "type": "address",
-          "internalType": "contract ITACoRootToChild"
-        }
-      ],
-      "outputs": []
-    },
-    {
-      "type": "function",
-      "name": "setRewardDistributor",
-      "stateMutability": "nonpayable",
-      "inputs": [
-        {
-          "name": "_rewardDistributor",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": []
-    },
-    {
-      "type": "function",
-      "name": "slash",
-      "stateMutability": "nonpayable",
-      "inputs": [
-        {
-          "name": "_stakingProvider",
-          "type": "address",
-          "internalType": "address"
-        },
-        {
-          "name": "_penalty",
-          "type": "uint96",
-          "internalType": "uint96"
-        },
-        {
-          "name": "_investigator",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": []
-    },
-    {
-      "type": "function",
-      "name": "stakingProviderInfo",
-      "stateMutability": "view",
-      "inputs": [
-        {
-          "name": "",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": [
-        {
-          "name": "operator",
-          "type": "address",
-          "internalType": "address"
-        },
-        {
-          "name": "operatorConfirmed",
-          "type": "bool",
-          "internalType": "bool"
-        },
-        {
-          "name": "operatorStartTimestamp",
-          "type": "uint64",
-          "internalType": "uint64"
-        },
-        {
-          "name": "authorized",
-          "type": "uint96",
-          "internalType": "uint96"
-        },
-        {
-          "name": "deauthorizing",
-          "type": "uint96",
-          "internalType": "uint96"
-        },
-        {
-          "name": "endDeauthorization",
-          "type": "uint64",
-          "internalType": "uint64"
-        },
-        {
-          "name": "tReward",
-          "type": "uint96",
-          "internalType": "uint96"
-        },
-        {
-          "name": "rewardPerTokenPaid",
-          "type": "uint160",
-          "internalType": "uint160"
-        },
-        {
-          "name": "endCommitment",
-          "type": "uint64",
-          "internalType": "uint64"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "stakingProviderToOperator",
-      "stateMutability": "view",
-      "inputs": [
-        {
-          "name": "_stakingProvider",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": [
-        {
-          "name": "",
-          "type": "address",
-          "internalType": "address"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "stakingProviders",
-      "stateMutability": "view",
-      "inputs": [
-        {
-          "name": "",
-          "type": "uint256",
-          "internalType": "uint256"
-        }
-      ],
-      "outputs": [
-        {
-          "name": "",
-          "type": "address",
-          "internalType": "address"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "tStaking",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "address",
-          "internalType": "contract IStaking"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "token",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "address",
-          "internalType": "contract IERC20"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "transferOwnership",
-      "stateMutability": "nonpayable",
-      "inputs": [
-        {
-          "name": "newOwner",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": []
-    },
-    {
-      "type": "function",
-      "name": "withdrawRewards",
-      "stateMutability": "nonpayable",
-      "inputs": [
-        {
-          "name": "_stakingProvider",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": []
-    }
-  ],
-  "tx_hash": "0x4824e7d3b6dae9ec69b79b9f0578853c51fd92a49b0edce45d892d6cdf7901bd",
-  "block_number": 5048617,
-  "deployer": "0x3B42d26E19FF860bC4dEbB920DD8caA53F93c600"
-}
diff --git a/src/threshold-ts/utils/contract.ts b/src/threshold-ts/utils/contract.ts
index e01210cb4..e20401c04 100644
--- a/src/threshold-ts/utils/contract.ts
+++ b/src/threshold-ts/utils/contract.ts
@@ -38,7 +38,7 @@ import WalletRegistryArtifactSepolia from "@keep-network/tbtc-v2.ts/src/lib/ethe
 import StakingArtifactSepolia from "../staking/sepolia-artifacts/TokenStaking.json"
 import RandomBeaconArtifactSepolia from "../tbtc/sepolia-artifacts/RandomBeacon.json"
 import LegacyKeepStakingArtifactSepolia from "../staking/sepolia-artifacts/LegacyKeepStaking.json"
-import TacoRegistryArtifactSepolia from "../mas/sepolia-artifacts/TacoRegistry.json"
+import TacoRegistryArtifactSepolia from "@nucypher/nucypher-contracts/deployment/artifacts/tapir.json"
 
 import BridgeArtifactDappDevelopmentSepolia from "../tbtc/dapp-development-sepolia-artifacts/Bridge.json"
 import NuCypherStakingEscrowDappDevelopmentSepolia from "../staking/dapp-development-sepolia-artifacts/NuCypherStakingEscrow.json"
@@ -51,7 +51,7 @@ import WalletRegistryArtifactDappDevelopmentSepolia from "../tbtc/dapp-developme
 import StakingArtifactDappDevelopmentSepolia from "../staking/dapp-development-sepolia-artifacts/TokenStaking.json"
 import RandomBeaconArtifactDappDevelopmentSepolia from "../tbtc/dapp-development-sepolia-artifacts/RandomBeacon.json"
 import LegacyKeepStakingArtifactDappDevelopmentSepolia from "../staking/dapp-development-sepolia-artifacts/LegacyKeepStaking.json"
-import TacoRegistryArtifactDappDevelopmentSepolia from "../mas/dapp-development-sepolia-artifacts/TacoRegistry.json"
+import TacoRegistryArtifactDappDevelopmentSepolia from "@nucypher/nucypher-contracts/deployment/artifacts/dashboard.json"
 
 export type ArtifactNameType =
   | "TacoRegistry"

From 7dca90feffe69a0b16e84b2cd72515c3d385f98c Mon Sep 17 00:00:00 2001
From: evandrosaturnino <evandro.saturnino@gmail.com>
Date: Mon, 6 Jan 2025 21:39:30 -0300
Subject: [PATCH 35/46] Fix testnet taco registry artifact application import

---
 src/threshold-ts/utils/contract.ts | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/src/threshold-ts/utils/contract.ts b/src/threshold-ts/utils/contract.ts
index e20401c04..c32a4e8aa 100644
--- a/src/threshold-ts/utils/contract.ts
+++ b/src/threshold-ts/utils/contract.ts
@@ -99,7 +99,8 @@ const contractArtifacts: ContractArtifacts = {
   [SupportedChainIds.Sepolia]: {
     ArbitrumL1BitcoinDepositor: ArbitrumL1BitcoinDepositorArtifactSepolia,
     BaseL1BitcoinDepositor: BaseL1BitcoinDepositorArtifactSepolia,
-    TacoRegistry: TacoRegistryArtifactSepolia,
+    TacoRegistry:
+      TacoRegistryArtifactSepolia[SupportedChainIds.Sepolia].TACoApplication,
     RandomBeacon: RandomBeaconArtifactSepolia,
     TokenStaking: StakingArtifactSepolia,
     Bridge: BridgeArtifactSepolia,
@@ -112,7 +113,8 @@ const contractArtifacts: ContractArtifacts = {
     VendingMachineNuCypher: VendingMachineNuCypherSepolia,
   },
   [SupportedChainIds.Localhost]: {
-    TacoRegistry: TacoRegistryArtifactDappDevelopmentSepolia,
+    TacoRegistry:
+      TacoRegistryArtifactSepolia[SupportedChainIds.Sepolia].TACoApplication,
     LegacyKeepStaking: LegacyKeepStakingArtifactDappDevelopmentSepolia,
     RandomBeacon: RandomBeaconArtifactDappDevelopmentSepolia,
     TokenStaking: StakingArtifactDappDevelopmentSepolia,

From 247a2f3e1b668b39ee6f7e5287fb89245f1113f8 Mon Sep 17 00:00:00 2001
From: evandrosaturnino <evandro.saturnino@gmail.com>
Date: Fri, 17 Jan 2025 00:45:47 -0300
Subject: [PATCH 36/46] Update nucypher contracts module version

---
 package.json                       |  2 +-
 src/threshold-ts/utils/contract.ts | 12 ++++++------
 yarn.lock                          |  8 ++++----
 3 files changed, 11 insertions(+), 11 deletions(-)

diff --git a/package.json b/package.json
index 6668fb35d..780d9e516 100644
--- a/package.json
+++ b/package.json
@@ -22,7 +22,7 @@
     "@ledgerhq/connect-kit-loader": "1.1.8",
     "@ledgerhq/wallet-api-client": "^1.2.0",
     "@ledgerhq/wallet-api-client-react": "^1.1.1",
-    "@nucypher/nucypher-contracts": "0.13.0",
+    "@nucypher/nucypher-contracts": "0.23.0",
     "@reduxjs/toolkit": "^1.6.1",
     "@rehooks/local-storage": "^2.4.4",
     "@sentry/react": "^7.33.0",
diff --git a/src/threshold-ts/utils/contract.ts b/src/threshold-ts/utils/contract.ts
index c32a4e8aa..db82d828e 100644
--- a/src/threshold-ts/utils/contract.ts
+++ b/src/threshold-ts/utils/contract.ts
@@ -23,7 +23,7 @@ import WalletRegistryArtifactMainnet from "@keep-network/tbtc-v2.ts/src/lib/ethe
 import StakingArtifactMainnet from "../staking/mainnet-artifacts/TokenStaking.json"
 import RandomBeaconArtifactMainnet from "../tbtc/mainnet-artifacts/RandomBeacon.json"
 import LegacyKeepStakingArtifactMainnet from "../staking/mainnet-artifacts/LegacyKeepStaking.json"
-import TacoRegistryArtifactMainnet from "@nucypher/nucypher-contracts/deployment/artifacts/mainnet.json"
+import TacoArtifactMainnet from "@nucypher/nucypher-contracts/deployment/artifacts/mainnet.json"
 
 import ArbitrumL1BitcoinDepositorArtifactSepolia from "../tbtc/sepolia-artifacts/ArbitrumL1BitcoinDepositor.json"
 import BaseL1BitcoinDepositorArtifactSepolia from "../tbtc/sepolia-artifacts/BaseL1BitcoinDepositor.json"
@@ -38,7 +38,7 @@ import WalletRegistryArtifactSepolia from "@keep-network/tbtc-v2.ts/src/lib/ethe
 import StakingArtifactSepolia from "../staking/sepolia-artifacts/TokenStaking.json"
 import RandomBeaconArtifactSepolia from "../tbtc/sepolia-artifacts/RandomBeacon.json"
 import LegacyKeepStakingArtifactSepolia from "../staking/sepolia-artifacts/LegacyKeepStaking.json"
-import TacoRegistryArtifactSepolia from "@nucypher/nucypher-contracts/deployment/artifacts/tapir.json"
+import TacoArtifactSepolia from "@nucypher/nucypher-contracts/deployment/artifacts/tapir.json"
 
 import BridgeArtifactDappDevelopmentSepolia from "../tbtc/dapp-development-sepolia-artifacts/Bridge.json"
 import NuCypherStakingEscrowDappDevelopmentSepolia from "../staking/dapp-development-sepolia-artifacts/NuCypherStakingEscrow.json"
@@ -51,7 +51,7 @@ import WalletRegistryArtifactDappDevelopmentSepolia from "../tbtc/dapp-developme
 import StakingArtifactDappDevelopmentSepolia from "../staking/dapp-development-sepolia-artifacts/TokenStaking.json"
 import RandomBeaconArtifactDappDevelopmentSepolia from "../tbtc/dapp-development-sepolia-artifacts/RandomBeacon.json"
 import LegacyKeepStakingArtifactDappDevelopmentSepolia from "../staking/dapp-development-sepolia-artifacts/LegacyKeepStaking.json"
-import TacoRegistryArtifactDappDevelopmentSepolia from "@nucypher/nucypher-contracts/deployment/artifacts/dashboard.json"
+import TacoArtifactDappDevelopmentSepolia from "@nucypher/nucypher-contracts/deployment/artifacts/dashboard.json"
 
 export type ArtifactNameType =
   | "TacoRegistry"
@@ -83,7 +83,7 @@ const contractArtifacts: ContractArtifacts = {
   [SupportedChainIds.Ethereum]: {
     ArbitrumL1BitcoinDepositor: ArbitrumL1BitcoinDepositorArtifactMainnet,
     TacoRegistry:
-      TacoRegistryArtifactMainnet[SupportedChainIds.Ethereum].TACoApplication,
+      TacoArtifactMainnet[SupportedChainIds.Ethereum].TACoApplication,
     LegacyKeepStaking: LegacyKeepStakingArtifactMainnet,
     RandomBeacon: RandomBeaconArtifactMainnet,
     TokenStaking: StakingArtifactMainnet,
@@ -100,7 +100,7 @@ const contractArtifacts: ContractArtifacts = {
     ArbitrumL1BitcoinDepositor: ArbitrumL1BitcoinDepositorArtifactSepolia,
     BaseL1BitcoinDepositor: BaseL1BitcoinDepositorArtifactSepolia,
     TacoRegistry:
-      TacoRegistryArtifactSepolia[SupportedChainIds.Sepolia].TACoApplication,
+      TacoArtifactSepolia[SupportedChainIds.Sepolia].TACoApplication,
     RandomBeacon: RandomBeaconArtifactSepolia,
     TokenStaking: StakingArtifactSepolia,
     Bridge: BridgeArtifactSepolia,
@@ -114,7 +114,7 @@ const contractArtifacts: ContractArtifacts = {
   },
   [SupportedChainIds.Localhost]: {
     TacoRegistry:
-      TacoRegistryArtifactSepolia[SupportedChainIds.Sepolia].TACoApplication,
+      TacoArtifactSepolia[SupportedChainIds.Sepolia].TACoApplication,
     LegacyKeepStaking: LegacyKeepStakingArtifactDappDevelopmentSepolia,
     RandomBeacon: RandomBeaconArtifactDappDevelopmentSepolia,
     TokenStaking: StakingArtifactDappDevelopmentSepolia,
diff --git a/yarn.lock b/yarn.lock
index 547cc3a0b..a4bb5bd31 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -3681,10 +3681,10 @@
     mkdirp "^1.0.4"
     rimraf "^3.0.2"
 
-"@nucypher/nucypher-contracts@0.13.0":
-  version "0.13.0"
-  resolved "https://registry.yarnpkg.com/@nucypher/nucypher-contracts/-/nucypher-contracts-0.13.0.tgz#43ead85d4cdf7eb6b459ba77a6ff90a8bb796300"
-  integrity sha512-QB9vCVq2mLR2SeA/gSX8Px2QW3wcc9keQuTwgtDOA5J7PLoxDHEAko4ow6ZlsfjsbK572Xz6YReH09MBr71ujA==
+"@nucypher/nucypher-contracts@0.23.0":
+  version "0.23.0"
+  resolved "https://registry.yarnpkg.com/@nucypher/nucypher-contracts/-/nucypher-contracts-0.23.0.tgz#beebaea7665e822949238fff4e712d29bbf64493"
+  integrity sha512-vilcgICbFzSP2x5otEJHzmaKsbX4t6DIU8aj4U33taTeCdR62LDFS6tCG1r+XzgSmIJZO8ksO5bGzaEHF+r1Ww==
 
 "@openzeppelin/contracts-upgradeable@^4.6.0", "@openzeppelin/contracts-upgradeable@^4.8.1":
   version "4.9.1"

From 764d57f509d05b3d0b7baad91c6c282f211ae71e Mon Sep 17 00:00:00 2001
From: evandrosaturnino <evandro.saturnino@gmail.com>
Date: Fri, 17 Jan 2025 11:37:28 -0300
Subject: [PATCH 37/46] convert coinbase chainid hex to number format

---
 src/web3/connectors/coinbaseWallet.ts | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/src/web3/connectors/coinbaseWallet.ts b/src/web3/connectors/coinbaseWallet.ts
index 012669b98..dcd785c29 100644
--- a/src/web3/connectors/coinbaseWallet.ts
+++ b/src/web3/connectors/coinbaseWallet.ts
@@ -1,6 +1,10 @@
 import { WalletLinkConnector } from "@web3-react/walletlink-connector"
 import { ConnectorUpdate } from "@web3-react/types"
-import { getRpcUrl, supportedNetworksMap } from "../../networks/utils"
+import {
+  getRpcUrl,
+  hexToNumber,
+  supportedNetworksMap,
+} from "../../networks/utils"
 
 interface CoinbaseWalletProvider {
   isCoinbaseWallet: boolean
@@ -18,7 +22,8 @@ export class CoinbaseWalletConnector extends WalletLinkConnector {
         (p) => p.isCoinbaseWallet
       ) ?? (window.ethereum as CoinbaseWalletProvider)
 
-    const chainId = provider.chainId || (await this.getChainId())
+    const chainIdHex = provider.chainId || (await this.getChainId())
+    const chainId = hexToNumber(chainIdHex)
 
     if (provider.isCoinbaseWallet) {
       // Force the Coinbase Wallet provider to use our RPC url. We can't fetch

From 786cebdbbcfd9ce2654adc335bef5951464f6165 Mon Sep 17 00:00:00 2001
From: evandrosaturnino <evandro.saturnino@gmail.com>
Date: Thu, 23 Jan 2025 00:11:58 -0300
Subject: [PATCH 38/46] update arbitrum minting fee

---
 src/threshold-ts/tbtc/index.ts | 15 +++++++++++----
 1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/src/threshold-ts/tbtc/index.ts b/src/threshold-ts/tbtc/index.ts
index 8a7de996c..637064d1e 100644
--- a/src/threshold-ts/tbtc/index.ts
+++ b/src/threshold-ts/tbtc/index.ts
@@ -936,19 +936,26 @@ export class TBTC implements ITBTC {
       this.ethereumChainId === SupportedChainIds.Arbitrum ||
       this.ethereumChainId === SupportedChainIds.ArbitrumSepolia
 
-    const amountToMint = depositAmount
-      .sub(isArbitrumNetworkConnected ? depositTxMaxFee : ZERO)
+    const amountToMintAfterTreasuryFee = depositAmount
       .sub(treasuryFee)
       .mul(this._satoshiMultiplier)
 
     // https://github.com/keep-network/tbtc-v2/blob/main/solidity/contracts/vault/TBTCOptimisticMinting.sol#L328-L336
     const optimisticMintFee = BigNumber.from(optimisticMintingFeeDivisor).gt(0)
-      ? amountToMint.div(optimisticMintingFeeDivisor)
+      ? amountToMintAfterTreasuryFee.div(optimisticMintingFeeDivisor)
       : ZERO
 
+    const finalAmountToMint = amountToMintAfterTreasuryFee
+      .sub(optimisticMintFee)
+      .sub(
+        isArbitrumNetworkConnected
+          ? depositTxMaxFee.mul(this._satoshiMultiplier)
+          : ZERO
+      )
+
     return {
       optimisticMintFee: optimisticMintFee,
-      amountToMint: amountToMint.sub(optimisticMintFee),
+      amountToMint: finalAmountToMint,
     }
   }
 

From 9e7ba9e0c721a73eb6d2a9d74444ebcfc3c7fd88 Mon Sep 17 00:00:00 2001
From: evandrosaturnino <evandro.saturnino@gmail.com>
Date: Fri, 24 Jan 2025 10:45:24 -0300
Subject: [PATCH 39/46] improve readability of minting fees calculation

---
 src/threshold-ts/tbtc/index.ts | 17 ++++++++++-------
 1 file changed, 10 insertions(+), 7 deletions(-)

diff --git a/src/threshold-ts/tbtc/index.ts b/src/threshold-ts/tbtc/index.ts
index 637064d1e..c7da93463 100644
--- a/src/threshold-ts/tbtc/index.ts
+++ b/src/threshold-ts/tbtc/index.ts
@@ -926,12 +926,15 @@ export class TBTC implements ITBTC {
     }
   }
 
-  private _calculateOptimisticMintingAmountAndFee = (
+  private _calculateOptimisticMintingAmountAndFee(
     depositAmount: BigNumber,
     treasuryFee: BigNumber,
     optimisticMintingFeeDivisor: BigNumber,
     depositTxMaxFee: BigNumber
-  ) => {
+  ): {
+    optimisticMintFee: BigNumber
+    amountToMint: BigNumber
+  } {
     const isArbitrumNetworkConnected =
       this.ethereumChainId === SupportedChainIds.Arbitrum ||
       this.ethereumChainId === SupportedChainIds.ArbitrumSepolia
@@ -945,13 +948,13 @@ export class TBTC implements ITBTC {
       ? amountToMintAfterTreasuryFee.div(optimisticMintingFeeDivisor)
       : ZERO
 
+    const networkSpecificFee = isArbitrumNetworkConnected
+      ? depositTxMaxFee.mul(this._satoshiMultiplier)
+      : ZERO
+
     const finalAmountToMint = amountToMintAfterTreasuryFee
       .sub(optimisticMintFee)
-      .sub(
-        isArbitrumNetworkConnected
-          ? depositTxMaxFee.mul(this._satoshiMultiplier)
-          : ZERO
-      )
+      .sub(networkSpecificFee)
 
     return {
       optimisticMintFee: optimisticMintFee,

From 8d6b4f94ed110308214cb4f2862f9924dd56bee5 Mon Sep 17 00:00:00 2001
From: evandrosaturnino <evandro.saturnino@gmail.com>
Date: Tue, 12 Nov 2024 10:26:36 -0300
Subject: [PATCH 40/46] Add networks centralized folder

---
 src/networks/hooks/useDefaultOrConnectedChainId.ts |  9 +++++++++
 src/networks/utils/validateL2TransactionType.ts    | 11 +++++++++++
 2 files changed, 20 insertions(+)
 create mode 100644 src/networks/hooks/useDefaultOrConnectedChainId.ts
 create mode 100644 src/networks/utils/validateL2TransactionType.ts

diff --git a/src/networks/hooks/useDefaultOrConnectedChainId.ts b/src/networks/hooks/useDefaultOrConnectedChainId.ts
new file mode 100644
index 000000000..fe023a21f
--- /dev/null
+++ b/src/networks/hooks/useDefaultOrConnectedChainId.ts
@@ -0,0 +1,9 @@
+import { useIsActive } from "../../hooks/useIsActive"
+import { getDefaultProviderChainId } from "../../utils/getEnvVariable"
+
+export const useDefaultOrConnectedChainId = () => {
+  const { chainId } = useIsActive()
+  const defaultOrConnectedChainId = chainId ?? getDefaultProviderChainId()
+
+  return defaultOrConnectedChainId
+}
diff --git a/src/networks/utils/validateL2TransactionType.ts b/src/networks/utils/validateL2TransactionType.ts
new file mode 100644
index 000000000..0af9f1c62
--- /dev/null
+++ b/src/networks/utils/validateL2TransactionType.ts
@@ -0,0 +1,11 @@
+import { ALLOWED_L2_TRANSACTIONS } from "../constants/networks"
+import { AllowedL2TransactionTypes } from "../enums/networks"
+
+export function isValidL2Transaction<T = AllowedL2TransactionTypes>(
+  type?: T
+): boolean {
+  if (!type) return false
+  return ALLOWED_L2_TRANSACTIONS.includes(
+    type as unknown as AllowedL2TransactionTypes
+  )
+}

From acfa2bac77c3f2e4a83c3777bbdd20428d250302 Mon Sep 17 00:00:00 2001
From: evandrosaturnino <evandro.saturnino@gmail.com>
Date: Tue, 12 Nov 2024 10:36:44 -0300
Subject: [PATCH 41/46] Update contract initialization handling

---
 src/contexts/TokenContext.tsx                 |    1 -
 .../useAuthorizeMultipleAppsTransaction.ts    |    2 +-
 src/hooks/useFetchStakingRewards.ts           |    2 +
 src/hooks/useFetchTvl.ts                      |    1 +
 src/store/staking-applications/effects.ts     |    2 +-
 src/store/staking/effects.ts                  |    2 +-
 .../TacoRegistry.json                         | 1352 ++++++++++++++
 .../mas/mainnet-artifacts/TacoRegistry.json   | 1646 +++++++++++++++++
 .../mas/sepolia-artifacts/TacoRegistry.json   | 1431 ++++++++++++++
 src/web3/hooks/useNuStakingEscrowContract.ts  |    2 +-
 10 files changed, 4436 insertions(+), 5 deletions(-)
 create mode 100644 src/threshold-ts/mas/dapp-development-sepolia-artifacts/TacoRegistry.json
 create mode 100644 src/threshold-ts/mas/mainnet-artifacts/TacoRegistry.json
 create mode 100644 src/threshold-ts/mas/sepolia-artifacts/TacoRegistry.json

diff --git a/src/contexts/TokenContext.tsx b/src/contexts/TokenContext.tsx
index b9d4a25dc..e518ee7ae 100644
--- a/src/contexts/TokenContext.tsx
+++ b/src/contexts/TokenContext.tsx
@@ -15,7 +15,6 @@ import { useTBTCv2TokenContract } from "../web3/hooks/useTBTCv2TokenContract"
 import { featureFlags } from "../constants"
 import { useIsActive } from "../hooks/useIsActive"
 import { isL1Network, isL2Network } from "../networks/utils/connectedNetwork"
-
 interface TokenContextState extends TokenState {
   contract: Contract | null
 }
diff --git a/src/hooks/staking-applications/useAuthorizeMultipleAppsTransaction.ts b/src/hooks/staking-applications/useAuthorizeMultipleAppsTransaction.ts
index 77fc0cb60..716eacea4 100644
--- a/src/hooks/staking-applications/useAuthorizeMultipleAppsTransaction.ts
+++ b/src/hooks/staking-applications/useAuthorizeMultipleAppsTransaction.ts
@@ -14,7 +14,7 @@ export const useAuthorizeMultipleAppsTransaction = () => {
   const { openModal } = useModal()
 
   const { sendTransaction, status } = useSendTransactionFromFn(
-    threshold.staking.increaseAuthorization
+    threshold.staking!.increaseAuthorization
   )
 
   const authorizeMultipleApps = useCallback(
diff --git a/src/hooks/useFetchStakingRewards.ts b/src/hooks/useFetchStakingRewards.ts
index e6f03e0e5..da89f919f 100644
--- a/src/hooks/useFetchStakingRewards.ts
+++ b/src/hooks/useFetchStakingRewards.ts
@@ -12,12 +12,14 @@ import { setInterimRewards } from "../store/rewards"
 import { selectStakingProviders } from "../store/staking"
 import { BigNumber } from "ethers"
 import { Zero } from "@ethersproject/constants"
+import { useIsActive } from "./useIsActive"
 
 interface StakingRewards {
   [stakingProvider: string]: string
 }
 
 export const useFetchStakingRewards = () => {
+  const { chainId } = useIsActive()
   const merkleDropContract = useMerkleDropContract()
   const stakingProviders = useSelector(selectStakingProviders)
   const { hasFetched, isFetching } = useSelector(
diff --git a/src/hooks/useFetchTvl.ts b/src/hooks/useFetchTvl.ts
index 020c5d2fb..22577dafb 100644
--- a/src/hooks/useFetchTvl.ts
+++ b/src/hooks/useFetchTvl.ts
@@ -127,6 +127,7 @@ export const useFetchTvl = (): [
   const fetchOnChainData = useMulticall(calls)
 
   const fetchTvlData = useCallback(async () => {
+    if (chainId && !isL1Network(chainId)) return initialState
     const chainData = await fetchOnChainData()
     if (chainData.length === 0) return initialState
 
diff --git a/src/store/staking-applications/effects.ts b/src/store/staking-applications/effects.ts
index f6b4874f9..95a1d73fa 100644
--- a/src/store/staking-applications/effects.ts
+++ b/src/store/staking-applications/effects.ts
@@ -62,7 +62,7 @@ export const getSupportedAppsEffect = async (
       })
     )
     const data =
-      await listenerApi.extra.threshold.multiAppStaking.getSupportedAppsAuthParameters()
+      await listenerApi.extra.threshold.multiAppStaking!.getSupportedAppsAuthParameters()
     const payload = {
       tbtc: {
         minimumAuthorization: data.tbtc!.minimumAuthorization.toString(),
diff --git a/src/store/staking/effects.ts b/src/store/staking/effects.ts
index 4180d3955..24b7597a9 100644
--- a/src/store/staking/effects.ts
+++ b/src/store/staking/effects.ts
@@ -57,7 +57,7 @@ const fetchStake = async (
   listenerApi: AppListenerEffectAPI
 ) => {
   const stake =
-    await listenerApi.extra.threshold.staking.getStakeByStakingProvider(
+    await listenerApi.extra.threshold.staking!.getStakeByStakingProvider(
       stakingProvider
     )
 
diff --git a/src/threshold-ts/mas/dapp-development-sepolia-artifacts/TacoRegistry.json b/src/threshold-ts/mas/dapp-development-sepolia-artifacts/TacoRegistry.json
new file mode 100644
index 000000000..1e5bcbf03
--- /dev/null
+++ b/src/threshold-ts/mas/dapp-development-sepolia-artifacts/TacoRegistry.json
@@ -0,0 +1,1352 @@
+{
+  "address": "0xE9Eb81F72cDBE9fE82f61EA527e8a3A39f5B023a",
+  "abi": [
+    {
+      "type": "constructor",
+      "stateMutability": "nonpayable",
+      "inputs": [
+        {
+          "name": "_token",
+          "type": "address",
+          "internalType": "contract IERC20"
+        },
+        {
+          "name": "_tStaking",
+          "type": "address",
+          "internalType": "contract IStaking"
+        },
+        {
+          "name": "_minimumAuthorization",
+          "type": "uint96",
+          "internalType": "uint96"
+        },
+        {
+          "name": "_minOperatorSeconds",
+          "type": "uint256",
+          "internalType": "uint256"
+        },
+        {
+          "name": "_rewardDuration",
+          "type": "uint256",
+          "internalType": "uint256"
+        },
+        {
+          "name": "_deauthorizationDuration",
+          "type": "uint256",
+          "internalType": "uint256"
+        },
+        {
+          "name": "_commitmentDurationOptions",
+          "type": "uint64[]",
+          "internalType": "uint64[]"
+        },
+        {
+          "name": "_commitmentDeadline",
+          "type": "uint64",
+          "internalType": "uint64"
+        }
+      ]
+    },
+    {
+      "type": "error",
+      "name": "AddressEmptyCode",
+      "inputs": [
+        {
+          "name": "target",
+          "type": "address",
+          "internalType": "address"
+        }
+      ]
+    },
+    {
+      "type": "error",
+      "name": "AddressInsufficientBalance",
+      "inputs": [
+        {
+          "name": "account",
+          "type": "address",
+          "internalType": "address"
+        }
+      ]
+    },
+    {
+      "type": "error",
+      "name": "FailedInnerCall",
+      "inputs": []
+    },
+    {
+      "type": "error",
+      "name": "InvalidInitialization",
+      "inputs": []
+    },
+    {
+      "type": "error",
+      "name": "NotInitializing",
+      "inputs": []
+    },
+    {
+      "type": "error",
+      "name": "OwnableInvalidOwner",
+      "inputs": [
+        {
+          "name": "owner",
+          "type": "address",
+          "internalType": "address"
+        }
+      ]
+    },
+    {
+      "type": "error",
+      "name": "OwnableUnauthorizedAccount",
+      "inputs": [
+        {
+          "name": "account",
+          "type": "address",
+          "internalType": "address"
+        }
+      ]
+    },
+    {
+      "type": "error",
+      "name": "SafeCastOverflowedUintDowncast",
+      "inputs": [
+        {
+          "name": "bits",
+          "type": "uint8",
+          "internalType": "uint8"
+        },
+        {
+          "name": "value",
+          "type": "uint256",
+          "internalType": "uint256"
+        }
+      ]
+    },
+    {
+      "type": "error",
+      "name": "SafeERC20FailedOperation",
+      "inputs": [
+        {
+          "name": "token",
+          "type": "address",
+          "internalType": "address"
+        }
+      ]
+    },
+    {
+      "type": "event",
+      "name": "AuthorizationDecreaseApproved",
+      "inputs": [
+        {
+          "name": "stakingProvider",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        },
+        {
+          "name": "fromAmount",
+          "type": "uint96",
+          "internalType": "uint96",
+          "indexed": false
+        },
+        {
+          "name": "toAmount",
+          "type": "uint96",
+          "internalType": "uint96",
+          "indexed": false
+        }
+      ],
+      "anonymous": false
+    },
+    {
+      "type": "event",
+      "name": "AuthorizationDecreaseRequested",
+      "inputs": [
+        {
+          "name": "stakingProvider",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        },
+        {
+          "name": "fromAmount",
+          "type": "uint96",
+          "internalType": "uint96",
+          "indexed": false
+        },
+        {
+          "name": "toAmount",
+          "type": "uint96",
+          "internalType": "uint96",
+          "indexed": false
+        }
+      ],
+      "anonymous": false
+    },
+    {
+      "type": "event",
+      "name": "AuthorizationIncreased",
+      "inputs": [
+        {
+          "name": "stakingProvider",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        },
+        {
+          "name": "fromAmount",
+          "type": "uint96",
+          "internalType": "uint96",
+          "indexed": false
+        },
+        {
+          "name": "toAmount",
+          "type": "uint96",
+          "internalType": "uint96",
+          "indexed": false
+        }
+      ],
+      "anonymous": false
+    },
+    {
+      "type": "event",
+      "name": "AuthorizationInvoluntaryDecreased",
+      "inputs": [
+        {
+          "name": "stakingProvider",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        },
+        {
+          "name": "fromAmount",
+          "type": "uint96",
+          "internalType": "uint96",
+          "indexed": false
+        },
+        {
+          "name": "toAmount",
+          "type": "uint96",
+          "internalType": "uint96",
+          "indexed": false
+        }
+      ],
+      "anonymous": false
+    },
+    {
+      "type": "event",
+      "name": "AuthorizationReSynchronized",
+      "inputs": [
+        {
+          "name": "stakingProvider",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        },
+        {
+          "name": "fromAmount",
+          "type": "uint96",
+          "internalType": "uint96",
+          "indexed": false
+        },
+        {
+          "name": "toAmount",
+          "type": "uint96",
+          "internalType": "uint96",
+          "indexed": false
+        }
+      ],
+      "anonymous": false
+    },
+    {
+      "type": "event",
+      "name": "CommitmentMade",
+      "inputs": [
+        {
+          "name": "stakingProvider",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        },
+        {
+          "name": "endCommitment",
+          "type": "uint256",
+          "internalType": "uint256",
+          "indexed": false
+        }
+      ],
+      "anonymous": false
+    },
+    {
+      "type": "event",
+      "name": "Initialized",
+      "inputs": [
+        {
+          "name": "version",
+          "type": "uint64",
+          "internalType": "uint64",
+          "indexed": false
+        }
+      ],
+      "anonymous": false
+    },
+    {
+      "type": "event",
+      "name": "OperatorBonded",
+      "inputs": [
+        {
+          "name": "stakingProvider",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        },
+        {
+          "name": "operator",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        },
+        {
+          "name": "previousOperator",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        },
+        {
+          "name": "startTimestamp",
+          "type": "uint256",
+          "internalType": "uint256",
+          "indexed": false
+        }
+      ],
+      "anonymous": false
+    },
+    {
+      "type": "event",
+      "name": "OperatorConfirmed",
+      "inputs": [
+        {
+          "name": "stakingProvider",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        },
+        {
+          "name": "operator",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        }
+      ],
+      "anonymous": false
+    },
+    {
+      "type": "event",
+      "name": "OwnershipTransferred",
+      "inputs": [
+        {
+          "name": "previousOwner",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        },
+        {
+          "name": "newOwner",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        }
+      ],
+      "anonymous": false
+    },
+    {
+      "type": "event",
+      "name": "RewardAdded",
+      "inputs": [
+        {
+          "name": "reward",
+          "type": "uint256",
+          "internalType": "uint256",
+          "indexed": false
+        }
+      ],
+      "anonymous": false
+    },
+    {
+      "type": "event",
+      "name": "RewardDistributorSet",
+      "inputs": [
+        {
+          "name": "distributor",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        }
+      ],
+      "anonymous": false
+    },
+    {
+      "type": "event",
+      "name": "RewardPaid",
+      "inputs": [
+        {
+          "name": "stakingProvider",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        },
+        {
+          "name": "beneficiary",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        },
+        {
+          "name": "reward",
+          "type": "uint256",
+          "internalType": "uint256",
+          "indexed": false
+        }
+      ],
+      "anonymous": false
+    },
+    {
+      "type": "event",
+      "name": "RewardsWithdrawn",
+      "inputs": [
+        {
+          "name": "stakingProvider",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        },
+        {
+          "name": "amount",
+          "type": "uint96",
+          "internalType": "uint96",
+          "indexed": false
+        }
+      ],
+      "anonymous": false
+    },
+    {
+      "type": "event",
+      "name": "Slashed",
+      "inputs": [
+        {
+          "name": "stakingProvider",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        },
+        {
+          "name": "penalty",
+          "type": "uint256",
+          "internalType": "uint256",
+          "indexed": false
+        },
+        {
+          "name": "investigator",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        },
+        {
+          "name": "reward",
+          "type": "uint256",
+          "internalType": "uint256",
+          "indexed": false
+        }
+      ],
+      "anonymous": false
+    },
+    {
+      "type": "function",
+      "name": "REWARD_PER_TOKEN_MULTIPLIER",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint256",
+          "internalType": "uint256"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "adjudicator",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "address",
+          "internalType": "address"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "approveAuthorizationDecrease",
+      "stateMutability": "nonpayable",
+      "inputs": [
+        {
+          "name": "_stakingProvider",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": []
+    },
+    {
+      "type": "function",
+      "name": "authorizationDecreaseRequested",
+      "stateMutability": "nonpayable",
+      "inputs": [
+        {
+          "name": "_stakingProvider",
+          "type": "address",
+          "internalType": "address"
+        },
+        {
+          "name": "_fromAmount",
+          "type": "uint96",
+          "internalType": "uint96"
+        },
+        {
+          "name": "_toAmount",
+          "type": "uint96",
+          "internalType": "uint96"
+        }
+      ],
+      "outputs": []
+    },
+    {
+      "type": "function",
+      "name": "authorizationIncreased",
+      "stateMutability": "nonpayable",
+      "inputs": [
+        {
+          "name": "_stakingProvider",
+          "type": "address",
+          "internalType": "address"
+        },
+        {
+          "name": "_fromAmount",
+          "type": "uint96",
+          "internalType": "uint96"
+        },
+        {
+          "name": "_toAmount",
+          "type": "uint96",
+          "internalType": "uint96"
+        }
+      ],
+      "outputs": []
+    },
+    {
+      "type": "function",
+      "name": "authorizationParameters",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "_minimumAuthorization",
+          "type": "uint96",
+          "internalType": "uint96"
+        },
+        {
+          "name": "authorizationDecreaseDelay",
+          "type": "uint64",
+          "internalType": "uint64"
+        },
+        {
+          "name": "authorizationDecreaseChangePeriod",
+          "type": "uint64",
+          "internalType": "uint64"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "authorizedOverall",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint96",
+          "internalType": "uint96"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "authorizedStake",
+      "stateMutability": "view",
+      "inputs": [
+        {
+          "name": "_stakingProvider",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint96",
+          "internalType": "uint96"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "availableRewards",
+      "stateMutability": "view",
+      "inputs": [
+        {
+          "name": "_stakingProvider",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint96",
+          "internalType": "uint96"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "bondOperator",
+      "stateMutability": "nonpayable",
+      "inputs": [
+        {
+          "name": "_stakingProvider",
+          "type": "address",
+          "internalType": "address"
+        },
+        {
+          "name": "_operator",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": []
+    },
+    {
+      "type": "function",
+      "name": "childApplication",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "address",
+          "internalType": "contract ITACoRootToChild"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "commitmentDeadline",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint64",
+          "internalType": "uint64"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "commitmentDurationOption1",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint64",
+          "internalType": "uint64"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "commitmentDurationOption2",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint64",
+          "internalType": "uint64"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "commitmentDurationOption3",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint64",
+          "internalType": "uint64"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "commitmentDurationOption4",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint64",
+          "internalType": "uint64"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "confirmOperatorAddress",
+      "stateMutability": "nonpayable",
+      "inputs": [
+        {
+          "name": "_operator",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": []
+    },
+    {
+      "type": "function",
+      "name": "deauthorizationDuration",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint256",
+          "internalType": "uint256"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "getActiveStakingProviders",
+      "stateMutability": "view",
+      "inputs": [
+        {
+          "name": "_startIndex",
+          "type": "uint256",
+          "internalType": "uint256"
+        },
+        {
+          "name": "_maxStakingProviders",
+          "type": "uint256",
+          "internalType": "uint256"
+        }
+      ],
+      "outputs": [
+        {
+          "name": "allAuthorizedTokens",
+          "type": "uint256",
+          "internalType": "uint256"
+        },
+        {
+          "name": "activeStakingProviders",
+          "type": "bytes32[]",
+          "internalType": "bytes32[]"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "getBeneficiary",
+      "stateMutability": "view",
+      "inputs": [
+        {
+          "name": "_stakingProvider",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": [
+        {
+          "name": "beneficiary",
+          "type": "address",
+          "internalType": "address payable"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "getStakingProvidersLength",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint256",
+          "internalType": "uint256"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "initialize",
+      "stateMutability": "nonpayable",
+      "inputs": [],
+      "outputs": []
+    },
+    {
+      "type": "function",
+      "name": "involuntaryAuthorizationDecrease",
+      "stateMutability": "nonpayable",
+      "inputs": [
+        {
+          "name": "_stakingProvider",
+          "type": "address",
+          "internalType": "address"
+        },
+        {
+          "name": "_fromAmount",
+          "type": "uint96",
+          "internalType": "uint96"
+        },
+        {
+          "name": "_toAmount",
+          "type": "uint96",
+          "internalType": "uint96"
+        }
+      ],
+      "outputs": []
+    },
+    {
+      "type": "function",
+      "name": "isAuthorized",
+      "stateMutability": "view",
+      "inputs": [
+        {
+          "name": "_stakingProvider",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": [
+        {
+          "name": "",
+          "type": "bool",
+          "internalType": "bool"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "isOperatorConfirmed",
+      "stateMutability": "view",
+      "inputs": [
+        {
+          "name": "_operator",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": [
+        {
+          "name": "",
+          "type": "bool",
+          "internalType": "bool"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "lastTimeRewardApplicable",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint256",
+          "internalType": "uint256"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "lastUpdateTime",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint256",
+          "internalType": "uint256"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "makeCommitment",
+      "stateMutability": "nonpayable",
+      "inputs": [
+        {
+          "name": "_stakingProvider",
+          "type": "address",
+          "internalType": "address"
+        },
+        {
+          "name": "_commitmentDuration",
+          "type": "uint64",
+          "internalType": "uint64"
+        }
+      ],
+      "outputs": []
+    },
+    {
+      "type": "function",
+      "name": "minOperatorSeconds",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint256",
+          "internalType": "uint256"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "minimumAuthorization",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint96",
+          "internalType": "uint96"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "operatorToStakingProvider",
+      "stateMutability": "view",
+      "inputs": [
+        {
+          "name": "_operator",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": [
+        {
+          "name": "",
+          "type": "address",
+          "internalType": "address"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "owner",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "address",
+          "internalType": "address"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "pendingAuthorizationDecrease",
+      "stateMutability": "view",
+      "inputs": [
+        {
+          "name": "_stakingProvider",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint96",
+          "internalType": "uint96"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "periodFinish",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint256",
+          "internalType": "uint256"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "pushReward",
+      "stateMutability": "nonpayable",
+      "inputs": [
+        {
+          "name": "_reward",
+          "type": "uint96",
+          "internalType": "uint96"
+        }
+      ],
+      "outputs": []
+    },
+    {
+      "type": "function",
+      "name": "registerOperator",
+      "stateMutability": "nonpayable",
+      "inputs": [
+        {
+          "name": "_operator",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": []
+    },
+    {
+      "type": "function",
+      "name": "remainingAuthorizationDecreaseDelay",
+      "stateMutability": "view",
+      "inputs": [
+        {
+          "name": "_stakingProvider",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint64",
+          "internalType": "uint64"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "renounceOwnership",
+      "stateMutability": "nonpayable",
+      "inputs": [],
+      "outputs": []
+    },
+    {
+      "type": "function",
+      "name": "resynchronizeAuthorization",
+      "stateMutability": "nonpayable",
+      "inputs": [
+        {
+          "name": "_stakingProvider",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": []
+    },
+    {
+      "type": "function",
+      "name": "rewardDistributor",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "address",
+          "internalType": "address"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "rewardDuration",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint256",
+          "internalType": "uint256"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "rewardPerToken",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint160",
+          "internalType": "uint160"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "rewardPerTokenStored",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint160",
+          "internalType": "uint160"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "rewardRateDecimals",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint256",
+          "internalType": "uint256"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "setAdjudicator",
+      "stateMutability": "nonpayable",
+      "inputs": [
+        {
+          "name": "_adjudicator",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": []
+    },
+    {
+      "type": "function",
+      "name": "setChildApplication",
+      "stateMutability": "nonpayable",
+      "inputs": [
+        {
+          "name": "_childApplication",
+          "type": "address",
+          "internalType": "contract ITACoRootToChild"
+        }
+      ],
+      "outputs": []
+    },
+    {
+      "type": "function",
+      "name": "setRewardDistributor",
+      "stateMutability": "nonpayable",
+      "inputs": [
+        {
+          "name": "_rewardDistributor",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": []
+    },
+    {
+      "type": "function",
+      "name": "slash",
+      "stateMutability": "nonpayable",
+      "inputs": [
+        {
+          "name": "_stakingProvider",
+          "type": "address",
+          "internalType": "address"
+        },
+        {
+          "name": "_penalty",
+          "type": "uint96",
+          "internalType": "uint96"
+        },
+        {
+          "name": "_investigator",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": []
+    },
+    {
+      "type": "function",
+      "name": "stakingProviderInfo",
+      "stateMutability": "view",
+      "inputs": [
+        {
+          "name": "",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": [
+        {
+          "name": "operator",
+          "type": "address",
+          "internalType": "address"
+        },
+        {
+          "name": "operatorConfirmed",
+          "type": "bool",
+          "internalType": "bool"
+        },
+        {
+          "name": "operatorStartTimestamp",
+          "type": "uint64",
+          "internalType": "uint64"
+        },
+        {
+          "name": "authorized",
+          "type": "uint96",
+          "internalType": "uint96"
+        },
+        {
+          "name": "deauthorizing",
+          "type": "uint96",
+          "internalType": "uint96"
+        },
+        {
+          "name": "endDeauthorization",
+          "type": "uint64",
+          "internalType": "uint64"
+        },
+        {
+          "name": "tReward",
+          "type": "uint96",
+          "internalType": "uint96"
+        },
+        {
+          "name": "rewardPerTokenPaid",
+          "type": "uint160",
+          "internalType": "uint160"
+        },
+        {
+          "name": "endCommitment",
+          "type": "uint64",
+          "internalType": "uint64"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "stakingProviderToOperator",
+      "stateMutability": "view",
+      "inputs": [
+        {
+          "name": "_stakingProvider",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": [
+        {
+          "name": "",
+          "type": "address",
+          "internalType": "address"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "stakingProviders",
+      "stateMutability": "view",
+      "inputs": [
+        {
+          "name": "",
+          "type": "uint256",
+          "internalType": "uint256"
+        }
+      ],
+      "outputs": [
+        {
+          "name": "",
+          "type": "address",
+          "internalType": "address"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "tStaking",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "address",
+          "internalType": "contract IStaking"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "token",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "address",
+          "internalType": "contract IERC20"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "transferOwnership",
+      "stateMutability": "nonpayable",
+      "inputs": [
+        {
+          "name": "newOwner",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": []
+    },
+    {
+      "type": "function",
+      "name": "withdrawRewards",
+      "stateMutability": "nonpayable",
+      "inputs": [
+        {
+          "name": "_stakingProvider",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": []
+    }
+  ],
+  "tx_hash": "0xb9cd5deb857d4e74e45bcd9dd435f3fccf08cdb8c91ac0ca9da36c47210eb149",
+  "block_number": 4776043,
+  "deployer": "0x24dbb0BEE134C3773D2C1791d65d99e307Fe86CF"
+}
diff --git a/src/threshold-ts/mas/mainnet-artifacts/TacoRegistry.json b/src/threshold-ts/mas/mainnet-artifacts/TacoRegistry.json
new file mode 100644
index 000000000..681f5b44a
--- /dev/null
+++ b/src/threshold-ts/mas/mainnet-artifacts/TacoRegistry.json
@@ -0,0 +1,1646 @@
+{
+  "address": "0x347CC7ede7e5517bD47D20620B2CF1b406edcF07",
+  "abi": [
+    {
+      "type": "constructor",
+      "stateMutability": "nonpayable",
+      "inputs": [
+        {
+          "name": "_token",
+          "type": "address",
+          "internalType": "contract IERC20"
+        },
+        {
+          "name": "_tStaking",
+          "type": "address",
+          "internalType": "contract IStaking"
+        },
+        {
+          "name": "_minimumAuthorization",
+          "type": "uint96",
+          "internalType": "uint96"
+        },
+        {
+          "name": "_minOperatorSeconds",
+          "type": "uint256",
+          "internalType": "uint256"
+        },
+        {
+          "name": "_rewardDuration",
+          "type": "uint256",
+          "internalType": "uint256"
+        },
+        {
+          "name": "_deauthorizationDuration",
+          "type": "uint256",
+          "internalType": "uint256"
+        },
+        {
+          "name": "_commitmentDurationOptions",
+          "type": "uint64[]",
+          "internalType": "uint64[]"
+        },
+        {
+          "name": "_commitmentDeadline",
+          "type": "uint64",
+          "internalType": "uint64"
+        },
+        {
+          "name": "_penaltyDefault",
+          "type": "uint192",
+          "internalType": "uint192"
+        },
+        {
+          "name": "_penaltyDuration",
+          "type": "uint256",
+          "internalType": "uint256"
+        },
+        {
+          "name": "_penaltyIncrement",
+          "type": "uint192",
+          "internalType": "uint192"
+        }
+      ]
+    },
+    {
+      "type": "error",
+      "name": "AddressEmptyCode",
+      "inputs": [
+        {
+          "name": "target",
+          "type": "address",
+          "internalType": "address"
+        }
+      ]
+    },
+    {
+      "type": "error",
+      "name": "AddressInsufficientBalance",
+      "inputs": [
+        {
+          "name": "account",
+          "type": "address",
+          "internalType": "address"
+        }
+      ]
+    },
+    {
+      "type": "error",
+      "name": "FailedInnerCall",
+      "inputs": []
+    },
+    {
+      "type": "error",
+      "name": "InvalidInitialization",
+      "inputs": []
+    },
+    {
+      "type": "error",
+      "name": "NotInitializing",
+      "inputs": []
+    },
+    {
+      "type": "error",
+      "name": "OwnableInvalidOwner",
+      "inputs": [
+        {
+          "name": "owner",
+          "type": "address",
+          "internalType": "address"
+        }
+      ]
+    },
+    {
+      "type": "error",
+      "name": "OwnableUnauthorizedAccount",
+      "inputs": [
+        {
+          "name": "account",
+          "type": "address",
+          "internalType": "address"
+        }
+      ]
+    },
+    {
+      "type": "error",
+      "name": "SafeCastOverflowedUintDowncast",
+      "inputs": [
+        {
+          "name": "bits",
+          "type": "uint8",
+          "internalType": "uint8"
+        },
+        {
+          "name": "value",
+          "type": "uint256",
+          "internalType": "uint256"
+        }
+      ]
+    },
+    {
+      "type": "error",
+      "name": "SafeERC20FailedOperation",
+      "inputs": [
+        {
+          "name": "token",
+          "type": "address",
+          "internalType": "address"
+        }
+      ]
+    },
+    {
+      "type": "event",
+      "name": "AuthorizationDecreaseApproved",
+      "inputs": [
+        {
+          "name": "stakingProvider",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        },
+        {
+          "name": "fromAmount",
+          "type": "uint96",
+          "internalType": "uint96",
+          "indexed": false
+        },
+        {
+          "name": "toAmount",
+          "type": "uint96",
+          "internalType": "uint96",
+          "indexed": false
+        }
+      ],
+      "anonymous": false
+    },
+    {
+      "type": "event",
+      "name": "AuthorizationDecreaseRequested",
+      "inputs": [
+        {
+          "name": "stakingProvider",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        },
+        {
+          "name": "fromAmount",
+          "type": "uint96",
+          "internalType": "uint96",
+          "indexed": false
+        },
+        {
+          "name": "toAmount",
+          "type": "uint96",
+          "internalType": "uint96",
+          "indexed": false
+        }
+      ],
+      "anonymous": false
+    },
+    {
+      "type": "event",
+      "name": "AuthorizationIncreased",
+      "inputs": [
+        {
+          "name": "stakingProvider",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        },
+        {
+          "name": "fromAmount",
+          "type": "uint96",
+          "internalType": "uint96",
+          "indexed": false
+        },
+        {
+          "name": "toAmount",
+          "type": "uint96",
+          "internalType": "uint96",
+          "indexed": false
+        }
+      ],
+      "anonymous": false
+    },
+    {
+      "type": "event",
+      "name": "AuthorizationInvoluntaryDecreased",
+      "inputs": [
+        {
+          "name": "stakingProvider",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        },
+        {
+          "name": "fromAmount",
+          "type": "uint96",
+          "internalType": "uint96",
+          "indexed": false
+        },
+        {
+          "name": "toAmount",
+          "type": "uint96",
+          "internalType": "uint96",
+          "indexed": false
+        }
+      ],
+      "anonymous": false
+    },
+    {
+      "type": "event",
+      "name": "AuthorizationReSynchronized",
+      "inputs": [
+        {
+          "name": "stakingProvider",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        },
+        {
+          "name": "fromAmount",
+          "type": "uint96",
+          "internalType": "uint96",
+          "indexed": false
+        },
+        {
+          "name": "toAmount",
+          "type": "uint96",
+          "internalType": "uint96",
+          "indexed": false
+        }
+      ],
+      "anonymous": false
+    },
+    {
+      "type": "event",
+      "name": "CommitmentMade",
+      "inputs": [
+        {
+          "name": "stakingProvider",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        },
+        {
+          "name": "endCommitment",
+          "type": "uint256",
+          "internalType": "uint256",
+          "indexed": false
+        }
+      ],
+      "anonymous": false
+    },
+    {
+      "type": "event",
+      "name": "Initialized",
+      "inputs": [
+        {
+          "name": "version",
+          "type": "uint64",
+          "internalType": "uint64",
+          "indexed": false
+        }
+      ],
+      "anonymous": false
+    },
+    {
+      "type": "event",
+      "name": "ManualChildSynchronizationSent",
+      "inputs": [
+        {
+          "name": "stakingProvider",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        },
+        {
+          "name": "authorized",
+          "type": "uint96",
+          "internalType": "uint96",
+          "indexed": false
+        },
+        {
+          "name": "deauthorizing",
+          "type": "uint96",
+          "internalType": "uint96",
+          "indexed": false
+        },
+        {
+          "name": "endDeauthorization",
+          "type": "uint64",
+          "internalType": "uint64",
+          "indexed": false
+        },
+        {
+          "name": "operator",
+          "type": "address",
+          "internalType": "address",
+          "indexed": false
+        }
+      ],
+      "anonymous": false
+    },
+    {
+      "type": "event",
+      "name": "OperatorBonded",
+      "inputs": [
+        {
+          "name": "stakingProvider",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        },
+        {
+          "name": "operator",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        },
+        {
+          "name": "previousOperator",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        },
+        {
+          "name": "startTimestamp",
+          "type": "uint256",
+          "internalType": "uint256",
+          "indexed": false
+        }
+      ],
+      "anonymous": false
+    },
+    {
+      "type": "event",
+      "name": "OperatorConfirmed",
+      "inputs": [
+        {
+          "name": "stakingProvider",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        },
+        {
+          "name": "operator",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        }
+      ],
+      "anonymous": false
+    },
+    {
+      "type": "event",
+      "name": "OwnershipTransferred",
+      "inputs": [
+        {
+          "name": "previousOwner",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        },
+        {
+          "name": "newOwner",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        }
+      ],
+      "anonymous": false
+    },
+    {
+      "type": "event",
+      "name": "Penalized",
+      "inputs": [
+        {
+          "name": "stakingProvider",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        },
+        {
+          "name": "penaltyPercent",
+          "type": "uint256",
+          "internalType": "uint256",
+          "indexed": false
+        },
+        {
+          "name": "endPenalty",
+          "type": "uint64",
+          "internalType": "uint64",
+          "indexed": false
+        }
+      ],
+      "anonymous": false
+    },
+    {
+      "type": "event",
+      "name": "RewardAdded",
+      "inputs": [
+        {
+          "name": "reward",
+          "type": "uint256",
+          "internalType": "uint256",
+          "indexed": false
+        }
+      ],
+      "anonymous": false
+    },
+    {
+      "type": "event",
+      "name": "RewardContractSet",
+      "inputs": [
+        {
+          "name": "rewardContract",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        }
+      ],
+      "anonymous": false
+    },
+    {
+      "type": "event",
+      "name": "RewardDistributorSet",
+      "inputs": [
+        {
+          "name": "distributor",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        }
+      ],
+      "anonymous": false
+    },
+    {
+      "type": "event",
+      "name": "RewardPaid",
+      "inputs": [
+        {
+          "name": "sender",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        },
+        {
+          "name": "stakingProvider",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        },
+        {
+          "name": "beneficiary",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        },
+        {
+          "name": "reward",
+          "type": "uint256",
+          "internalType": "uint256",
+          "indexed": false
+        }
+      ],
+      "anonymous": false
+    },
+    {
+      "type": "event",
+      "name": "RewardReset",
+      "inputs": [
+        {
+          "name": "stakingProvider",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        }
+      ],
+      "anonymous": false
+    },
+    {
+      "type": "event",
+      "name": "RewardsWithdrawn",
+      "inputs": [
+        {
+          "name": "stakingProvider",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        },
+        {
+          "name": "amount",
+          "type": "uint96",
+          "internalType": "uint96",
+          "indexed": false
+        }
+      ],
+      "anonymous": false
+    },
+    {
+      "type": "event",
+      "name": "Slashed",
+      "inputs": [
+        {
+          "name": "stakingProvider",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        },
+        {
+          "name": "penalty",
+          "type": "uint256",
+          "internalType": "uint256",
+          "indexed": false
+        },
+        {
+          "name": "investigator",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        },
+        {
+          "name": "reward",
+          "type": "uint256",
+          "internalType": "uint256",
+          "indexed": false
+        }
+      ],
+      "anonymous": false
+    },
+    {
+      "type": "function",
+      "name": "PENALTY_BASE",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint192",
+          "internalType": "uint192"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "REWARD_PER_TOKEN_MULTIPLIER",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint256",
+          "internalType": "uint256"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "adjudicator",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "address",
+          "internalType": "address"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "approveAuthorizationDecrease",
+      "stateMutability": "nonpayable",
+      "inputs": [
+        {
+          "name": "_stakingProvider",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": []
+    },
+    {
+      "type": "function",
+      "name": "authorizationDecreaseRequested",
+      "stateMutability": "nonpayable",
+      "inputs": [
+        {
+          "name": "_stakingProvider",
+          "type": "address",
+          "internalType": "address"
+        },
+        {
+          "name": "_fromAmount",
+          "type": "uint96",
+          "internalType": "uint96"
+        },
+        {
+          "name": "_toAmount",
+          "type": "uint96",
+          "internalType": "uint96"
+        }
+      ],
+      "outputs": []
+    },
+    {
+      "type": "function",
+      "name": "authorizationIncreased",
+      "stateMutability": "nonpayable",
+      "inputs": [
+        {
+          "name": "_stakingProvider",
+          "type": "address",
+          "internalType": "address"
+        },
+        {
+          "name": "_fromAmount",
+          "type": "uint96",
+          "internalType": "uint96"
+        },
+        {
+          "name": "_toAmount",
+          "type": "uint96",
+          "internalType": "uint96"
+        }
+      ],
+      "outputs": []
+    },
+    {
+      "type": "function",
+      "name": "authorizationParameters",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "_minimumAuthorization",
+          "type": "uint96",
+          "internalType": "uint96"
+        },
+        {
+          "name": "authorizationDecreaseDelay",
+          "type": "uint64",
+          "internalType": "uint64"
+        },
+        {
+          "name": "authorizationDecreaseChangePeriod",
+          "type": "uint64",
+          "internalType": "uint64"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "authorizedOverall",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint96",
+          "internalType": "uint96"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "authorizedStake",
+      "stateMutability": "view",
+      "inputs": [
+        {
+          "name": "_stakingProvider",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint96",
+          "internalType": "uint96"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "availableRewards",
+      "stateMutability": "view",
+      "inputs": [
+        {
+          "name": "_stakingProvider",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint96",
+          "internalType": "uint96"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "bondOperator",
+      "stateMutability": "nonpayable",
+      "inputs": [
+        {
+          "name": "_stakingProvider",
+          "type": "address",
+          "internalType": "address"
+        },
+        {
+          "name": "_operator",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": []
+    },
+    {
+      "type": "function",
+      "name": "childApplication",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "address",
+          "internalType": "contract ITACoRootToChild"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "commitmentDeadline",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint64",
+          "internalType": "uint64"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "commitmentDurationOption1",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint64",
+          "internalType": "uint64"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "commitmentDurationOption2",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint64",
+          "internalType": "uint64"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "commitmentDurationOption3",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint64",
+          "internalType": "uint64"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "commitmentDurationOption4",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint64",
+          "internalType": "uint64"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "confirmOperatorAddress",
+      "stateMutability": "nonpayable",
+      "inputs": [
+        {
+          "name": "_operator",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": []
+    },
+    {
+      "type": "function",
+      "name": "deauthorizationDuration",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint256",
+          "internalType": "uint256"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "eligibleStake",
+      "stateMutability": "view",
+      "inputs": [
+        {
+          "name": "_stakingProvider",
+          "type": "address",
+          "internalType": "address"
+        },
+        {
+          "name": "_endDate",
+          "type": "uint256",
+          "internalType": "uint256"
+        }
+      ],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint96",
+          "internalType": "uint96"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "getActiveStakingProviders",
+      "stateMutability": "view",
+      "inputs": [
+        {
+          "name": "_startIndex",
+          "type": "uint256",
+          "internalType": "uint256"
+        },
+        {
+          "name": "_maxStakingProviders",
+          "type": "uint256",
+          "internalType": "uint256"
+        },
+        {
+          "name": "_cohortDuration",
+          "type": "uint32",
+          "internalType": "uint32"
+        }
+      ],
+      "outputs": [
+        {
+          "name": "allAuthorizedTokens",
+          "type": "uint256",
+          "internalType": "uint256"
+        },
+        {
+          "name": "activeStakingProviders",
+          "type": "bytes32[]",
+          "internalType": "bytes32[]"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "getBeneficiary",
+      "stateMutability": "view",
+      "inputs": [
+        {
+          "name": "_stakingProvider",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": [
+        {
+          "name": "beneficiary",
+          "type": "address",
+          "internalType": "address payable"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "getPenalty",
+      "stateMutability": "view",
+      "inputs": [
+        {
+          "name": "_stakingProvider",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": [
+        {
+          "name": "penalty",
+          "type": "uint192",
+          "internalType": "uint192"
+        },
+        {
+          "name": "endPenalty",
+          "type": "uint64",
+          "internalType": "uint64"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "getStakingProvidersLength",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint256",
+          "internalType": "uint256"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "initialize",
+      "stateMutability": "nonpayable",
+      "inputs": [],
+      "outputs": []
+    },
+    {
+      "type": "function",
+      "name": "involuntaryAuthorizationDecrease",
+      "stateMutability": "nonpayable",
+      "inputs": [
+        {
+          "name": "_stakingProvider",
+          "type": "address",
+          "internalType": "address"
+        },
+        {
+          "name": "_fromAmount",
+          "type": "uint96",
+          "internalType": "uint96"
+        },
+        {
+          "name": "_toAmount",
+          "type": "uint96",
+          "internalType": "uint96"
+        }
+      ],
+      "outputs": []
+    },
+    {
+      "type": "function",
+      "name": "isAuthorized",
+      "stateMutability": "view",
+      "inputs": [
+        {
+          "name": "_stakingProvider",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": [
+        {
+          "name": "",
+          "type": "bool",
+          "internalType": "bool"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "isOperatorConfirmed",
+      "stateMutability": "view",
+      "inputs": [
+        {
+          "name": "_operator",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": [
+        {
+          "name": "",
+          "type": "bool",
+          "internalType": "bool"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "lastTimeRewardApplicable",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint256",
+          "internalType": "uint256"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "lastUpdateTime",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint256",
+          "internalType": "uint256"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "makeCommitment",
+      "stateMutability": "nonpayable",
+      "inputs": [
+        {
+          "name": "_stakingProvider",
+          "type": "address",
+          "internalType": "address"
+        },
+        {
+          "name": "_commitmentDuration",
+          "type": "uint64",
+          "internalType": "uint64"
+        }
+      ],
+      "outputs": []
+    },
+    {
+      "type": "function",
+      "name": "manualChildSynchronization",
+      "stateMutability": "nonpayable",
+      "inputs": [
+        {
+          "name": "_stakingProvider",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": []
+    },
+    {
+      "type": "function",
+      "name": "minOperatorSeconds",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint256",
+          "internalType": "uint256"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "minimumAuthorization",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint96",
+          "internalType": "uint96"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "operatorToStakingProvider",
+      "stateMutability": "view",
+      "inputs": [
+        {
+          "name": "_operator",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": [
+        {
+          "name": "",
+          "type": "address",
+          "internalType": "address"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "owner",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "address",
+          "internalType": "address"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "penalize",
+      "stateMutability": "nonpayable",
+      "inputs": [
+        {
+          "name": "_stakingProvider",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": []
+    },
+    {
+      "type": "function",
+      "name": "penaltyDefault",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint192",
+          "internalType": "uint192"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "penaltyDuration",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint256",
+          "internalType": "uint256"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "penaltyIncrement",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint192",
+          "internalType": "uint192"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "pendingAuthorizationDecrease",
+      "stateMutability": "view",
+      "inputs": [
+        {
+          "name": "_stakingProvider",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint96",
+          "internalType": "uint96"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "periodFinish",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint256",
+          "internalType": "uint256"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "pushReward",
+      "stateMutability": "nonpayable",
+      "inputs": [
+        {
+          "name": "_reward",
+          "type": "uint96",
+          "internalType": "uint96"
+        }
+      ],
+      "outputs": []
+    },
+    {
+      "type": "function",
+      "name": "registerOperator",
+      "stateMutability": "nonpayable",
+      "inputs": [
+        {
+          "name": "_operator",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": []
+    },
+    {
+      "type": "function",
+      "name": "remainingAuthorizationDecreaseDelay",
+      "stateMutability": "view",
+      "inputs": [
+        {
+          "name": "_stakingProvider",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint64",
+          "internalType": "uint64"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "renounceOwnership",
+      "stateMutability": "nonpayable",
+      "inputs": [],
+      "outputs": []
+    },
+    {
+      "type": "function",
+      "name": "resetReward",
+      "stateMutability": "nonpayable",
+      "inputs": [
+        {
+          "name": "_stakingProvider",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": []
+    },
+    {
+      "type": "function",
+      "name": "resynchronizeAuthorization",
+      "stateMutability": "nonpayable",
+      "inputs": [
+        {
+          "name": "_stakingProvider",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": []
+    },
+    {
+      "type": "function",
+      "name": "rewardContract",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "address",
+          "internalType": "address"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "rewardDistributor",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "address",
+          "internalType": "address"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "rewardDuration",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint256",
+          "internalType": "uint256"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "rewardPerToken",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint160",
+          "internalType": "uint160"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "rewardPerTokenStored",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint160",
+          "internalType": "uint160"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "rewardRateDecimals",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint256",
+          "internalType": "uint256"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "setAdjudicator",
+      "stateMutability": "nonpayable",
+      "inputs": [
+        {
+          "name": "_adjudicator",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": []
+    },
+    {
+      "type": "function",
+      "name": "setChildApplication",
+      "stateMutability": "nonpayable",
+      "inputs": [
+        {
+          "name": "_childApplication",
+          "type": "address",
+          "internalType": "contract ITACoRootToChild"
+        }
+      ],
+      "outputs": []
+    },
+    {
+      "type": "function",
+      "name": "setRewardContract",
+      "stateMutability": "nonpayable",
+      "inputs": [
+        {
+          "name": "_rewardContract",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": []
+    },
+    {
+      "type": "function",
+      "name": "setRewardDistributor",
+      "stateMutability": "nonpayable",
+      "inputs": [
+        {
+          "name": "_rewardDistributor",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": []
+    },
+    {
+      "type": "function",
+      "name": "slash",
+      "stateMutability": "nonpayable",
+      "inputs": [
+        {
+          "name": "_stakingProvider",
+          "type": "address",
+          "internalType": "address"
+        },
+        {
+          "name": "_penalty",
+          "type": "uint96",
+          "internalType": "uint96"
+        },
+        {
+          "name": "_investigator",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": []
+    },
+    {
+      "type": "function",
+      "name": "stakingProviderInfo",
+      "stateMutability": "view",
+      "inputs": [
+        {
+          "name": "",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": [
+        {
+          "name": "operator",
+          "type": "address",
+          "internalType": "address"
+        },
+        {
+          "name": "operatorConfirmed",
+          "type": "bool",
+          "internalType": "bool"
+        },
+        {
+          "name": "operatorStartTimestamp",
+          "type": "uint64",
+          "internalType": "uint64"
+        },
+        {
+          "name": "authorized",
+          "type": "uint96",
+          "internalType": "uint96"
+        },
+        {
+          "name": "deauthorizing",
+          "type": "uint96",
+          "internalType": "uint96"
+        },
+        {
+          "name": "endDeauthorization",
+          "type": "uint64",
+          "internalType": "uint64"
+        },
+        {
+          "name": "tReward",
+          "type": "uint96",
+          "internalType": "uint96"
+        },
+        {
+          "name": "rewardPerTokenPaid",
+          "type": "uint160",
+          "internalType": "uint160"
+        },
+        {
+          "name": "endCommitment",
+          "type": "uint64",
+          "internalType": "uint64"
+        },
+        {
+          "name": "stub",
+          "type": "uint256",
+          "internalType": "uint256"
+        },
+        {
+          "name": "penaltyPercent",
+          "type": "uint192",
+          "internalType": "uint192"
+        },
+        {
+          "name": "endPenalty",
+          "type": "uint64",
+          "internalType": "uint64"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "stakingProviderToOperator",
+      "stateMutability": "view",
+      "inputs": [
+        {
+          "name": "_stakingProvider",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": [
+        {
+          "name": "",
+          "type": "address",
+          "internalType": "address"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "stakingProviders",
+      "stateMutability": "view",
+      "inputs": [
+        {
+          "name": "",
+          "type": "uint256",
+          "internalType": "uint256"
+        }
+      ],
+      "outputs": [
+        {
+          "name": "",
+          "type": "address",
+          "internalType": "address"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "tStaking",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "address",
+          "internalType": "contract IStaking"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "token",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "address",
+          "internalType": "contract IERC20"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "transferOwnership",
+      "stateMutability": "nonpayable",
+      "inputs": [
+        {
+          "name": "newOwner",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": []
+    },
+    {
+      "type": "function",
+      "name": "withdrawRewards",
+      "stateMutability": "nonpayable",
+      "inputs": [
+        {
+          "name": "_stakingProvider",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": []
+    }
+  ],
+  "tx_hash": "0x178f50155caea7bb32dab5cd79280c66d19a52aa2d303174fa9f5d843ba2ea91",
+  "block_number": 20410589,
+  "deployer": "0xFfFd7092685bDeeBD121D1A0FEA3c349114Cce50"
+}
diff --git a/src/threshold-ts/mas/sepolia-artifacts/TacoRegistry.json b/src/threshold-ts/mas/sepolia-artifacts/TacoRegistry.json
new file mode 100644
index 000000000..968c9536e
--- /dev/null
+++ b/src/threshold-ts/mas/sepolia-artifacts/TacoRegistry.json
@@ -0,0 +1,1431 @@
+{
+  "address": "0xCcFf527698E78a536d80695D9Af4F4f3265ADA05",
+  "abi": [
+    {
+      "type": "constructor",
+      "stateMutability": "nonpayable",
+      "inputs": [
+        {
+          "name": "_token",
+          "type": "address",
+          "internalType": "contract IERC20"
+        },
+        {
+          "name": "_tStaking",
+          "type": "address",
+          "internalType": "contract IStaking"
+        },
+        {
+          "name": "_minimumAuthorization",
+          "type": "uint96",
+          "internalType": "uint96"
+        },
+        {
+          "name": "_minOperatorSeconds",
+          "type": "uint256",
+          "internalType": "uint256"
+        },
+        {
+          "name": "_rewardDuration",
+          "type": "uint256",
+          "internalType": "uint256"
+        },
+        {
+          "name": "_deauthorizationDuration",
+          "type": "uint256",
+          "internalType": "uint256"
+        },
+        {
+          "name": "_commitmentDurationOptions",
+          "type": "uint64[]",
+          "internalType": "uint64[]"
+        },
+        {
+          "name": "_commitmentDeadline",
+          "type": "uint64",
+          "internalType": "uint64"
+        }
+      ]
+    },
+    {
+      "type": "error",
+      "name": "AddressEmptyCode",
+      "inputs": [
+        {
+          "name": "target",
+          "type": "address",
+          "internalType": "address"
+        }
+      ]
+    },
+    {
+      "type": "error",
+      "name": "AddressInsufficientBalance",
+      "inputs": [
+        {
+          "name": "account",
+          "type": "address",
+          "internalType": "address"
+        }
+      ]
+    },
+    {
+      "type": "error",
+      "name": "FailedInnerCall",
+      "inputs": []
+    },
+    {
+      "type": "error",
+      "name": "InvalidInitialization",
+      "inputs": []
+    },
+    {
+      "type": "error",
+      "name": "NotInitializing",
+      "inputs": []
+    },
+    {
+      "type": "error",
+      "name": "OwnableInvalidOwner",
+      "inputs": [
+        {
+          "name": "owner",
+          "type": "address",
+          "internalType": "address"
+        }
+      ]
+    },
+    {
+      "type": "error",
+      "name": "OwnableUnauthorizedAccount",
+      "inputs": [
+        {
+          "name": "account",
+          "type": "address",
+          "internalType": "address"
+        }
+      ]
+    },
+    {
+      "type": "error",
+      "name": "SafeCastOverflowedUintDowncast",
+      "inputs": [
+        {
+          "name": "bits",
+          "type": "uint8",
+          "internalType": "uint8"
+        },
+        {
+          "name": "value",
+          "type": "uint256",
+          "internalType": "uint256"
+        }
+      ]
+    },
+    {
+      "type": "error",
+      "name": "SafeERC20FailedOperation",
+      "inputs": [
+        {
+          "name": "token",
+          "type": "address",
+          "internalType": "address"
+        }
+      ]
+    },
+    {
+      "type": "event",
+      "name": "AuthorizationDecreaseApproved",
+      "inputs": [
+        {
+          "name": "stakingProvider",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        },
+        {
+          "name": "fromAmount",
+          "type": "uint96",
+          "internalType": "uint96",
+          "indexed": false
+        },
+        {
+          "name": "toAmount",
+          "type": "uint96",
+          "internalType": "uint96",
+          "indexed": false
+        }
+      ],
+      "anonymous": false
+    },
+    {
+      "type": "event",
+      "name": "AuthorizationDecreaseRequested",
+      "inputs": [
+        {
+          "name": "stakingProvider",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        },
+        {
+          "name": "fromAmount",
+          "type": "uint96",
+          "internalType": "uint96",
+          "indexed": false
+        },
+        {
+          "name": "toAmount",
+          "type": "uint96",
+          "internalType": "uint96",
+          "indexed": false
+        }
+      ],
+      "anonymous": false
+    },
+    {
+      "type": "event",
+      "name": "AuthorizationIncreased",
+      "inputs": [
+        {
+          "name": "stakingProvider",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        },
+        {
+          "name": "fromAmount",
+          "type": "uint96",
+          "internalType": "uint96",
+          "indexed": false
+        },
+        {
+          "name": "toAmount",
+          "type": "uint96",
+          "internalType": "uint96",
+          "indexed": false
+        }
+      ],
+      "anonymous": false
+    },
+    {
+      "type": "event",
+      "name": "AuthorizationInvoluntaryDecreased",
+      "inputs": [
+        {
+          "name": "stakingProvider",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        },
+        {
+          "name": "fromAmount",
+          "type": "uint96",
+          "internalType": "uint96",
+          "indexed": false
+        },
+        {
+          "name": "toAmount",
+          "type": "uint96",
+          "internalType": "uint96",
+          "indexed": false
+        }
+      ],
+      "anonymous": false
+    },
+    {
+      "type": "event",
+      "name": "AuthorizationReSynchronized",
+      "inputs": [
+        {
+          "name": "stakingProvider",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        },
+        {
+          "name": "fromAmount",
+          "type": "uint96",
+          "internalType": "uint96",
+          "indexed": false
+        },
+        {
+          "name": "toAmount",
+          "type": "uint96",
+          "internalType": "uint96",
+          "indexed": false
+        }
+      ],
+      "anonymous": false
+    },
+    {
+      "type": "event",
+      "name": "CommitmentMade",
+      "inputs": [
+        {
+          "name": "stakingProvider",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        },
+        {
+          "name": "endCommitment",
+          "type": "uint256",
+          "internalType": "uint256",
+          "indexed": false
+        }
+      ],
+      "anonymous": false
+    },
+    {
+      "type": "event",
+      "name": "Initialized",
+      "inputs": [
+        {
+          "name": "version",
+          "type": "uint64",
+          "internalType": "uint64",
+          "indexed": false
+        }
+      ],
+      "anonymous": false
+    },
+    {
+      "type": "event",
+      "name": "ManualChildSynchronizationSent",
+      "inputs": [
+        {
+          "name": "stakingProvider",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        },
+        {
+          "name": "authorized",
+          "type": "uint96",
+          "internalType": "uint96",
+          "indexed": false
+        },
+        {
+          "name": "deauthorizing",
+          "type": "uint96",
+          "internalType": "uint96",
+          "indexed": false
+        },
+        {
+          "name": "endDeauthorization",
+          "type": "uint64",
+          "internalType": "uint64",
+          "indexed": false
+        },
+        {
+          "name": "operator",
+          "type": "address",
+          "internalType": "address",
+          "indexed": false
+        }
+      ],
+      "anonymous": false
+    },
+    {
+      "type": "event",
+      "name": "OperatorBonded",
+      "inputs": [
+        {
+          "name": "stakingProvider",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        },
+        {
+          "name": "operator",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        },
+        {
+          "name": "previousOperator",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        },
+        {
+          "name": "startTimestamp",
+          "type": "uint256",
+          "internalType": "uint256",
+          "indexed": false
+        }
+      ],
+      "anonymous": false
+    },
+    {
+      "type": "event",
+      "name": "OperatorConfirmed",
+      "inputs": [
+        {
+          "name": "stakingProvider",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        },
+        {
+          "name": "operator",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        }
+      ],
+      "anonymous": false
+    },
+    {
+      "type": "event",
+      "name": "OwnershipTransferred",
+      "inputs": [
+        {
+          "name": "previousOwner",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        },
+        {
+          "name": "newOwner",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        }
+      ],
+      "anonymous": false
+    },
+    {
+      "type": "event",
+      "name": "RewardAdded",
+      "inputs": [
+        {
+          "name": "reward",
+          "type": "uint256",
+          "internalType": "uint256",
+          "indexed": false
+        }
+      ],
+      "anonymous": false
+    },
+    {
+      "type": "event",
+      "name": "RewardDistributorSet",
+      "inputs": [
+        {
+          "name": "distributor",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        }
+      ],
+      "anonymous": false
+    },
+    {
+      "type": "event",
+      "name": "RewardPaid",
+      "inputs": [
+        {
+          "name": "stakingProvider",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        },
+        {
+          "name": "beneficiary",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        },
+        {
+          "name": "reward",
+          "type": "uint256",
+          "internalType": "uint256",
+          "indexed": false
+        }
+      ],
+      "anonymous": false
+    },
+    {
+      "type": "event",
+      "name": "RewardsWithdrawn",
+      "inputs": [
+        {
+          "name": "stakingProvider",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        },
+        {
+          "name": "amount",
+          "type": "uint96",
+          "internalType": "uint96",
+          "indexed": false
+        }
+      ],
+      "anonymous": false
+    },
+    {
+      "type": "event",
+      "name": "Slashed",
+      "inputs": [
+        {
+          "name": "stakingProvider",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        },
+        {
+          "name": "penalty",
+          "type": "uint256",
+          "internalType": "uint256",
+          "indexed": false
+        },
+        {
+          "name": "investigator",
+          "type": "address",
+          "internalType": "address",
+          "indexed": true
+        },
+        {
+          "name": "reward",
+          "type": "uint256",
+          "internalType": "uint256",
+          "indexed": false
+        }
+      ],
+      "anonymous": false
+    },
+    {
+      "type": "function",
+      "name": "REWARD_PER_TOKEN_MULTIPLIER",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint256",
+          "internalType": "uint256"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "adjudicator",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "address",
+          "internalType": "address"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "approveAuthorizationDecrease",
+      "stateMutability": "nonpayable",
+      "inputs": [
+        {
+          "name": "_stakingProvider",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": []
+    },
+    {
+      "type": "function",
+      "name": "authorizationDecreaseRequested",
+      "stateMutability": "nonpayable",
+      "inputs": [
+        {
+          "name": "_stakingProvider",
+          "type": "address",
+          "internalType": "address"
+        },
+        {
+          "name": "_fromAmount",
+          "type": "uint96",
+          "internalType": "uint96"
+        },
+        {
+          "name": "_toAmount",
+          "type": "uint96",
+          "internalType": "uint96"
+        }
+      ],
+      "outputs": []
+    },
+    {
+      "type": "function",
+      "name": "authorizationIncreased",
+      "stateMutability": "nonpayable",
+      "inputs": [
+        {
+          "name": "_stakingProvider",
+          "type": "address",
+          "internalType": "address"
+        },
+        {
+          "name": "_fromAmount",
+          "type": "uint96",
+          "internalType": "uint96"
+        },
+        {
+          "name": "_toAmount",
+          "type": "uint96",
+          "internalType": "uint96"
+        }
+      ],
+      "outputs": []
+    },
+    {
+      "type": "function",
+      "name": "authorizationParameters",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "_minimumAuthorization",
+          "type": "uint96",
+          "internalType": "uint96"
+        },
+        {
+          "name": "authorizationDecreaseDelay",
+          "type": "uint64",
+          "internalType": "uint64"
+        },
+        {
+          "name": "authorizationDecreaseChangePeriod",
+          "type": "uint64",
+          "internalType": "uint64"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "authorizedOverall",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint96",
+          "internalType": "uint96"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "authorizedStake",
+      "stateMutability": "view",
+      "inputs": [
+        {
+          "name": "_stakingProvider",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint96",
+          "internalType": "uint96"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "availableRewards",
+      "stateMutability": "view",
+      "inputs": [
+        {
+          "name": "_stakingProvider",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint96",
+          "internalType": "uint96"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "bondOperator",
+      "stateMutability": "nonpayable",
+      "inputs": [
+        {
+          "name": "_stakingProvider",
+          "type": "address",
+          "internalType": "address"
+        },
+        {
+          "name": "_operator",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": []
+    },
+    {
+      "type": "function",
+      "name": "childApplication",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "address",
+          "internalType": "contract ITACoRootToChild"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "commitmentDeadline",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint64",
+          "internalType": "uint64"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "commitmentDurationOption1",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint64",
+          "internalType": "uint64"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "commitmentDurationOption2",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint64",
+          "internalType": "uint64"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "commitmentDurationOption3",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint64",
+          "internalType": "uint64"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "commitmentDurationOption4",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint64",
+          "internalType": "uint64"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "confirmOperatorAddress",
+      "stateMutability": "nonpayable",
+      "inputs": [
+        {
+          "name": "_operator",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": []
+    },
+    {
+      "type": "function",
+      "name": "deauthorizationDuration",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint256",
+          "internalType": "uint256"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "eligibleStake",
+      "stateMutability": "view",
+      "inputs": [
+        {
+          "name": "_stakingProvider",
+          "type": "address",
+          "internalType": "address"
+        },
+        {
+          "name": "_endDate",
+          "type": "uint256",
+          "internalType": "uint256"
+        }
+      ],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint96",
+          "internalType": "uint96"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "getActiveStakingProviders",
+      "stateMutability": "view",
+      "inputs": [
+        {
+          "name": "_startIndex",
+          "type": "uint256",
+          "internalType": "uint256"
+        },
+        {
+          "name": "_maxStakingProviders",
+          "type": "uint256",
+          "internalType": "uint256"
+        },
+        {
+          "name": "_cohortDuration",
+          "type": "uint32",
+          "internalType": "uint32"
+        }
+      ],
+      "outputs": [
+        {
+          "name": "allAuthorizedTokens",
+          "type": "uint256",
+          "internalType": "uint256"
+        },
+        {
+          "name": "activeStakingProviders",
+          "type": "bytes32[]",
+          "internalType": "bytes32[]"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "getBeneficiary",
+      "stateMutability": "view",
+      "inputs": [
+        {
+          "name": "_stakingProvider",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": [
+        {
+          "name": "beneficiary",
+          "type": "address",
+          "internalType": "address payable"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "getStakingProvidersLength",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint256",
+          "internalType": "uint256"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "initialize",
+      "stateMutability": "nonpayable",
+      "inputs": [],
+      "outputs": []
+    },
+    {
+      "type": "function",
+      "name": "involuntaryAuthorizationDecrease",
+      "stateMutability": "nonpayable",
+      "inputs": [
+        {
+          "name": "_stakingProvider",
+          "type": "address",
+          "internalType": "address"
+        },
+        {
+          "name": "_fromAmount",
+          "type": "uint96",
+          "internalType": "uint96"
+        },
+        {
+          "name": "_toAmount",
+          "type": "uint96",
+          "internalType": "uint96"
+        }
+      ],
+      "outputs": []
+    },
+    {
+      "type": "function",
+      "name": "isAuthorized",
+      "stateMutability": "view",
+      "inputs": [
+        {
+          "name": "_stakingProvider",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": [
+        {
+          "name": "",
+          "type": "bool",
+          "internalType": "bool"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "isOperatorConfirmed",
+      "stateMutability": "view",
+      "inputs": [
+        {
+          "name": "_operator",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": [
+        {
+          "name": "",
+          "type": "bool",
+          "internalType": "bool"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "lastTimeRewardApplicable",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint256",
+          "internalType": "uint256"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "lastUpdateTime",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint256",
+          "internalType": "uint256"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "makeCommitment",
+      "stateMutability": "nonpayable",
+      "inputs": [
+        {
+          "name": "_stakingProvider",
+          "type": "address",
+          "internalType": "address"
+        },
+        {
+          "name": "_commitmentDuration",
+          "type": "uint64",
+          "internalType": "uint64"
+        }
+      ],
+      "outputs": []
+    },
+    {
+      "type": "function",
+      "name": "manualChildSynchronization",
+      "stateMutability": "nonpayable",
+      "inputs": [
+        {
+          "name": "_stakingProvider",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": []
+    },
+    {
+      "type": "function",
+      "name": "minOperatorSeconds",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint256",
+          "internalType": "uint256"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "minimumAuthorization",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint96",
+          "internalType": "uint96"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "operatorToStakingProvider",
+      "stateMutability": "view",
+      "inputs": [
+        {
+          "name": "_operator",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": [
+        {
+          "name": "",
+          "type": "address",
+          "internalType": "address"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "owner",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "address",
+          "internalType": "address"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "pendingAuthorizationDecrease",
+      "stateMutability": "view",
+      "inputs": [
+        {
+          "name": "_stakingProvider",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint96",
+          "internalType": "uint96"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "periodFinish",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint256",
+          "internalType": "uint256"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "pushReward",
+      "stateMutability": "nonpayable",
+      "inputs": [
+        {
+          "name": "_reward",
+          "type": "uint96",
+          "internalType": "uint96"
+        }
+      ],
+      "outputs": []
+    },
+    {
+      "type": "function",
+      "name": "registerOperator",
+      "stateMutability": "nonpayable",
+      "inputs": [
+        {
+          "name": "_operator",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": []
+    },
+    {
+      "type": "function",
+      "name": "remainingAuthorizationDecreaseDelay",
+      "stateMutability": "view",
+      "inputs": [
+        {
+          "name": "_stakingProvider",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint64",
+          "internalType": "uint64"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "renounceOwnership",
+      "stateMutability": "nonpayable",
+      "inputs": [],
+      "outputs": []
+    },
+    {
+      "type": "function",
+      "name": "resynchronizeAuthorization",
+      "stateMutability": "nonpayable",
+      "inputs": [
+        {
+          "name": "_stakingProvider",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": []
+    },
+    {
+      "type": "function",
+      "name": "rewardDistributor",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "address",
+          "internalType": "address"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "rewardDuration",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint256",
+          "internalType": "uint256"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "rewardPerToken",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint160",
+          "internalType": "uint160"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "rewardPerTokenStored",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint160",
+          "internalType": "uint160"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "rewardRateDecimals",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "uint256",
+          "internalType": "uint256"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "setAdjudicator",
+      "stateMutability": "nonpayable",
+      "inputs": [
+        {
+          "name": "_adjudicator",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": []
+    },
+    {
+      "type": "function",
+      "name": "setChildApplication",
+      "stateMutability": "nonpayable",
+      "inputs": [
+        {
+          "name": "_childApplication",
+          "type": "address",
+          "internalType": "contract ITACoRootToChild"
+        }
+      ],
+      "outputs": []
+    },
+    {
+      "type": "function",
+      "name": "setRewardDistributor",
+      "stateMutability": "nonpayable",
+      "inputs": [
+        {
+          "name": "_rewardDistributor",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": []
+    },
+    {
+      "type": "function",
+      "name": "slash",
+      "stateMutability": "nonpayable",
+      "inputs": [
+        {
+          "name": "_stakingProvider",
+          "type": "address",
+          "internalType": "address"
+        },
+        {
+          "name": "_penalty",
+          "type": "uint96",
+          "internalType": "uint96"
+        },
+        {
+          "name": "_investigator",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": []
+    },
+    {
+      "type": "function",
+      "name": "stakingProviderInfo",
+      "stateMutability": "view",
+      "inputs": [
+        {
+          "name": "",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": [
+        {
+          "name": "operator",
+          "type": "address",
+          "internalType": "address"
+        },
+        {
+          "name": "operatorConfirmed",
+          "type": "bool",
+          "internalType": "bool"
+        },
+        {
+          "name": "operatorStartTimestamp",
+          "type": "uint64",
+          "internalType": "uint64"
+        },
+        {
+          "name": "authorized",
+          "type": "uint96",
+          "internalType": "uint96"
+        },
+        {
+          "name": "deauthorizing",
+          "type": "uint96",
+          "internalType": "uint96"
+        },
+        {
+          "name": "endDeauthorization",
+          "type": "uint64",
+          "internalType": "uint64"
+        },
+        {
+          "name": "tReward",
+          "type": "uint96",
+          "internalType": "uint96"
+        },
+        {
+          "name": "rewardPerTokenPaid",
+          "type": "uint160",
+          "internalType": "uint160"
+        },
+        {
+          "name": "endCommitment",
+          "type": "uint64",
+          "internalType": "uint64"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "stakingProviderToOperator",
+      "stateMutability": "view",
+      "inputs": [
+        {
+          "name": "_stakingProvider",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": [
+        {
+          "name": "",
+          "type": "address",
+          "internalType": "address"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "stakingProviders",
+      "stateMutability": "view",
+      "inputs": [
+        {
+          "name": "",
+          "type": "uint256",
+          "internalType": "uint256"
+        }
+      ],
+      "outputs": [
+        {
+          "name": "",
+          "type": "address",
+          "internalType": "address"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "tStaking",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "address",
+          "internalType": "contract IStaking"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "token",
+      "stateMutability": "view",
+      "inputs": [],
+      "outputs": [
+        {
+          "name": "",
+          "type": "address",
+          "internalType": "contract IERC20"
+        }
+      ]
+    },
+    {
+      "type": "function",
+      "name": "transferOwnership",
+      "stateMutability": "nonpayable",
+      "inputs": [
+        {
+          "name": "newOwner",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": []
+    },
+    {
+      "type": "function",
+      "name": "withdrawRewards",
+      "stateMutability": "nonpayable",
+      "inputs": [
+        {
+          "name": "_stakingProvider",
+          "type": "address",
+          "internalType": "address"
+        }
+      ],
+      "outputs": []
+    }
+  ],
+  "tx_hash": "0x4824e7d3b6dae9ec69b79b9f0578853c51fd92a49b0edce45d892d6cdf7901bd",
+  "block_number": 5048617,
+  "deployer": "0x3B42d26E19FF860bC4dEbB920DD8caA53F93c600"
+}
diff --git a/src/web3/hooks/useNuStakingEscrowContract.ts b/src/web3/hooks/useNuStakingEscrowContract.ts
index df0755000..976acadfe 100644
--- a/src/web3/hooks/useNuStakingEscrowContract.ts
+++ b/src/web3/hooks/useNuStakingEscrowContract.ts
@@ -3,5 +3,5 @@ import { useThreshold } from "../../contexts/ThresholdContext"
 export const useNuStakingEscrowContract = () => {
   const threshold = useThreshold()
 
-  return threshold.staking.legacyNuStakingContract
+  return threshold.staking!.legacyNuStakingContract
 }

From 2cd71d1b419b486f7e3a534b2a0797fc03b58aa5 Mon Sep 17 00:00:00 2001
From: evandrosaturnino <evandro.saturnino@gmail.com>
Date: Thu, 12 Dec 2024 22:12:50 -0300
Subject: [PATCH 42/46] implements generic rpc service support

---
 .env.example                                  |  3 +-
 .env.production                               |  3 +-
 .env.test                                     |  1 +
 .github/workflows/dashboard-ci.yml            | 12 ++-
 .github/workflows/dashboard-mainnet.yml       |  6 +-
 .../workflows/reusable-build-and-publish.yml  | 13 +++-
 README.md                                     |  6 +-
 src/enums/env.ts                              |  5 +-
 src/networks/README.md                        | 78 +++++++------------
 src/networks/constants/networks.ts            |  2 +
 src/networks/enums/networks.ts                | 18 ++++-
 src/networks/types/networks.ts                | 19 ++---
 src/networks/utils/connectedNetwork.ts        |  4 +-
 ...rkName.ts => getNetworkNameFromChainId.ts} |  5 +-
 src/networks/utils/getRpcEndpointUrl.ts       | 30 +++++++
 src/networks/utils/getRpcNetworkConfig.ts     | 36 +++++++++
 src/networks/utils/getRpcUrl.ts               | 17 ----
 src/networks/utils/index.ts                   |  5 +-
 src/networks/utils/networks.ts                | 30 ++-----
 src/networks/utils/networksAlchemyConfig.ts   | 29 -------
 src/pages/tBTC/Bridge/Minting/ProvideData.tsx |  4 +-
 src/store/tbtc/effects.ts                     |  4 +-
 src/threshold-ts/tbtc/index.ts                | 14 ++--
 src/utils/getThresholdLib.ts                  |  5 +-
 src/web3/connectors/coinbaseWallet.ts         |  4 +-
 src/web3/connectors/ledgerLive.ts             | 13 ++--
 src/web3/connectors/walletConnect.ts          |  8 +-
 src/web3/hooks/__tests__/useContract.test.ts  |  4 +-
 28 files changed, 198 insertions(+), 180 deletions(-)
 rename src/networks/utils/{getChainIdToNetworkName.ts => getNetworkNameFromChainId.ts} (72%)
 create mode 100644 src/networks/utils/getRpcEndpointUrl.ts
 create mode 100644 src/networks/utils/getRpcNetworkConfig.ts
 delete mode 100644 src/networks/utils/getRpcUrl.ts
 delete mode 100644 src/networks/utils/networksAlchemyConfig.ts

diff --git a/.env.example b/.env.example
index 9e876f45b..68c1a9d5a 100644
--- a/.env.example
+++ b/.env.example
@@ -1,5 +1,6 @@
 REACT_APP_DEFAULT_PROVIDER_CHAIN_ID=1337
-REACT_APP_ALCHEMY_API=$ALCHEMY_API
+REACT_APP_RPC_SERVICE_API=$RPC_SERVICE_API
+REACT_APP_RPC_SERVICE_NAME=$RPC_SERVICE_NAME
 REACT_APP_MULTICALL_ADDRESS=$MULTICALL_ADDRESS
 REACT_APP_DAPP_DEVELOPMENT_TESTNET_CONTRACTS=$DAPP_DEVELOPMENT_TESTNET_CONTRACTS
 
diff --git a/.env.production b/.env.production
index 745dc37e7..5f5b189a2 100644
--- a/.env.production
+++ b/.env.production
@@ -1,5 +1,6 @@
 REACT_APP_DEFAULT_PROVIDER_CHAIN_ID=$CHAIN_ID
-REACT_APP_ALCHEMY_API=$ALCHEMY_API
+REACT_APP_RPC_SERVICE_API=$RPC_SERVICE_API
+REACT_APP_RPC_SERVICE_NAME=$RPC_SERVICE_NAME
 REACT_APP_DAPP_DEVELOPMENT_TESTNET_CONTRACTS=$DAPP_DEVELOPMENT_TESTNET_CONTRACTS
 
 REACT_APP_FEATURE_FLAG_TBTC_V2=true
diff --git a/.env.test b/.env.test
index ccece28fe..1e0d1bc93 100644
--- a/.env.test
+++ b/.env.test
@@ -1,3 +1,4 @@
 REACT_APP_DEFAULT_PROVIDER_CHAIN_ID=1337
 REACT_APP_MULTICALL_ADDRESS=0xcA11bde05977b3631167028862bE2a173976CA11
+REACT_APP_RPC_SERVICE_NAME=alchemy
 REACT_APP_TACO_DOMAIN=dashboard
\ No newline at end of file
diff --git a/.github/workflows/dashboard-ci.yml b/.github/workflows/dashboard-ci.yml
index 3c52b07eb..0f740f9b4 100644
--- a/.github/workflows/dashboard-ci.yml
+++ b/.github/workflows/dashboard-ci.yml
@@ -87,7 +87,8 @@ jobs:
         env:
           PUBLIC_URL: /${{ github.head_ref }}
           DEFAULT_PROVIDER_CHAIN_ID: 11155111
-          ALCHEMY_API: ${{ secrets.ALCHEMY_API }}
+          RPC_SERVICE_API: ${{ secrets.RPC_SERVICE_API }}
+          RPC_SERVICE_NAME: ${{ secrets.RPC_SERVICE_NAME }}
           NODE_OPTIONS: --max_old_space_size=4096
           MAINNET_ELECTRUM_PROTOCOL: ${{ secrets.MAINNET_ELECTRUMX_PROTOCOL }}
           MAINNET_ELECTRUM_HOST: ${{ secrets.MAINNET_ELECTRUMX_HOST }}
@@ -124,7 +125,8 @@ jobs:
       gcpBucketPath: ${{ github.head_ref }}
       preview: true
     secrets:
-      alchemyApi: ${{ secrets.ALCHEMY_API }}
+      rpcServiceApi: ${{ secrets.RPC_SERVICE_API }}
+      rpcServiceName: ${{ secrets.RPC_SERVICE_NAME }}
       gcpServiceKey: ${{ secrets.KEEP_TEST_CI_UPLOAD_DAPP_JSON_KEY_BASE64 }}
       electrumProtocol: ${{ secrets.TESTNET_ELECTRUMX_PROTOCOL }}
       electrumHost: ${{ secrets.TESTNET_ELECTRUMX_HOST }}
@@ -155,7 +157,8 @@ jobs:
       gcpBucketName: dashboard.test.threshold.network
       preview: false
     secrets:
-      alchemyApi: ${{ secrets.ALCHEMY_API }}
+      rpcServiceApi: ${{ secrets.RPC_SERVICE_API }}
+      rpcServiceName: ${{ secrets.RPC_SERVICE_NAME }}
       gcpServiceKey: ${{ secrets.KEEP_TEST_CI_UPLOAD_DAPP_JSON_KEY_BASE64 }}
       electrumProtocol: ${{ secrets.TESTNET_ELECTRUMX_PROTOCOL }}
       electrumHost: ${{ secrets.TESTNET_ELECTRUMX_HOST }}
@@ -181,7 +184,8 @@ jobs:
       gcpBucketName: dashboard.test.threshold.network
       preview: false
     secrets:
-      alchemyApi: ${{ secrets.ALCHEMY_API }}
+      rpcServiceApi: ${{ secrets.RPC_SERVICE_API }}
+      rpcServiceName: ${{ secrets.RPC_SERVICE_NAME }}
       gcpServiceKey: ${{ secrets.KEEP_TEST_CI_UPLOAD_DAPP_JSON_KEY_BASE64 }}
       electrumProtocol: ${{ secrets.TESTNET_ELECTRUMX_PROTOCOL }}
       electrumHost: ${{ secrets.TESTNET_ELECTRUMX_HOST }}
diff --git a/.github/workflows/dashboard-mainnet.yml b/.github/workflows/dashboard-mainnet.yml
index 94a3c2ebc..cf31e06a1 100644
--- a/.github/workflows/dashboard-mainnet.yml
+++ b/.github/workflows/dashboard-mainnet.yml
@@ -49,7 +49,8 @@ jobs:
         env:
           PUBLIC_URL: /${{ github.ref_name }}
           DEFAULT_PROVIDER_CHAIN_ID: 1
-          ALCHEMY_API: ${{ secrets.ALCHEMY_API }}
+          RPC_SERVICE_API: ${{ secrets.RPC_SERVICE_API }}
+          RPC_SERVICE_NAME: ${{ secrets.RPC_SERVICE_NAME }}
           NODE_OPTIONS: --max_old_space_size=4096
           MAINNET_ELECTRUM_PROTOCOL: ${{ secrets.MAINNET_ELECTRUMX_PROTOCOL }}
           MAINNET_ELECTRUM_HOST: ${{ secrets.MAINNET_ELECTRUMX_HOST }}
@@ -71,7 +72,8 @@ jobs:
         env:
           PUBLIC_URL: /
           DEFAULT_PROVIDER_CHAIN_ID: 1
-          ALCHEMY_API: ${{ secrets.ALCHEMY_API }}
+          RPC_SERVICE_API: ${{ secrets.RPC_SERVICE_API }}
+          RPC_SERVICE_NAME: ${{ secrets.RPC_SERVICE_NAME }}
           NODE_OPTIONS: --max_old_space_size=4096
           POSTHOG_SUPPORT: true
           POSTHOG_API_KEY: ${{ secrets.MAINNET_POSTHOG_API_KEY }}
diff --git a/.github/workflows/reusable-build-and-publish.yml b/.github/workflows/reusable-build-and-publish.yml
index bc1579df5..575f388dd 100644
--- a/.github/workflows/reusable-build-and-publish.yml
+++ b/.github/workflows/reusable-build-and-publish.yml
@@ -49,8 +49,11 @@ on:
         default: false
         type: boolean
     secrets:
-      alchemyApi:
-        description: The Alchemy API Key.
+      rpcServiceApi:
+        description: The RPC service API Key.
+        required: true
+      rpcServiceName:
+        description: The RPC service name.
         required: true
       gcpServiceKey:
         description: JSON key for Google Cloud Platform service account.
@@ -162,7 +165,8 @@ jobs:
         env:
           PUBLIC_URL: /
           DEFAULT_PROVIDER_CHAIN_ID: ${{ env.NETWORK_ID }}
-          ALCHEMY_API: ${{ secrets.alchemyApi }}
+          RPC_SERVICE_API: ${{ secrets.rpcServiceApi }}
+          RPC_SERVICE_NAME: ${{ secrets.rpcServiceName }}
           NODE_OPTIONS: --max_old_space_size=4096
           MAINNET_ELECTRUM_PROTOCOL: ${{ secrets.mainnetElectrumProtocol }}
           MAINNET_ELECTRUM_HOST: ${{ secrets.mainnetElectrumHost }}
@@ -183,7 +187,8 @@ jobs:
         env:
           PUBLIC_URL: /${{ inputs.gcpBucketPath }}
           DEFAULT_PROVIDER_CHAIN_ID: ${{ env.NETWORK_ID }}
-          ALCHEMY_API: ${{ secrets.alchemyApi }}
+          RPC_SERVICE_API: ${{ secrets.rpcServiceApi }}
+          RPC_SERVICE_NAME: ${{ secrets.rpcServiceName }}
           NODE_OPTIONS: --max_old_space_size=4096
           MAINNET_ELECTRUM_PROTOCOL: ${{ secrets.mainnetElectrumProtocol }}
           MAINNET_ELECTRUM_HOST: ${{ secrets.mainnetElectrumHost }}
diff --git a/README.md b/README.md
index 3168902fc..d23b5d464 100644
--- a/README.md
+++ b/README.md
@@ -12,7 +12,8 @@ This project was bootstrapped with [Create React App](https://github.com/faceboo
 
 ```
 REACT_APP_DEFAULT_PROVIDER_CHAIN_ID=11155111
-REACT_APP_ALCHEMY_API=<your Alchemy API key>
+REACT_APP_RPC_SERVICE_API=<your RPC service API key>
+REACT_APP_RPC_SERVICE_NAME=<the RPC service name - Expected in RpcServices enum format e.g. "alchemy" or "infura">
 // We can skip this env variable- the dapp uses the correct address
 // of Multicall contract for Sepolia under the hood.
 REACT_APP_MULTICALL_ADDRESS=$MULTICALL_ADDRESS
@@ -109,7 +110,8 @@ Update `.env` to contain:
 
 ```
 REACT_APP_DEFAULT_PROVIDER_CHAIN_ID=11155111
-REACT_APP_ALCHEMY_API=<your Alchemy API key here>
+REACT_APP_RPC_SERVICE_API=<your RPC service API key here>
+REACT_APP_RPC_SERVICE_NAME=<your RPC service name here>
 REACT_APP_MULTICALL_ADDRESS=$MULTICALL_ADDRESS
 
 REACT_APP_FEATURE_FLAG_TBTC_V2=true
diff --git a/src/enums/env.ts b/src/enums/env.ts
index 6a9715427..f82d32cc5 100644
--- a/src/enums/env.ts
+++ b/src/enums/env.ts
@@ -1,6 +1,7 @@
 const envVariables = [
   "DEFAULT_PROVIDER_CHAIN_ID",
-  "ALCHEMY_API",
+  "RPC_SERVICE_API",
+  "RPC_SERVICE_NAME",
   "TBTC_SUBGRAPH_API",
   "FEATURE_FLAG_TBTC_V2",
   "FEATURE_FLAG_TBTC_V2_REDEMPTION",
@@ -29,7 +30,7 @@ const envVariables = [
 export type EnvVariableKey = typeof envVariables[number]
 
 // In order not to break the previous enum API, so using eg.
-// `EnvVariable.ALCHEMY_API` is still valid.
+// `EnvVariable.RPC_SERVICE_API` is still valid.
 export const EnvVariable: Record<EnvVariableKey, EnvVariableKey> =
   envVariables.reduce((reducer, envKey) => {
     reducer[envKey] = envKey
diff --git a/src/networks/README.md b/src/networks/README.md
index 7ce950d69..48c6933c5 100644
--- a/src/networks/README.md
+++ b/src/networks/README.md
@@ -33,16 +33,25 @@ export enum SupportedChainIds {
 }
 ```
 
-AlchemyName: Identifies the API identifiers (Alchemy) associated with each network.
+AlchemyNetworkId: Identifies the API identifiers (Alchemy) associated with each network.
 
 ```
-export enum AlchemyName {
+export enum AlchemyNetworkId {
   Ethereum = "eth",
   Arbitrum = "arb",
   Base = "base",
 }
 ```
 
+InfuraNetworkId: Identifies the API identifiers (Infura) associated with each network.
+
+```
+export enum InfuraNetworkId {
+  Arbitrum = "arbitrum",
+  Base = "base",
+}
+```
+
 NetworkType: Classifies networks based on whether they are Mainnet or Testnet.
 
 ```
@@ -63,7 +72,7 @@ export enum Layer {
 
 Network List Definition
 
-The networks.ts file in utils defines an array of Network objects, where each network is described by its chain ID, name, layer, network type, and Alchemy identifier. This array serves as the central configuration point for supported networks.
+The networks.ts file in utils defines an array of Network objects, where each network is described by its chain ID, name, layer, network type, and RPC service identifier (Alchemy or Infura). This array serves as the central configuration point for supported networks.
 
 Example Network Configuration
 
@@ -73,53 +82,22 @@ Below is an example network configuration, which includes key properties for eac
 export const networks: Network[] = [
   {
     chainId: SupportedChainIds.Ethereum,
-    name: "Ethereum",
-    layer: Layer.L1,
-    networkType: NetworkType.Mainnet,
-    alchemyName: AlchemyName.Ethereum,
-  },
-  {
-    chainId: SupportedChainIds.Sepolia,
-    name: "Sepolia",
-    layer: Layer.L1,
-    networkType: NetworkType.Testnet,
-    alchemyName: AlchemyName.Ethereum,
-  },
-  {
-    chainId: SupportedChainIds.Localhost,
-    name: "Localhost",
+    name: SupportedNetworksName.Ethereum,
     layer: Layer.L1,
-    networkType: NetworkType.Testnet,
-    alchemyName: "",
-  },
-  {
-    chainId: SupportedChainIds.Arbitrum,
-    name: "Arbitrum",
-    layer: Layer.L2,
     networkType: NetworkType.Mainnet,
-    alchemyName: AlchemyName.Arbitrum,
-  },
-  {
-    chainId: SupportedChainIds.ArbitrumSepolia,
-    name: "ArbitrumSepolia",
-    layer: Layer.L2,
-    networkType: NetworkType.Testnet,
-    alchemyName: AlchemyName.Arbitrum,
-  },
-  {
-    chainId: SupportedChainIds.Base,
-    name: "Base",
-    layer: Layer.L2,
-    networkType: NetworkType.Mainnet,
-    alchemyName: AlchemyName.Base,
-  },
-  {
-    chainId: SupportedChainIds.BaseSepolia,
-    name: "BaseSepolia",
-    layer: Layer.L2,
-    networkType: NetworkType.Testnet,
-    alchemyName: AlchemyName.Base,
-  },
+    chainParameters: {
+      chainId: toHex(SupportedChainIds.Ethereum),
+      chainName: "Ethereum Mainnet",
+      nativeCurrency: {
+        name: NativeCurrency.Ether,
+        symbol: ETH_SYMBOL,
+        decimals: DECIMALS,
+      },
+      rpcUrls: [PublicRpcUrls.Ethereum],
+      blockExplorerUrls: [createExplorerPrefix(SupportedChainIds.Ethereum)],
+    },
+  }
+  // ...
 ]
 ```
 
@@ -127,13 +105,13 @@ Adding a New Network
 
 - Update the SupportedChainIds enum: Add the new chain ID with a unique identifier.
 - Add a corresponding entry in networks.ts: Create a new network object with the required properties such as name, layer, networkType, and alchemyName (if applicable).
-- Define the Alchemy name (if needed): If the new network is supported by Alchemy, add its API identifier to the AlchemyName enum.
+- Define the RPC network Id (if needed): If the new network is supported by Alchemy or Infura, add its API identifier to the AlchemyNetworkId or InfuraNetworkId.
 
 Removing a Network
 
 - Remove the chain ID from SupportedChainIds.
 - Delete the network entry from networks.ts.
-- Remove its corresponding entry from the AlchemyName enum if no longer needed.
+- Remove its corresponding entry from the AlchemyNetworkId or InfuraNetworkId enum if no longer needed.
 
 Conclusion
 
diff --git a/src/networks/constants/networks.ts b/src/networks/constants/networks.ts
index e14705c9b..55b5b4491 100644
--- a/src/networks/constants/networks.ts
+++ b/src/networks/constants/networks.ts
@@ -1,2 +1,4 @@
 export const DECIMALS = 18
 export const ETH_SYMBOL = "ETH"
+export const MAIN_ALCHEMY_URL = "g.alchemy.com/v2/"
+export const MAIN_INFURA_URL = "infura.io/v3/"
diff --git a/src/networks/enums/networks.ts b/src/networks/enums/networks.ts
index 93f1f27ae..fbd07f1ea 100644
--- a/src/networks/enums/networks.ts
+++ b/src/networks/enums/networks.ts
@@ -1,3 +1,9 @@
+export enum NetworksName {
+  Ethereum = "Ethereum",
+  Arbitrum = "Arbitrum",
+  Base = "Base",
+}
+
 export enum TrmNetworksChainId {
   ethereum = 1,
   arbitrum = 42161,
@@ -14,12 +20,22 @@ export enum SupportedChainIds {
   BaseSepolia = 84532,
 }
 
-export enum AlchemyName {
+export enum RpcServices {
+  Alchemy = "alchemy",
+  Infura = "infura",
+}
+
+export enum AlchemyNetworkId {
   Ethereum = "eth",
   Arbitrum = "arb",
   Base = "base",
 }
 
+export enum InfuraNetworkId {
+  Arbitrum = "arbitrum",
+  Base = "base",
+}
+
 export enum NetworkType {
   Mainnet = "mainnet",
   Testnet = "sepolia",
diff --git a/src/networks/types/networks.ts b/src/networks/types/networks.ts
index 4c6e630be..51827a3d4 100644
--- a/src/networks/types/networks.ts
+++ b/src/networks/types/networks.ts
@@ -1,16 +1,14 @@
-import { Chains } from "@keep-network/tbtc-v2.ts"
 import {
   Layer,
   NetworkType,
   SupportedChainIds,
-  AlchemyName,
+  AlchemyNetworkId,
+  InfuraNetworkId,
+  NetworksName,
 } from "../enums/networks"
-
-export interface NetworksAlchemyConfig {
-  [chainId: number]: {
-    name: AlchemyName
-    type: NetworkType
-  }
+export interface RpcServiceConfig {
+  networkId?: AlchemyNetworkId | InfuraNetworkId
+  networkType: NetworkType
 }
 
 export interface EthereumRpcMap {
@@ -20,7 +18,7 @@ export interface EthereumRpcMap {
 export type NetworkName = keyof typeof SupportedChainIds
 export interface Network {
   chainId: SupportedChainIds
-  name: keyof typeof Chains
+  name: NetworksName
   layer: Layer
   networkType: NetworkType
   chainParameters: {
@@ -31,10 +29,9 @@ export interface Network {
       symbol: string
       decimals: number
     }
-    rpcUrls: string[]
     blockExplorerUrls: string[]
   }
-  alchemyName?: AlchemyName
+  rpcNetworkId?: AlchemyNetworkId | InfuraNetworkId
 }
 
 export type TrmNetworksMap = {
diff --git a/src/networks/utils/connectedNetwork.ts b/src/networks/utils/connectedNetwork.ts
index f0a54d1ce..3cdcd652a 100644
--- a/src/networks/utils/connectedNetwork.ts
+++ b/src/networks/utils/connectedNetwork.ts
@@ -1,4 +1,4 @@
-import { getChainIdToNetworkName } from "./getChainIdToNetworkName"
+import { getNetworkNameFromChainId } from "./getNetworkNameFromChainId"
 import {
   l1MainnetNetworksMap,
   l1TestNetworksMap,
@@ -8,7 +8,7 @@ import {
 } from "./mappings"
 
 export const isSupportedNetwork = (chainId?: string | number): boolean => {
-  return getChainIdToNetworkName(chainId) !== "Unsupported"
+  return getNetworkNameFromChainId(chainId) !== "Unsupported"
 }
 
 export const isTestnetNetwork = (networkChainId: string | number): boolean => {
diff --git a/src/networks/utils/getChainIdToNetworkName.ts b/src/networks/utils/getNetworkNameFromChainId.ts
similarity index 72%
rename from src/networks/utils/getChainIdToNetworkName.ts
rename to src/networks/utils/getNetworkNameFromChainId.ts
index 9c5f977b2..4812db7b8 100644
--- a/src/networks/utils/getChainIdToNetworkName.ts
+++ b/src/networks/utils/getNetworkNameFromChainId.ts
@@ -1,6 +1,9 @@
+import { NetworksName } from "../enums/networks"
 import { networks } from "./networks"
 
-export function getChainIdToNetworkName(chainId?: number | string): string {
+export function getNetworkNameFromChainId(
+  chainId?: number | string
+): NetworksName | "Unsupported" {
   const network = networks.find(
     (network) => network.chainId === Number(chainId)
   )
diff --git a/src/networks/utils/getRpcEndpointUrl.ts b/src/networks/utils/getRpcEndpointUrl.ts
new file mode 100644
index 000000000..1939b170c
--- /dev/null
+++ b/src/networks/utils/getRpcEndpointUrl.ts
@@ -0,0 +1,30 @@
+import { EnvVariable } from "../../enums"
+import { getEnvVariable } from "../../utils/getEnvVariable"
+import { MAIN_ALCHEMY_URL, MAIN_INFURA_URL } from "../constants/networks"
+import { NetworksName, RpcServices, SupportedChainIds } from "../enums/networks"
+import { getNetworkNameFromChainId } from "./getNetworkNameFromChainId"
+import { getRpcNetworkConfig } from "./getRpcNetworkConfig"
+
+export const getRpcEndpointUrl = (chainId?: number | string) => {
+  const rpcServiceApi = getEnvVariable(EnvVariable.RPC_SERVICE_API)
+  const rpcServiceName = getEnvVariable(EnvVariable.RPC_SERVICE_NAME)
+  const defaultChainId = SupportedChainIds.Ethereum
+  const chainIdNumber = Number(chainId) || defaultChainId
+  const networkName = getNetworkNameFromChainId(chainIdNumber)
+
+  if (networkName === "Unsupported") {
+    return "http://localhost:8545"
+  }
+  const rpcConfig = getRpcNetworkConfig(networkName, chainIdNumber)
+
+  switch (rpcServiceName) {
+    case RpcServices.Infura:
+      return networkName === NetworksName.Ethereum
+        ? `https://${rpcConfig.networkType}.${MAIN_INFURA_URL}${rpcServiceApi}`
+        : `https://${rpcConfig.networkId}-${rpcConfig.networkType}.${MAIN_INFURA_URL}${rpcServiceApi}`
+    case RpcServices.Alchemy:
+      return `https://${rpcConfig.networkId}-${rpcConfig.networkType}.${MAIN_ALCHEMY_URL}${rpcServiceApi}`
+    default:
+      return "http://localhost:8545"
+  }
+}
diff --git a/src/networks/utils/getRpcNetworkConfig.ts b/src/networks/utils/getRpcNetworkConfig.ts
new file mode 100644
index 000000000..94456e34d
--- /dev/null
+++ b/src/networks/utils/getRpcNetworkConfig.ts
@@ -0,0 +1,36 @@
+import { EnvVariable } from "../../enums"
+import { getEnvVariable } from "../../utils/getEnvVariable"
+import {
+  AlchemyNetworkId,
+  InfuraNetworkId,
+  NetworksName,
+  NetworkType,
+  RpcServices,
+} from "../enums/networks"
+import { RpcServiceConfig } from "../types/networks"
+import { isTestnetNetwork } from "./connectedNetwork"
+
+export function getRpcNetworkConfig(
+  networkName: NetworksName,
+  chainId: number | string
+): RpcServiceConfig {
+  const rpcServiceName = getEnvVariable(EnvVariable.RPC_SERVICE_NAME)
+  const networkType = isTestnetNetwork(chainId)
+    ? NetworkType.Testnet
+    : NetworkType.Mainnet
+
+  switch (rpcServiceName) {
+    case RpcServices.Infura:
+      return {
+        networkId: InfuraNetworkId[networkName as keyof typeof InfuraNetworkId],
+        networkType,
+      }
+    case RpcServices.Alchemy:
+    default:
+      return {
+        networkId:
+          AlchemyNetworkId[networkName as keyof typeof AlchemyNetworkId],
+        networkType,
+      }
+  }
+}
diff --git a/src/networks/utils/getRpcUrl.ts b/src/networks/utils/getRpcUrl.ts
deleted file mode 100644
index fc05d6337..000000000
--- a/src/networks/utils/getRpcUrl.ts
+++ /dev/null
@@ -1,17 +0,0 @@
-import { EnvVariable } from "../../enums"
-import { getEnvVariable } from "../../utils/getEnvVariable"
-import { SupportedChainIds } from "../enums/networks"
-import { networksAlchemyConfig } from "./networksAlchemyConfig"
-
-const MAIN_ALCHEMY_URL = "g.alchemy.com/v2/"
-
-export const getRpcUrl = (chainId?: number | string) => {
-  const alchemyApi = getEnvVariable(EnvVariable.ALCHEMY_API)
-  const defaultChainId = SupportedChainIds.Ethereum
-  const chainIdNum = Number(chainId) || defaultChainId
-  const alchemyConfig = networksAlchemyConfig[chainIdNum]
-
-  return alchemyConfig?.name
-    ? `https://${alchemyConfig.name}-${alchemyConfig.type}.${MAIN_ALCHEMY_URL}${alchemyApi}`
-    : `http://localhost:8545`
-}
diff --git a/src/networks/utils/index.ts b/src/networks/utils/index.ts
index e0e31c80b..a04bcb7a6 100644
--- a/src/networks/utils/index.ts
+++ b/src/networks/utils/index.ts
@@ -1,10 +1,9 @@
 export * from "./chainId"
-export * from "./getChainIdToNetworkName"
+export * from "./getNetworkNameFromChainId"
 export * from "./chainIdToTrmNetworkName"
 export * from "./connectedNetwork"
 export * from "./createExplorerLink"
-export * from "./getRpcUrl"
+export * from "./getRpcEndpointUrl"
 export * from "./mappings"
 export * from "./networks"
-export * from "./networksAlchemyConfig"
 export * from "./getMainnetOrTestnetChainId"
diff --git a/src/networks/utils/networks.ts b/src/networks/utils/networks.ts
index 8d37d6268..91930c2c6 100644
--- a/src/networks/utils/networks.ts
+++ b/src/networks/utils/networks.ts
@@ -1,10 +1,9 @@
 import {
-  AlchemyName,
   Layer,
   NetworkType,
   SupportedChainIds,
   NativeCurrency,
-  PublicRpcUrls,
+  NetworksName,
 } from "../enums/networks"
 import { Network } from "../types/networks"
 import { DECIMALS, ETH_SYMBOL } from "../constants/networks"
@@ -14,10 +13,9 @@ import { createExplorerPrefix } from "./createExplorerLink"
 export const networks: Network[] = [
   {
     chainId: SupportedChainIds.Ethereum,
-    name: "Ethereum",
+    name: NetworksName.Ethereum,
     layer: Layer.L1,
     networkType: NetworkType.Mainnet,
-    alchemyName: AlchemyName.Ethereum,
     chainParameters: {
       chainId: toHex(SupportedChainIds.Ethereum),
       chainName: "Ethereum Mainnet",
@@ -26,16 +24,14 @@ export const networks: Network[] = [
         symbol: ETH_SYMBOL,
         decimals: DECIMALS,
       },
-      rpcUrls: [PublicRpcUrls.Ethereum],
       blockExplorerUrls: [createExplorerPrefix(SupportedChainIds.Ethereum)],
     },
   },
   {
     chainId: SupportedChainIds.Arbitrum,
-    name: "Arbitrum",
+    name: NetworksName.Arbitrum,
     layer: Layer.L2,
     networkType: NetworkType.Mainnet,
-    alchemyName: AlchemyName.Arbitrum,
     chainParameters: {
       chainId: toHex(SupportedChainIds.Arbitrum),
       chainName: "Arbitrum One",
@@ -44,13 +40,12 @@ export const networks: Network[] = [
         symbol: ETH_SYMBOL,
         decimals: DECIMALS,
       },
-      rpcUrls: [PublicRpcUrls.Arbitrum],
       blockExplorerUrls: [createExplorerPrefix(SupportedChainIds.Arbitrum)],
     },
   },
   {
     chainId: SupportedChainIds.Localhost,
-    name: "Ethereum",
+    name: NetworksName.Ethereum,
     layer: Layer.L1,
     networkType: NetworkType.Testnet,
     chainParameters: {
@@ -61,16 +56,14 @@ export const networks: Network[] = [
         symbol: ETH_SYMBOL,
         decimals: DECIMALS,
       },
-      rpcUrls: [PublicRpcUrls.Localhost],
       blockExplorerUrls: ["http://localhost:8545"],
     },
   },
   // {
   //   chainId: SupportedChainIds.Base,
-  //   name: "Base",
+  //   name: NetworksName.Base,
   //   layer: Layer.L2,
   //   networkType: NetworkType.Mainnet,
-  //   alchemyName: AlchemyName.Base,
   //   chainParameters: {
   //     chainId: toHex(SupportedChainIds.Base),
   //     chainName: "Base Mainnet",
@@ -79,16 +72,14 @@ export const networks: Network[] = [
   //       symbol: ETH_SYMBOL,
   //       decimals: DECIMALS,
   //     },
-  //     rpcUrls: [PublicRpcUrls.Base],
   //     blockExplorerUrls: [createExplorerPrefix(SupportedChainIds.Base)],
   //   },
   // },
   {
     chainId: SupportedChainIds.Sepolia,
-    name: "Ethereum",
+    name: NetworksName.Ethereum,
     layer: Layer.L1,
     networkType: NetworkType.Testnet,
-    alchemyName: AlchemyName.Ethereum,
     chainParameters: {
       chainId: toHex(SupportedChainIds.Sepolia),
       chainName: "Sepolia Testnet",
@@ -97,16 +88,14 @@ export const networks: Network[] = [
         symbol: ETH_SYMBOL,
         decimals: DECIMALS,
       },
-      rpcUrls: [PublicRpcUrls.Sepolia],
       blockExplorerUrls: [createExplorerPrefix(SupportedChainIds.Sepolia)],
     },
   },
   {
     chainId: SupportedChainIds.ArbitrumSepolia,
-    name: "Arbitrum",
+    name: NetworksName.Arbitrum,
     layer: Layer.L2,
     networkType: NetworkType.Testnet,
-    alchemyName: AlchemyName.Arbitrum,
     chainParameters: {
       chainId: toHex(SupportedChainIds.ArbitrumSepolia),
       chainName: "Arbitrum Sepolia",
@@ -115,7 +104,6 @@ export const networks: Network[] = [
         symbol: ETH_SYMBOL,
         decimals: DECIMALS,
       },
-      rpcUrls: [PublicRpcUrls.ArbitrumSepolia],
       blockExplorerUrls: [
         createExplorerPrefix(SupportedChainIds.ArbitrumSepolia),
       ],
@@ -123,10 +111,9 @@ export const networks: Network[] = [
   },
   {
     chainId: SupportedChainIds.BaseSepolia,
-    name: "Base",
+    name: NetworksName.Base,
     layer: Layer.L2,
     networkType: NetworkType.Testnet,
-    alchemyName: AlchemyName.Base,
     chainParameters: {
       chainId: toHex(SupportedChainIds.BaseSepolia),
       chainName: "Base Sepolia",
@@ -135,7 +122,6 @@ export const networks: Network[] = [
         symbol: ETH_SYMBOL,
         decimals: DECIMALS,
       },
-      rpcUrls: [PublicRpcUrls.BaseSepolia],
       blockExplorerUrls: [createExplorerPrefix(SupportedChainIds.BaseSepolia)],
     },
   },
diff --git a/src/networks/utils/networksAlchemyConfig.ts b/src/networks/utils/networksAlchemyConfig.ts
deleted file mode 100644
index b21543d11..000000000
--- a/src/networks/utils/networksAlchemyConfig.ts
+++ /dev/null
@@ -1,29 +0,0 @@
-import { AlchemyName, NetworkType, SupportedChainIds } from "../enums/networks"
-import { NetworksAlchemyConfig } from "../types/networks"
-
-export const networksAlchemyConfig: NetworksAlchemyConfig = {
-  [SupportedChainIds.Ethereum]: {
-    name: AlchemyName.Ethereum,
-    type: NetworkType.Mainnet,
-  },
-  [SupportedChainIds.Sepolia]: {
-    name: AlchemyName.Ethereum,
-    type: NetworkType.Testnet,
-  },
-  [SupportedChainIds.Arbitrum]: {
-    name: AlchemyName.Arbitrum,
-    type: NetworkType.Mainnet,
-  },
-  [SupportedChainIds.ArbitrumSepolia]: {
-    name: AlchemyName.Arbitrum,
-    type: NetworkType.Testnet,
-  },
-  [SupportedChainIds.Base]: {
-    name: AlchemyName.Base,
-    type: NetworkType.Mainnet,
-  },
-  [SupportedChainIds.BaseSepolia]: {
-    name: AlchemyName.Base,
-    type: NetworkType.Testnet,
-  },
-}
diff --git a/src/pages/tBTC/Bridge/Minting/ProvideData.tsx b/src/pages/tBTC/Bridge/Minting/ProvideData.tsx
index 646a5b9d3..84ba12dd0 100644
--- a/src/pages/tBTC/Bridge/Minting/ProvideData.tsx
+++ b/src/pages/tBTC/Bridge/Minting/ProvideData.tsx
@@ -20,7 +20,7 @@ import {
 } from "../../../../utils/forms"
 import { SupportedChainIds } from "../../../../networks/enums/networks"
 import {
-  getChainIdToNetworkName,
+  getNetworkNameFromChainId,
   isL1Network,
   isSupportedNetwork,
   isTestnetNetwork,
@@ -154,7 +154,7 @@ export const ProvideDataComponent: FC<{
         )
       }
 
-      const chainName = getChainIdToNetworkName(chainId)
+      const chainName = getNetworkNameFromChainId(chainId)
 
       setSubmitButtonLoading(true)
 
diff --git a/src/store/tbtc/effects.ts b/src/store/tbtc/effects.ts
index 2e0626361..c2593fd86 100644
--- a/src/store/tbtc/effects.ts
+++ b/src/store/tbtc/effects.ts
@@ -10,7 +10,7 @@ import { isAddress, isAddressZero } from "../../web3/utils"
 import { AppListenerEffectAPI } from "../listener"
 import { tbtcSlice } from "./tbtcSlice"
 import {
-  getChainIdToNetworkName,
+  getNetworkNameFromChainId,
   isL1Network,
   isSameChainId,
 } from "../../networks/utils"
@@ -85,7 +85,7 @@ export const findUtxoEffect = async (
   const pollingTask = listenerApi.fork(async (forkApi) => {
     try {
       while (true) {
-        if (getChainIdToNetworkName(chainId) !== chainName) {
+        if (getNetworkNameFromChainId(chainId) !== chainName) {
           throw new Error("Chain ID and deposit chain name mismatch")
         }
         // Initiating deposit from redux store (if deposit object is empty)
diff --git a/src/threshold-ts/tbtc/index.ts b/src/threshold-ts/tbtc/index.ts
index c7da93463..30f73e7ac 100644
--- a/src/threshold-ts/tbtc/index.ts
+++ b/src/threshold-ts/tbtc/index.ts
@@ -49,7 +49,7 @@ import {
 import {
   isL1Network,
   isL2Network,
-  getChainIdToNetworkName,
+  getNetworkNameFromChainId,
   getMainnetOrTestnetChainId,
 } from "../../networks/utils"
 import { SupportedChainIds } from "../../networks/enums/networks"
@@ -579,7 +579,7 @@ export class TBTC implements ITBTC {
     })
 
     if (this._isCrossChain) {
-      const networkName = getChainIdToNetworkName(chainId)
+      const networkName = getNetworkNameFromChainId(chainId)
       const l1BitcoinDepositorArtifact = getArtifact(
         `${networkName}L1BitcoinDepositor` as ArtifactNameType,
         mainnetOrTestnetEthereumChainId,
@@ -729,7 +729,7 @@ export class TBTC implements ITBTC {
     const signer = getSigner(providerOrSigner as Web3Provider, account)
 
     const connectedChainId = await chainIdFromSigner(signer)
-    const l2NetworkName = getChainIdToNetworkName(connectedChainId)
+    const l2NetworkName = getNetworkNameFromChainId(connectedChainId)
 
     await sdk.initializeCrossChain(l2NetworkName as L2Chain, signer)
   }
@@ -749,7 +749,7 @@ export class TBTC implements ITBTC {
     }
 
     const sdk = await this._getSdk()
-    const l2NetworkName = getChainIdToNetworkName(chainId)
+    const l2NetworkName = getNetworkNameFromChainId(chainId)
     this._deposit = await sdk.deposits.initiateCrossChainDeposit(
       btcRecoveryAddress,
       l2NetworkName as Exclude<keyof typeof Chains, "Ethereum">
@@ -796,7 +796,7 @@ export class TBTC implements ITBTC {
     if (!this._isCrossChain) {
       throw new Error("Unsupported chain ID")
     }
-    const l2NetworkName = getChainIdToNetworkName(chainId)
+    const l2NetworkName = getNetworkNameFromChainId(chainId)
     const sdk = await this._getSdk()
 
     const {
@@ -1213,7 +1213,7 @@ export class TBTC implements ITBTC {
     const l1Sender = L2_RELAYER_BOT_WALLET
 
     const l1BitcoinDepositorArtifact = getArtifact(
-      `${getChainIdToNetworkName(
+      `${getNetworkNameFromChainId(
         this.ethereumChainId
       )}L1BitcoinDepositor` as ArtifactNameType,
       getMainnetOrTestnetChainId(this.ethereumChainId)
@@ -1238,7 +1238,7 @@ export class TBTC implements ITBTC {
     const l1Sender = L2_RELAYER_BOT_WALLET
 
     const l1BitcoinDepositorArtifact = getArtifact(
-      `${getChainIdToNetworkName(
+      `${getNetworkNameFromChainId(
         this.ethereumChainId
       )}L1BitcoinDepositor` as ArtifactNameType,
       getMainnetOrTestnetChainId(this.ethereumChainId)
diff --git a/src/utils/getThresholdLib.ts b/src/utils/getThresholdLib.ts
index 5ecf1bc1b..66b4c7169 100644
--- a/src/utils/getThresholdLib.ts
+++ b/src/utils/getThresholdLib.ts
@@ -11,7 +11,7 @@ import {
   isSupportedNetwork,
   isTestnetNetwork,
 } from "../networks/utils/connectedNetwork"
-import { getRpcUrl } from "../networks/utils/getRpcUrl"
+import { getRpcEndpointUrl } from "../networks/utils/getRpcEndpointUrl"
 import { MockBitcoinClient } from "../tbtc/mock-bitcoin-client"
 import {
   BitcoinConfig,
@@ -59,8 +59,7 @@ export const getThresholdLibProvider = (chainId?: number | string) => {
   const supportedChainId = isSupportedNetwork(chainId)
     ? Number(chainId)
     : getDefaultProviderChainId()
-
-  const rpcUrl = getRpcUrl(supportedChainId)
+  const rpcUrl = getRpcEndpointUrl(supportedChainId)
 
   return new JsonRpcProvider(rpcUrl, supportedChainId)
 }
diff --git a/src/web3/connectors/coinbaseWallet.ts b/src/web3/connectors/coinbaseWallet.ts
index dcd785c29..e690f36e6 100644
--- a/src/web3/connectors/coinbaseWallet.ts
+++ b/src/web3/connectors/coinbaseWallet.ts
@@ -35,7 +35,7 @@ export class CoinbaseWalletConnector extends WalletLinkConnector {
       // only enforced during type checking. This means that JavaScript runtime
       // constructs like `in` or simple property lookup can still access a
       // `private` or `protected` member.
-      provider.updateProviderInfo(getRpcUrl(chainId), chainId, true)
+      provider.updateProviderInfo(getRpcEndpointUrl(chainId), chainId, true)
     }
 
     return await super.activate()
@@ -43,7 +43,7 @@ export class CoinbaseWalletConnector extends WalletLinkConnector {
 }
 
 export const coinbaseConnector = new CoinbaseWalletConnector({
-  url: getRpcUrl(),
+  url: getRpcEndpointUrl(),
   appName: "threshold-token-dashboard",
   supportedChainIds: Object.keys(supportedNetworksMap).map(Number),
 })
diff --git a/src/web3/connectors/ledgerLive.ts b/src/web3/connectors/ledgerLive.ts
index abc77ee1c..ea1edfac8 100644
--- a/src/web3/connectors/ledgerLive.ts
+++ b/src/web3/connectors/ledgerLive.ts
@@ -8,13 +8,10 @@ import {
   EthereumProvider,
 } from "@ledgerhq/connect-kit-loader"
 import { EnvVariable } from "../../enums"
-import {
-  getRpcUrl,
-  networks,
-  supportedNetworksMap,
-  getChainIdToNetworkName,
-} from "../../networks/utils"
+import { networks, supportedNetworksMap } from "../../networks/utils"
 import { EthereumRpcMap } from "../../networks/types/networks"
+import { getNetworkNameFromChainId } from "../../networks/utils/getNetworkNameFromChainId"
+import { getRpcEndpointUrl } from "../../networks/utils/getRpcEndpointUrl"
 
 const supportedNetworks = Object.keys(supportedNetworksMap).map(Number)
 
@@ -92,7 +89,7 @@ export class LedgerLiveConnector extends AbstractConnector {
 
     if (!checkSupportResult.isChainIdSupported) {
       throw new Error(
-        `The ${getChainIdToNetworkName(
+        `The ${getNetworkNameFromChainId(
           chainId
         )} network is not supported by LedgerLive.`
       )
@@ -145,7 +142,7 @@ export class LedgerLiveConnector extends AbstractConnector {
 export const ledgerLive = new LedgerLiveConnector({
   supportedChainIds: supportedNetworks,
   rpc: networks.reduce((acc, network) => {
-    acc[network.chainId] = getRpcUrl(network.chainId)
+    acc[network.chainId] = getRpcEndpointUrl(network.chainId)
     return acc
   }, {} as EthereumRpcMap),
   walletConnectProjectId: getEnvVariable(EnvVariable.WALLET_CONNECT_PROJECT_ID),
diff --git a/src/web3/connectors/walletConnect.ts b/src/web3/connectors/walletConnect.ts
index 581577bb9..eec3e68f3 100644
--- a/src/web3/connectors/walletConnect.ts
+++ b/src/web3/connectors/walletConnect.ts
@@ -4,7 +4,11 @@ import { ConnectorUpdate } from "@web3-react/types"
 import { EnvVariable } from "../../enums"
 import { ArrayOneOrMore } from "../../types"
 import { getEnvVariable } from "../../utils/getEnvVariable"
-import { getRpcUrl, networks, supportedNetworksMap } from "../../networks/utils"
+import {
+  getRpcEndpointUrl,
+  networks,
+  supportedNetworksMap,
+} from "../../networks/utils"
 import { toHex } from "../../networks/utils/chainId"
 import { EthereumRpcMap } from "../../networks/types/networks"
 
@@ -182,7 +186,7 @@ const walletConnectProjectId = getEnvVariable(
 export const walletConnect = new WalletConnectConnector({
   chains: supportedNetworks,
   rpc: networks.reduce((acc, network) => {
-    acc[network.chainId] = getRpcUrl(network.chainId)
+    acc[network.chainId] = getRpcEndpointUrl(network.chainId)
     return acc
   }, {} as EthereumRpcMap),
   projectId: walletConnectProjectId,
diff --git a/src/web3/hooks/__tests__/useContract.test.ts b/src/web3/hooks/__tests__/useContract.test.ts
index 1e156a9b4..08f5b99f7 100644
--- a/src/web3/hooks/__tests__/useContract.test.ts
+++ b/src/web3/hooks/__tests__/useContract.test.ts
@@ -4,7 +4,7 @@ import { JsonRpcProvider } from "@ethersproject/providers"
 import { useContract } from "../useContract"
 import { getContract } from "../../../utils/getContract"
 import { getEnvVariable } from "../../../utils/getEnvVariable"
-import { getRpcUrl } from "../../../networks/utils"
+import { getRpcEndpointUrl } from "../../../networks/utils"
 
 jest.mock("../../../utils/getContract", () => ({
   ...(jest.requireActual("../../../utils/getContract") as {}),
@@ -62,7 +62,7 @@ describe("Test the `useContract` hook", () => {
 
       const { result } = renderHook(() => useContract(address, abi))
 
-      expect(getEnvVariable).toHaveBeenCalledWith(getRpcUrl())
+      expect(getEnvVariable).toHaveBeenCalledWith(getRpcEndpointUrl())
       expect(JsonRpcProvider).toHaveBeenCalledWith(mockedEthNodeUrl)
       expect(result.current).toEqual(mockedContract)
     })

From a34f77effb39d00f0b33a870117418e0ce48334c Mon Sep 17 00:00:00 2001
From: evandrosaturnino <evandro.saturnino@gmail.com>
Date: Mon, 16 Dec 2024 22:05:37 -0300
Subject: [PATCH 43/46] get public rpc url in case of missing rpc service

---
 src/networks/README.md                  |  1 -
 src/networks/constants/networks.ts      | 12 ++++++++++++
 src/networks/enums/networks.ts          | 10 ----------
 src/networks/utils/getRpcEndpointUrl.ts |  8 ++++++--
 4 files changed, 18 insertions(+), 13 deletions(-)

diff --git a/src/networks/README.md b/src/networks/README.md
index 48c6933c5..622439d5d 100644
--- a/src/networks/README.md
+++ b/src/networks/README.md
@@ -93,7 +93,6 @@ export const networks: Network[] = [
         symbol: ETH_SYMBOL,
         decimals: DECIMALS,
       },
-      rpcUrls: [PublicRpcUrls.Ethereum],
       blockExplorerUrls: [createExplorerPrefix(SupportedChainIds.Ethereum)],
     },
   }
diff --git a/src/networks/constants/networks.ts b/src/networks/constants/networks.ts
index 55b5b4491..f971d916b 100644
--- a/src/networks/constants/networks.ts
+++ b/src/networks/constants/networks.ts
@@ -1,4 +1,16 @@
+import { SupportedChainIds } from "../enums/networks"
+
 export const DECIMALS = 18
 export const ETH_SYMBOL = "ETH"
 export const MAIN_ALCHEMY_URL = "g.alchemy.com/v2/"
 export const MAIN_INFURA_URL = "infura.io/v3/"
+
+export const publicRpcUrls: Record<SupportedChainIds, string> = {
+  [SupportedChainIds.Ethereum]: "https://eth.drpc.org",
+  [SupportedChainIds.Sepolia]: "https://sepolia.drpc.org",
+  [SupportedChainIds.Localhost]: "http://localhost:8545",
+  [SupportedChainIds.Arbitrum]: "https://arbitrum.drpc.org",
+  [SupportedChainIds.ArbitrumSepolia]: "https://arbitrum-sepolia.drpc.org",
+  [SupportedChainIds.Base]: "https://base.drpc.org",
+  [SupportedChainIds.BaseSepolia]: "https://base-sepolia.drpc.org",
+}
diff --git a/src/networks/enums/networks.ts b/src/networks/enums/networks.ts
index fbd07f1ea..14ffa37a2 100644
--- a/src/networks/enums/networks.ts
+++ b/src/networks/enums/networks.ts
@@ -57,13 +57,3 @@ export enum ExplorerDataType {
   ADDRESS = "address",
   BLOCK = "block",
 }
-
-export enum PublicRpcUrls {
-  Ethereum = "https://eth.drpc.org",
-  Sepolia = "https://sepolia.drpc.org",
-  Localhost = "http://localhost:8545",
-  Arbitrum = "https://arbitrum.drpc.org",
-  ArbitrumSepolia = "https://arbitrum-sepolia.drpc.org",
-  Base = "https://base.drpc.org",
-  BaseSepolia = "https://base-sepolia.drpc.org",
-}
diff --git a/src/networks/utils/getRpcEndpointUrl.ts b/src/networks/utils/getRpcEndpointUrl.ts
index 1939b170c..03a8fedbf 100644
--- a/src/networks/utils/getRpcEndpointUrl.ts
+++ b/src/networks/utils/getRpcEndpointUrl.ts
@@ -1,6 +1,10 @@
 import { EnvVariable } from "../../enums"
 import { getEnvVariable } from "../../utils/getEnvVariable"
-import { MAIN_ALCHEMY_URL, MAIN_INFURA_URL } from "../constants/networks"
+import {
+  MAIN_ALCHEMY_URL,
+  MAIN_INFURA_URL,
+  publicRpcUrls,
+} from "../constants/networks"
 import { NetworksName, RpcServices, SupportedChainIds } from "../enums/networks"
 import { getNetworkNameFromChainId } from "./getNetworkNameFromChainId"
 import { getRpcNetworkConfig } from "./getRpcNetworkConfig"
@@ -25,6 +29,6 @@ export const getRpcEndpointUrl = (chainId?: number | string) => {
     case RpcServices.Alchemy:
       return `https://${rpcConfig.networkId}-${rpcConfig.networkType}.${MAIN_ALCHEMY_URL}${rpcServiceApi}`
     default:
-      return "http://localhost:8545"
+      return publicRpcUrls[chainIdNumber as SupportedChainIds]
   }
 }

From 46e51d799f15ab9c8663fd98aced437625350b60 Mon Sep 17 00:00:00 2001
From: evandrosaturnino <evandro.saturnino@gmail.com>
Date: Mon, 16 Dec 2024 22:21:24 -0300
Subject: [PATCH 44/46] add loyalty program url if arbitrum is connected

---
 src/pages/PageLayout.tsx | 9 ++++++++-
 src/pages/tBTC/index.tsx | 8 ++++++++
 src/types/page.ts        | 1 +
 3 files changed, 17 insertions(+), 1 deletion(-)

diff --git a/src/pages/PageLayout.tsx b/src/pages/PageLayout.tsx
index 1da9ab318..20f78b869 100644
--- a/src/pages/PageLayout.tsx
+++ b/src/pages/PageLayout.tsx
@@ -23,10 +23,17 @@ const PageLayout: FC<PageLayoutProps> = ({
     ? pages.filter((_) => !_.route.hideFromMenu).map((_) => _.route)
     : []
 
+  const visibleExternalLinks = externalLinks
+    ? externalLinks?.filter((_) => !_.hideFromMenu)
+    : []
+
   return (
     <>
       {links.length > 0 && (
-        <SubNavigationPills links={links} externalLinks={externalLinks} />
+        <SubNavigationPills
+          links={links}
+          externalLinks={visibleExternalLinks}
+        />
       )}
       <Container
         maxW={{ base: "2xl", xl: "6xl" }}
diff --git a/src/pages/tBTC/index.tsx b/src/pages/tBTC/index.tsx
index c46176eb1..55050dfe7 100644
--- a/src/pages/tBTC/index.tsx
+++ b/src/pages/tBTC/index.tsx
@@ -5,13 +5,21 @@ import TBTCBridge from "./Bridge"
 import { featureFlags } from "../../constants"
 import { ExplorerPage } from "./Explorer"
 import { ResumeDepositPage } from "./Bridge/ResumeDeposit"
+import { useIsActive } from "../../hooks/useIsActive"
+import { SupportedChainIds } from "../../networks/enums/networks"
 
 const MainTBTCPage: PageComponent = (props) => {
+  const { chainId } = useIsActive()
   const externalLinks = [
     {
       title: "tBTC Explorer",
       href: "https://tbtcscan.com/",
     },
+    {
+      title: "Loyalty Program",
+      href: "https://arbitrum.threshold.network/loyalty-program",
+      hideFromMenu: chainId !== SupportedChainIds.Arbitrum,
+    },
   ]
 
   return (
diff --git a/src/types/page.ts b/src/types/page.ts
index 473002081..4351dfd5c 100644
--- a/src/types/page.ts
+++ b/src/types/page.ts
@@ -19,4 +19,5 @@ export type PageComponent = FC<RouteProps> & {
 
 export type ExternalLinkProps = LinkProps & {
   title: string
+  hideFromMenu?: boolean
 }

From 2e843c7b804daa6055b3312df0d820b612dffa14 Mon Sep 17 00:00:00 2001
From: evandrosaturnino <evandro.saturnino@gmail.com>
Date: Mon, 10 Feb 2025 01:25:19 -0300
Subject: [PATCH 45/46] fixes the coinbase wallet rpc url

---
 src/web3/connectors/coinbaseWallet.ts | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/web3/connectors/coinbaseWallet.ts b/src/web3/connectors/coinbaseWallet.ts
index e690f36e6..2b206f5ae 100644
--- a/src/web3/connectors/coinbaseWallet.ts
+++ b/src/web3/connectors/coinbaseWallet.ts
@@ -1,7 +1,7 @@
 import { WalletLinkConnector } from "@web3-react/walletlink-connector"
 import { ConnectorUpdate } from "@web3-react/types"
 import {
-  getRpcUrl,
+  getRpcEndpointUrl,
   hexToNumber,
   supportedNetworksMap,
 } from "../../networks/utils"

From 6832c2aa5f9280cfac32eedd244170fb915ef710 Mon Sep 17 00:00:00 2001
From: evandrosaturnino <evandro.saturnino@gmail.com>
Date: Mon, 10 Feb 2025 01:39:36 -0300
Subject: [PATCH 46/46] remove hardcoded taco registry artifacts

---
 src/hooks/useFetchTvl.ts                      |    1 -
 .../utils/validateL2TransactionType.ts        |   11 -
 .../TacoRegistry.json                         | 1352 --------------
 .../mas/mainnet-artifacts/TacoRegistry.json   | 1646 -----------------
 .../mas/sepolia-artifacts/TacoRegistry.json   | 1431 --------------
 5 files changed, 4441 deletions(-)
 delete mode 100644 src/networks/utils/validateL2TransactionType.ts
 delete mode 100644 src/threshold-ts/mas/dapp-development-sepolia-artifacts/TacoRegistry.json
 delete mode 100644 src/threshold-ts/mas/mainnet-artifacts/TacoRegistry.json
 delete mode 100644 src/threshold-ts/mas/sepolia-artifacts/TacoRegistry.json

diff --git a/src/hooks/useFetchTvl.ts b/src/hooks/useFetchTvl.ts
index 22577dafb..020c5d2fb 100644
--- a/src/hooks/useFetchTvl.ts
+++ b/src/hooks/useFetchTvl.ts
@@ -127,7 +127,6 @@ export const useFetchTvl = (): [
   const fetchOnChainData = useMulticall(calls)
 
   const fetchTvlData = useCallback(async () => {
-    if (chainId && !isL1Network(chainId)) return initialState
     const chainData = await fetchOnChainData()
     if (chainData.length === 0) return initialState
 
diff --git a/src/networks/utils/validateL2TransactionType.ts b/src/networks/utils/validateL2TransactionType.ts
deleted file mode 100644
index 0af9f1c62..000000000
--- a/src/networks/utils/validateL2TransactionType.ts
+++ /dev/null
@@ -1,11 +0,0 @@
-import { ALLOWED_L2_TRANSACTIONS } from "../constants/networks"
-import { AllowedL2TransactionTypes } from "../enums/networks"
-
-export function isValidL2Transaction<T = AllowedL2TransactionTypes>(
-  type?: T
-): boolean {
-  if (!type) return false
-  return ALLOWED_L2_TRANSACTIONS.includes(
-    type as unknown as AllowedL2TransactionTypes
-  )
-}
diff --git a/src/threshold-ts/mas/dapp-development-sepolia-artifacts/TacoRegistry.json b/src/threshold-ts/mas/dapp-development-sepolia-artifacts/TacoRegistry.json
deleted file mode 100644
index 1e5bcbf03..000000000
--- a/src/threshold-ts/mas/dapp-development-sepolia-artifacts/TacoRegistry.json
+++ /dev/null
@@ -1,1352 +0,0 @@
-{
-  "address": "0xE9Eb81F72cDBE9fE82f61EA527e8a3A39f5B023a",
-  "abi": [
-    {
-      "type": "constructor",
-      "stateMutability": "nonpayable",
-      "inputs": [
-        {
-          "name": "_token",
-          "type": "address",
-          "internalType": "contract IERC20"
-        },
-        {
-          "name": "_tStaking",
-          "type": "address",
-          "internalType": "contract IStaking"
-        },
-        {
-          "name": "_minimumAuthorization",
-          "type": "uint96",
-          "internalType": "uint96"
-        },
-        {
-          "name": "_minOperatorSeconds",
-          "type": "uint256",
-          "internalType": "uint256"
-        },
-        {
-          "name": "_rewardDuration",
-          "type": "uint256",
-          "internalType": "uint256"
-        },
-        {
-          "name": "_deauthorizationDuration",
-          "type": "uint256",
-          "internalType": "uint256"
-        },
-        {
-          "name": "_commitmentDurationOptions",
-          "type": "uint64[]",
-          "internalType": "uint64[]"
-        },
-        {
-          "name": "_commitmentDeadline",
-          "type": "uint64",
-          "internalType": "uint64"
-        }
-      ]
-    },
-    {
-      "type": "error",
-      "name": "AddressEmptyCode",
-      "inputs": [
-        {
-          "name": "target",
-          "type": "address",
-          "internalType": "address"
-        }
-      ]
-    },
-    {
-      "type": "error",
-      "name": "AddressInsufficientBalance",
-      "inputs": [
-        {
-          "name": "account",
-          "type": "address",
-          "internalType": "address"
-        }
-      ]
-    },
-    {
-      "type": "error",
-      "name": "FailedInnerCall",
-      "inputs": []
-    },
-    {
-      "type": "error",
-      "name": "InvalidInitialization",
-      "inputs": []
-    },
-    {
-      "type": "error",
-      "name": "NotInitializing",
-      "inputs": []
-    },
-    {
-      "type": "error",
-      "name": "OwnableInvalidOwner",
-      "inputs": [
-        {
-          "name": "owner",
-          "type": "address",
-          "internalType": "address"
-        }
-      ]
-    },
-    {
-      "type": "error",
-      "name": "OwnableUnauthorizedAccount",
-      "inputs": [
-        {
-          "name": "account",
-          "type": "address",
-          "internalType": "address"
-        }
-      ]
-    },
-    {
-      "type": "error",
-      "name": "SafeCastOverflowedUintDowncast",
-      "inputs": [
-        {
-          "name": "bits",
-          "type": "uint8",
-          "internalType": "uint8"
-        },
-        {
-          "name": "value",
-          "type": "uint256",
-          "internalType": "uint256"
-        }
-      ]
-    },
-    {
-      "type": "error",
-      "name": "SafeERC20FailedOperation",
-      "inputs": [
-        {
-          "name": "token",
-          "type": "address",
-          "internalType": "address"
-        }
-      ]
-    },
-    {
-      "type": "event",
-      "name": "AuthorizationDecreaseApproved",
-      "inputs": [
-        {
-          "name": "stakingProvider",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        },
-        {
-          "name": "fromAmount",
-          "type": "uint96",
-          "internalType": "uint96",
-          "indexed": false
-        },
-        {
-          "name": "toAmount",
-          "type": "uint96",
-          "internalType": "uint96",
-          "indexed": false
-        }
-      ],
-      "anonymous": false
-    },
-    {
-      "type": "event",
-      "name": "AuthorizationDecreaseRequested",
-      "inputs": [
-        {
-          "name": "stakingProvider",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        },
-        {
-          "name": "fromAmount",
-          "type": "uint96",
-          "internalType": "uint96",
-          "indexed": false
-        },
-        {
-          "name": "toAmount",
-          "type": "uint96",
-          "internalType": "uint96",
-          "indexed": false
-        }
-      ],
-      "anonymous": false
-    },
-    {
-      "type": "event",
-      "name": "AuthorizationIncreased",
-      "inputs": [
-        {
-          "name": "stakingProvider",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        },
-        {
-          "name": "fromAmount",
-          "type": "uint96",
-          "internalType": "uint96",
-          "indexed": false
-        },
-        {
-          "name": "toAmount",
-          "type": "uint96",
-          "internalType": "uint96",
-          "indexed": false
-        }
-      ],
-      "anonymous": false
-    },
-    {
-      "type": "event",
-      "name": "AuthorizationInvoluntaryDecreased",
-      "inputs": [
-        {
-          "name": "stakingProvider",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        },
-        {
-          "name": "fromAmount",
-          "type": "uint96",
-          "internalType": "uint96",
-          "indexed": false
-        },
-        {
-          "name": "toAmount",
-          "type": "uint96",
-          "internalType": "uint96",
-          "indexed": false
-        }
-      ],
-      "anonymous": false
-    },
-    {
-      "type": "event",
-      "name": "AuthorizationReSynchronized",
-      "inputs": [
-        {
-          "name": "stakingProvider",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        },
-        {
-          "name": "fromAmount",
-          "type": "uint96",
-          "internalType": "uint96",
-          "indexed": false
-        },
-        {
-          "name": "toAmount",
-          "type": "uint96",
-          "internalType": "uint96",
-          "indexed": false
-        }
-      ],
-      "anonymous": false
-    },
-    {
-      "type": "event",
-      "name": "CommitmentMade",
-      "inputs": [
-        {
-          "name": "stakingProvider",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        },
-        {
-          "name": "endCommitment",
-          "type": "uint256",
-          "internalType": "uint256",
-          "indexed": false
-        }
-      ],
-      "anonymous": false
-    },
-    {
-      "type": "event",
-      "name": "Initialized",
-      "inputs": [
-        {
-          "name": "version",
-          "type": "uint64",
-          "internalType": "uint64",
-          "indexed": false
-        }
-      ],
-      "anonymous": false
-    },
-    {
-      "type": "event",
-      "name": "OperatorBonded",
-      "inputs": [
-        {
-          "name": "stakingProvider",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        },
-        {
-          "name": "operator",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        },
-        {
-          "name": "previousOperator",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        },
-        {
-          "name": "startTimestamp",
-          "type": "uint256",
-          "internalType": "uint256",
-          "indexed": false
-        }
-      ],
-      "anonymous": false
-    },
-    {
-      "type": "event",
-      "name": "OperatorConfirmed",
-      "inputs": [
-        {
-          "name": "stakingProvider",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        },
-        {
-          "name": "operator",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        }
-      ],
-      "anonymous": false
-    },
-    {
-      "type": "event",
-      "name": "OwnershipTransferred",
-      "inputs": [
-        {
-          "name": "previousOwner",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        },
-        {
-          "name": "newOwner",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        }
-      ],
-      "anonymous": false
-    },
-    {
-      "type": "event",
-      "name": "RewardAdded",
-      "inputs": [
-        {
-          "name": "reward",
-          "type": "uint256",
-          "internalType": "uint256",
-          "indexed": false
-        }
-      ],
-      "anonymous": false
-    },
-    {
-      "type": "event",
-      "name": "RewardDistributorSet",
-      "inputs": [
-        {
-          "name": "distributor",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        }
-      ],
-      "anonymous": false
-    },
-    {
-      "type": "event",
-      "name": "RewardPaid",
-      "inputs": [
-        {
-          "name": "stakingProvider",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        },
-        {
-          "name": "beneficiary",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        },
-        {
-          "name": "reward",
-          "type": "uint256",
-          "internalType": "uint256",
-          "indexed": false
-        }
-      ],
-      "anonymous": false
-    },
-    {
-      "type": "event",
-      "name": "RewardsWithdrawn",
-      "inputs": [
-        {
-          "name": "stakingProvider",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        },
-        {
-          "name": "amount",
-          "type": "uint96",
-          "internalType": "uint96",
-          "indexed": false
-        }
-      ],
-      "anonymous": false
-    },
-    {
-      "type": "event",
-      "name": "Slashed",
-      "inputs": [
-        {
-          "name": "stakingProvider",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        },
-        {
-          "name": "penalty",
-          "type": "uint256",
-          "internalType": "uint256",
-          "indexed": false
-        },
-        {
-          "name": "investigator",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        },
-        {
-          "name": "reward",
-          "type": "uint256",
-          "internalType": "uint256",
-          "indexed": false
-        }
-      ],
-      "anonymous": false
-    },
-    {
-      "type": "function",
-      "name": "REWARD_PER_TOKEN_MULTIPLIER",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint256",
-          "internalType": "uint256"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "adjudicator",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "address",
-          "internalType": "address"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "approveAuthorizationDecrease",
-      "stateMutability": "nonpayable",
-      "inputs": [
-        {
-          "name": "_stakingProvider",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": []
-    },
-    {
-      "type": "function",
-      "name": "authorizationDecreaseRequested",
-      "stateMutability": "nonpayable",
-      "inputs": [
-        {
-          "name": "_stakingProvider",
-          "type": "address",
-          "internalType": "address"
-        },
-        {
-          "name": "_fromAmount",
-          "type": "uint96",
-          "internalType": "uint96"
-        },
-        {
-          "name": "_toAmount",
-          "type": "uint96",
-          "internalType": "uint96"
-        }
-      ],
-      "outputs": []
-    },
-    {
-      "type": "function",
-      "name": "authorizationIncreased",
-      "stateMutability": "nonpayable",
-      "inputs": [
-        {
-          "name": "_stakingProvider",
-          "type": "address",
-          "internalType": "address"
-        },
-        {
-          "name": "_fromAmount",
-          "type": "uint96",
-          "internalType": "uint96"
-        },
-        {
-          "name": "_toAmount",
-          "type": "uint96",
-          "internalType": "uint96"
-        }
-      ],
-      "outputs": []
-    },
-    {
-      "type": "function",
-      "name": "authorizationParameters",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "_minimumAuthorization",
-          "type": "uint96",
-          "internalType": "uint96"
-        },
-        {
-          "name": "authorizationDecreaseDelay",
-          "type": "uint64",
-          "internalType": "uint64"
-        },
-        {
-          "name": "authorizationDecreaseChangePeriod",
-          "type": "uint64",
-          "internalType": "uint64"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "authorizedOverall",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint96",
-          "internalType": "uint96"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "authorizedStake",
-      "stateMutability": "view",
-      "inputs": [
-        {
-          "name": "_stakingProvider",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint96",
-          "internalType": "uint96"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "availableRewards",
-      "stateMutability": "view",
-      "inputs": [
-        {
-          "name": "_stakingProvider",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint96",
-          "internalType": "uint96"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "bondOperator",
-      "stateMutability": "nonpayable",
-      "inputs": [
-        {
-          "name": "_stakingProvider",
-          "type": "address",
-          "internalType": "address"
-        },
-        {
-          "name": "_operator",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": []
-    },
-    {
-      "type": "function",
-      "name": "childApplication",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "address",
-          "internalType": "contract ITACoRootToChild"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "commitmentDeadline",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint64",
-          "internalType": "uint64"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "commitmentDurationOption1",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint64",
-          "internalType": "uint64"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "commitmentDurationOption2",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint64",
-          "internalType": "uint64"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "commitmentDurationOption3",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint64",
-          "internalType": "uint64"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "commitmentDurationOption4",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint64",
-          "internalType": "uint64"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "confirmOperatorAddress",
-      "stateMutability": "nonpayable",
-      "inputs": [
-        {
-          "name": "_operator",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": []
-    },
-    {
-      "type": "function",
-      "name": "deauthorizationDuration",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint256",
-          "internalType": "uint256"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "getActiveStakingProviders",
-      "stateMutability": "view",
-      "inputs": [
-        {
-          "name": "_startIndex",
-          "type": "uint256",
-          "internalType": "uint256"
-        },
-        {
-          "name": "_maxStakingProviders",
-          "type": "uint256",
-          "internalType": "uint256"
-        }
-      ],
-      "outputs": [
-        {
-          "name": "allAuthorizedTokens",
-          "type": "uint256",
-          "internalType": "uint256"
-        },
-        {
-          "name": "activeStakingProviders",
-          "type": "bytes32[]",
-          "internalType": "bytes32[]"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "getBeneficiary",
-      "stateMutability": "view",
-      "inputs": [
-        {
-          "name": "_stakingProvider",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": [
-        {
-          "name": "beneficiary",
-          "type": "address",
-          "internalType": "address payable"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "getStakingProvidersLength",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint256",
-          "internalType": "uint256"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "initialize",
-      "stateMutability": "nonpayable",
-      "inputs": [],
-      "outputs": []
-    },
-    {
-      "type": "function",
-      "name": "involuntaryAuthorizationDecrease",
-      "stateMutability": "nonpayable",
-      "inputs": [
-        {
-          "name": "_stakingProvider",
-          "type": "address",
-          "internalType": "address"
-        },
-        {
-          "name": "_fromAmount",
-          "type": "uint96",
-          "internalType": "uint96"
-        },
-        {
-          "name": "_toAmount",
-          "type": "uint96",
-          "internalType": "uint96"
-        }
-      ],
-      "outputs": []
-    },
-    {
-      "type": "function",
-      "name": "isAuthorized",
-      "stateMutability": "view",
-      "inputs": [
-        {
-          "name": "_stakingProvider",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": [
-        {
-          "name": "",
-          "type": "bool",
-          "internalType": "bool"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "isOperatorConfirmed",
-      "stateMutability": "view",
-      "inputs": [
-        {
-          "name": "_operator",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": [
-        {
-          "name": "",
-          "type": "bool",
-          "internalType": "bool"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "lastTimeRewardApplicable",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint256",
-          "internalType": "uint256"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "lastUpdateTime",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint256",
-          "internalType": "uint256"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "makeCommitment",
-      "stateMutability": "nonpayable",
-      "inputs": [
-        {
-          "name": "_stakingProvider",
-          "type": "address",
-          "internalType": "address"
-        },
-        {
-          "name": "_commitmentDuration",
-          "type": "uint64",
-          "internalType": "uint64"
-        }
-      ],
-      "outputs": []
-    },
-    {
-      "type": "function",
-      "name": "minOperatorSeconds",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint256",
-          "internalType": "uint256"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "minimumAuthorization",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint96",
-          "internalType": "uint96"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "operatorToStakingProvider",
-      "stateMutability": "view",
-      "inputs": [
-        {
-          "name": "_operator",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": [
-        {
-          "name": "",
-          "type": "address",
-          "internalType": "address"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "owner",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "address",
-          "internalType": "address"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "pendingAuthorizationDecrease",
-      "stateMutability": "view",
-      "inputs": [
-        {
-          "name": "_stakingProvider",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint96",
-          "internalType": "uint96"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "periodFinish",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint256",
-          "internalType": "uint256"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "pushReward",
-      "stateMutability": "nonpayable",
-      "inputs": [
-        {
-          "name": "_reward",
-          "type": "uint96",
-          "internalType": "uint96"
-        }
-      ],
-      "outputs": []
-    },
-    {
-      "type": "function",
-      "name": "registerOperator",
-      "stateMutability": "nonpayable",
-      "inputs": [
-        {
-          "name": "_operator",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": []
-    },
-    {
-      "type": "function",
-      "name": "remainingAuthorizationDecreaseDelay",
-      "stateMutability": "view",
-      "inputs": [
-        {
-          "name": "_stakingProvider",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint64",
-          "internalType": "uint64"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "renounceOwnership",
-      "stateMutability": "nonpayable",
-      "inputs": [],
-      "outputs": []
-    },
-    {
-      "type": "function",
-      "name": "resynchronizeAuthorization",
-      "stateMutability": "nonpayable",
-      "inputs": [
-        {
-          "name": "_stakingProvider",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": []
-    },
-    {
-      "type": "function",
-      "name": "rewardDistributor",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "address",
-          "internalType": "address"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "rewardDuration",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint256",
-          "internalType": "uint256"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "rewardPerToken",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint160",
-          "internalType": "uint160"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "rewardPerTokenStored",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint160",
-          "internalType": "uint160"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "rewardRateDecimals",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint256",
-          "internalType": "uint256"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "setAdjudicator",
-      "stateMutability": "nonpayable",
-      "inputs": [
-        {
-          "name": "_adjudicator",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": []
-    },
-    {
-      "type": "function",
-      "name": "setChildApplication",
-      "stateMutability": "nonpayable",
-      "inputs": [
-        {
-          "name": "_childApplication",
-          "type": "address",
-          "internalType": "contract ITACoRootToChild"
-        }
-      ],
-      "outputs": []
-    },
-    {
-      "type": "function",
-      "name": "setRewardDistributor",
-      "stateMutability": "nonpayable",
-      "inputs": [
-        {
-          "name": "_rewardDistributor",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": []
-    },
-    {
-      "type": "function",
-      "name": "slash",
-      "stateMutability": "nonpayable",
-      "inputs": [
-        {
-          "name": "_stakingProvider",
-          "type": "address",
-          "internalType": "address"
-        },
-        {
-          "name": "_penalty",
-          "type": "uint96",
-          "internalType": "uint96"
-        },
-        {
-          "name": "_investigator",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": []
-    },
-    {
-      "type": "function",
-      "name": "stakingProviderInfo",
-      "stateMutability": "view",
-      "inputs": [
-        {
-          "name": "",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": [
-        {
-          "name": "operator",
-          "type": "address",
-          "internalType": "address"
-        },
-        {
-          "name": "operatorConfirmed",
-          "type": "bool",
-          "internalType": "bool"
-        },
-        {
-          "name": "operatorStartTimestamp",
-          "type": "uint64",
-          "internalType": "uint64"
-        },
-        {
-          "name": "authorized",
-          "type": "uint96",
-          "internalType": "uint96"
-        },
-        {
-          "name": "deauthorizing",
-          "type": "uint96",
-          "internalType": "uint96"
-        },
-        {
-          "name": "endDeauthorization",
-          "type": "uint64",
-          "internalType": "uint64"
-        },
-        {
-          "name": "tReward",
-          "type": "uint96",
-          "internalType": "uint96"
-        },
-        {
-          "name": "rewardPerTokenPaid",
-          "type": "uint160",
-          "internalType": "uint160"
-        },
-        {
-          "name": "endCommitment",
-          "type": "uint64",
-          "internalType": "uint64"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "stakingProviderToOperator",
-      "stateMutability": "view",
-      "inputs": [
-        {
-          "name": "_stakingProvider",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": [
-        {
-          "name": "",
-          "type": "address",
-          "internalType": "address"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "stakingProviders",
-      "stateMutability": "view",
-      "inputs": [
-        {
-          "name": "",
-          "type": "uint256",
-          "internalType": "uint256"
-        }
-      ],
-      "outputs": [
-        {
-          "name": "",
-          "type": "address",
-          "internalType": "address"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "tStaking",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "address",
-          "internalType": "contract IStaking"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "token",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "address",
-          "internalType": "contract IERC20"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "transferOwnership",
-      "stateMutability": "nonpayable",
-      "inputs": [
-        {
-          "name": "newOwner",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": []
-    },
-    {
-      "type": "function",
-      "name": "withdrawRewards",
-      "stateMutability": "nonpayable",
-      "inputs": [
-        {
-          "name": "_stakingProvider",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": []
-    }
-  ],
-  "tx_hash": "0xb9cd5deb857d4e74e45bcd9dd435f3fccf08cdb8c91ac0ca9da36c47210eb149",
-  "block_number": 4776043,
-  "deployer": "0x24dbb0BEE134C3773D2C1791d65d99e307Fe86CF"
-}
diff --git a/src/threshold-ts/mas/mainnet-artifacts/TacoRegistry.json b/src/threshold-ts/mas/mainnet-artifacts/TacoRegistry.json
deleted file mode 100644
index 681f5b44a..000000000
--- a/src/threshold-ts/mas/mainnet-artifacts/TacoRegistry.json
+++ /dev/null
@@ -1,1646 +0,0 @@
-{
-  "address": "0x347CC7ede7e5517bD47D20620B2CF1b406edcF07",
-  "abi": [
-    {
-      "type": "constructor",
-      "stateMutability": "nonpayable",
-      "inputs": [
-        {
-          "name": "_token",
-          "type": "address",
-          "internalType": "contract IERC20"
-        },
-        {
-          "name": "_tStaking",
-          "type": "address",
-          "internalType": "contract IStaking"
-        },
-        {
-          "name": "_minimumAuthorization",
-          "type": "uint96",
-          "internalType": "uint96"
-        },
-        {
-          "name": "_minOperatorSeconds",
-          "type": "uint256",
-          "internalType": "uint256"
-        },
-        {
-          "name": "_rewardDuration",
-          "type": "uint256",
-          "internalType": "uint256"
-        },
-        {
-          "name": "_deauthorizationDuration",
-          "type": "uint256",
-          "internalType": "uint256"
-        },
-        {
-          "name": "_commitmentDurationOptions",
-          "type": "uint64[]",
-          "internalType": "uint64[]"
-        },
-        {
-          "name": "_commitmentDeadline",
-          "type": "uint64",
-          "internalType": "uint64"
-        },
-        {
-          "name": "_penaltyDefault",
-          "type": "uint192",
-          "internalType": "uint192"
-        },
-        {
-          "name": "_penaltyDuration",
-          "type": "uint256",
-          "internalType": "uint256"
-        },
-        {
-          "name": "_penaltyIncrement",
-          "type": "uint192",
-          "internalType": "uint192"
-        }
-      ]
-    },
-    {
-      "type": "error",
-      "name": "AddressEmptyCode",
-      "inputs": [
-        {
-          "name": "target",
-          "type": "address",
-          "internalType": "address"
-        }
-      ]
-    },
-    {
-      "type": "error",
-      "name": "AddressInsufficientBalance",
-      "inputs": [
-        {
-          "name": "account",
-          "type": "address",
-          "internalType": "address"
-        }
-      ]
-    },
-    {
-      "type": "error",
-      "name": "FailedInnerCall",
-      "inputs": []
-    },
-    {
-      "type": "error",
-      "name": "InvalidInitialization",
-      "inputs": []
-    },
-    {
-      "type": "error",
-      "name": "NotInitializing",
-      "inputs": []
-    },
-    {
-      "type": "error",
-      "name": "OwnableInvalidOwner",
-      "inputs": [
-        {
-          "name": "owner",
-          "type": "address",
-          "internalType": "address"
-        }
-      ]
-    },
-    {
-      "type": "error",
-      "name": "OwnableUnauthorizedAccount",
-      "inputs": [
-        {
-          "name": "account",
-          "type": "address",
-          "internalType": "address"
-        }
-      ]
-    },
-    {
-      "type": "error",
-      "name": "SafeCastOverflowedUintDowncast",
-      "inputs": [
-        {
-          "name": "bits",
-          "type": "uint8",
-          "internalType": "uint8"
-        },
-        {
-          "name": "value",
-          "type": "uint256",
-          "internalType": "uint256"
-        }
-      ]
-    },
-    {
-      "type": "error",
-      "name": "SafeERC20FailedOperation",
-      "inputs": [
-        {
-          "name": "token",
-          "type": "address",
-          "internalType": "address"
-        }
-      ]
-    },
-    {
-      "type": "event",
-      "name": "AuthorizationDecreaseApproved",
-      "inputs": [
-        {
-          "name": "stakingProvider",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        },
-        {
-          "name": "fromAmount",
-          "type": "uint96",
-          "internalType": "uint96",
-          "indexed": false
-        },
-        {
-          "name": "toAmount",
-          "type": "uint96",
-          "internalType": "uint96",
-          "indexed": false
-        }
-      ],
-      "anonymous": false
-    },
-    {
-      "type": "event",
-      "name": "AuthorizationDecreaseRequested",
-      "inputs": [
-        {
-          "name": "stakingProvider",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        },
-        {
-          "name": "fromAmount",
-          "type": "uint96",
-          "internalType": "uint96",
-          "indexed": false
-        },
-        {
-          "name": "toAmount",
-          "type": "uint96",
-          "internalType": "uint96",
-          "indexed": false
-        }
-      ],
-      "anonymous": false
-    },
-    {
-      "type": "event",
-      "name": "AuthorizationIncreased",
-      "inputs": [
-        {
-          "name": "stakingProvider",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        },
-        {
-          "name": "fromAmount",
-          "type": "uint96",
-          "internalType": "uint96",
-          "indexed": false
-        },
-        {
-          "name": "toAmount",
-          "type": "uint96",
-          "internalType": "uint96",
-          "indexed": false
-        }
-      ],
-      "anonymous": false
-    },
-    {
-      "type": "event",
-      "name": "AuthorizationInvoluntaryDecreased",
-      "inputs": [
-        {
-          "name": "stakingProvider",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        },
-        {
-          "name": "fromAmount",
-          "type": "uint96",
-          "internalType": "uint96",
-          "indexed": false
-        },
-        {
-          "name": "toAmount",
-          "type": "uint96",
-          "internalType": "uint96",
-          "indexed": false
-        }
-      ],
-      "anonymous": false
-    },
-    {
-      "type": "event",
-      "name": "AuthorizationReSynchronized",
-      "inputs": [
-        {
-          "name": "stakingProvider",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        },
-        {
-          "name": "fromAmount",
-          "type": "uint96",
-          "internalType": "uint96",
-          "indexed": false
-        },
-        {
-          "name": "toAmount",
-          "type": "uint96",
-          "internalType": "uint96",
-          "indexed": false
-        }
-      ],
-      "anonymous": false
-    },
-    {
-      "type": "event",
-      "name": "CommitmentMade",
-      "inputs": [
-        {
-          "name": "stakingProvider",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        },
-        {
-          "name": "endCommitment",
-          "type": "uint256",
-          "internalType": "uint256",
-          "indexed": false
-        }
-      ],
-      "anonymous": false
-    },
-    {
-      "type": "event",
-      "name": "Initialized",
-      "inputs": [
-        {
-          "name": "version",
-          "type": "uint64",
-          "internalType": "uint64",
-          "indexed": false
-        }
-      ],
-      "anonymous": false
-    },
-    {
-      "type": "event",
-      "name": "ManualChildSynchronizationSent",
-      "inputs": [
-        {
-          "name": "stakingProvider",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        },
-        {
-          "name": "authorized",
-          "type": "uint96",
-          "internalType": "uint96",
-          "indexed": false
-        },
-        {
-          "name": "deauthorizing",
-          "type": "uint96",
-          "internalType": "uint96",
-          "indexed": false
-        },
-        {
-          "name": "endDeauthorization",
-          "type": "uint64",
-          "internalType": "uint64",
-          "indexed": false
-        },
-        {
-          "name": "operator",
-          "type": "address",
-          "internalType": "address",
-          "indexed": false
-        }
-      ],
-      "anonymous": false
-    },
-    {
-      "type": "event",
-      "name": "OperatorBonded",
-      "inputs": [
-        {
-          "name": "stakingProvider",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        },
-        {
-          "name": "operator",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        },
-        {
-          "name": "previousOperator",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        },
-        {
-          "name": "startTimestamp",
-          "type": "uint256",
-          "internalType": "uint256",
-          "indexed": false
-        }
-      ],
-      "anonymous": false
-    },
-    {
-      "type": "event",
-      "name": "OperatorConfirmed",
-      "inputs": [
-        {
-          "name": "stakingProvider",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        },
-        {
-          "name": "operator",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        }
-      ],
-      "anonymous": false
-    },
-    {
-      "type": "event",
-      "name": "OwnershipTransferred",
-      "inputs": [
-        {
-          "name": "previousOwner",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        },
-        {
-          "name": "newOwner",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        }
-      ],
-      "anonymous": false
-    },
-    {
-      "type": "event",
-      "name": "Penalized",
-      "inputs": [
-        {
-          "name": "stakingProvider",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        },
-        {
-          "name": "penaltyPercent",
-          "type": "uint256",
-          "internalType": "uint256",
-          "indexed": false
-        },
-        {
-          "name": "endPenalty",
-          "type": "uint64",
-          "internalType": "uint64",
-          "indexed": false
-        }
-      ],
-      "anonymous": false
-    },
-    {
-      "type": "event",
-      "name": "RewardAdded",
-      "inputs": [
-        {
-          "name": "reward",
-          "type": "uint256",
-          "internalType": "uint256",
-          "indexed": false
-        }
-      ],
-      "anonymous": false
-    },
-    {
-      "type": "event",
-      "name": "RewardContractSet",
-      "inputs": [
-        {
-          "name": "rewardContract",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        }
-      ],
-      "anonymous": false
-    },
-    {
-      "type": "event",
-      "name": "RewardDistributorSet",
-      "inputs": [
-        {
-          "name": "distributor",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        }
-      ],
-      "anonymous": false
-    },
-    {
-      "type": "event",
-      "name": "RewardPaid",
-      "inputs": [
-        {
-          "name": "sender",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        },
-        {
-          "name": "stakingProvider",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        },
-        {
-          "name": "beneficiary",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        },
-        {
-          "name": "reward",
-          "type": "uint256",
-          "internalType": "uint256",
-          "indexed": false
-        }
-      ],
-      "anonymous": false
-    },
-    {
-      "type": "event",
-      "name": "RewardReset",
-      "inputs": [
-        {
-          "name": "stakingProvider",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        }
-      ],
-      "anonymous": false
-    },
-    {
-      "type": "event",
-      "name": "RewardsWithdrawn",
-      "inputs": [
-        {
-          "name": "stakingProvider",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        },
-        {
-          "name": "amount",
-          "type": "uint96",
-          "internalType": "uint96",
-          "indexed": false
-        }
-      ],
-      "anonymous": false
-    },
-    {
-      "type": "event",
-      "name": "Slashed",
-      "inputs": [
-        {
-          "name": "stakingProvider",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        },
-        {
-          "name": "penalty",
-          "type": "uint256",
-          "internalType": "uint256",
-          "indexed": false
-        },
-        {
-          "name": "investigator",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        },
-        {
-          "name": "reward",
-          "type": "uint256",
-          "internalType": "uint256",
-          "indexed": false
-        }
-      ],
-      "anonymous": false
-    },
-    {
-      "type": "function",
-      "name": "PENALTY_BASE",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint192",
-          "internalType": "uint192"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "REWARD_PER_TOKEN_MULTIPLIER",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint256",
-          "internalType": "uint256"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "adjudicator",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "address",
-          "internalType": "address"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "approveAuthorizationDecrease",
-      "stateMutability": "nonpayable",
-      "inputs": [
-        {
-          "name": "_stakingProvider",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": []
-    },
-    {
-      "type": "function",
-      "name": "authorizationDecreaseRequested",
-      "stateMutability": "nonpayable",
-      "inputs": [
-        {
-          "name": "_stakingProvider",
-          "type": "address",
-          "internalType": "address"
-        },
-        {
-          "name": "_fromAmount",
-          "type": "uint96",
-          "internalType": "uint96"
-        },
-        {
-          "name": "_toAmount",
-          "type": "uint96",
-          "internalType": "uint96"
-        }
-      ],
-      "outputs": []
-    },
-    {
-      "type": "function",
-      "name": "authorizationIncreased",
-      "stateMutability": "nonpayable",
-      "inputs": [
-        {
-          "name": "_stakingProvider",
-          "type": "address",
-          "internalType": "address"
-        },
-        {
-          "name": "_fromAmount",
-          "type": "uint96",
-          "internalType": "uint96"
-        },
-        {
-          "name": "_toAmount",
-          "type": "uint96",
-          "internalType": "uint96"
-        }
-      ],
-      "outputs": []
-    },
-    {
-      "type": "function",
-      "name": "authorizationParameters",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "_minimumAuthorization",
-          "type": "uint96",
-          "internalType": "uint96"
-        },
-        {
-          "name": "authorizationDecreaseDelay",
-          "type": "uint64",
-          "internalType": "uint64"
-        },
-        {
-          "name": "authorizationDecreaseChangePeriod",
-          "type": "uint64",
-          "internalType": "uint64"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "authorizedOverall",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint96",
-          "internalType": "uint96"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "authorizedStake",
-      "stateMutability": "view",
-      "inputs": [
-        {
-          "name": "_stakingProvider",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint96",
-          "internalType": "uint96"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "availableRewards",
-      "stateMutability": "view",
-      "inputs": [
-        {
-          "name": "_stakingProvider",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint96",
-          "internalType": "uint96"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "bondOperator",
-      "stateMutability": "nonpayable",
-      "inputs": [
-        {
-          "name": "_stakingProvider",
-          "type": "address",
-          "internalType": "address"
-        },
-        {
-          "name": "_operator",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": []
-    },
-    {
-      "type": "function",
-      "name": "childApplication",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "address",
-          "internalType": "contract ITACoRootToChild"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "commitmentDeadline",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint64",
-          "internalType": "uint64"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "commitmentDurationOption1",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint64",
-          "internalType": "uint64"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "commitmentDurationOption2",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint64",
-          "internalType": "uint64"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "commitmentDurationOption3",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint64",
-          "internalType": "uint64"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "commitmentDurationOption4",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint64",
-          "internalType": "uint64"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "confirmOperatorAddress",
-      "stateMutability": "nonpayable",
-      "inputs": [
-        {
-          "name": "_operator",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": []
-    },
-    {
-      "type": "function",
-      "name": "deauthorizationDuration",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint256",
-          "internalType": "uint256"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "eligibleStake",
-      "stateMutability": "view",
-      "inputs": [
-        {
-          "name": "_stakingProvider",
-          "type": "address",
-          "internalType": "address"
-        },
-        {
-          "name": "_endDate",
-          "type": "uint256",
-          "internalType": "uint256"
-        }
-      ],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint96",
-          "internalType": "uint96"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "getActiveStakingProviders",
-      "stateMutability": "view",
-      "inputs": [
-        {
-          "name": "_startIndex",
-          "type": "uint256",
-          "internalType": "uint256"
-        },
-        {
-          "name": "_maxStakingProviders",
-          "type": "uint256",
-          "internalType": "uint256"
-        },
-        {
-          "name": "_cohortDuration",
-          "type": "uint32",
-          "internalType": "uint32"
-        }
-      ],
-      "outputs": [
-        {
-          "name": "allAuthorizedTokens",
-          "type": "uint256",
-          "internalType": "uint256"
-        },
-        {
-          "name": "activeStakingProviders",
-          "type": "bytes32[]",
-          "internalType": "bytes32[]"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "getBeneficiary",
-      "stateMutability": "view",
-      "inputs": [
-        {
-          "name": "_stakingProvider",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": [
-        {
-          "name": "beneficiary",
-          "type": "address",
-          "internalType": "address payable"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "getPenalty",
-      "stateMutability": "view",
-      "inputs": [
-        {
-          "name": "_stakingProvider",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": [
-        {
-          "name": "penalty",
-          "type": "uint192",
-          "internalType": "uint192"
-        },
-        {
-          "name": "endPenalty",
-          "type": "uint64",
-          "internalType": "uint64"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "getStakingProvidersLength",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint256",
-          "internalType": "uint256"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "initialize",
-      "stateMutability": "nonpayable",
-      "inputs": [],
-      "outputs": []
-    },
-    {
-      "type": "function",
-      "name": "involuntaryAuthorizationDecrease",
-      "stateMutability": "nonpayable",
-      "inputs": [
-        {
-          "name": "_stakingProvider",
-          "type": "address",
-          "internalType": "address"
-        },
-        {
-          "name": "_fromAmount",
-          "type": "uint96",
-          "internalType": "uint96"
-        },
-        {
-          "name": "_toAmount",
-          "type": "uint96",
-          "internalType": "uint96"
-        }
-      ],
-      "outputs": []
-    },
-    {
-      "type": "function",
-      "name": "isAuthorized",
-      "stateMutability": "view",
-      "inputs": [
-        {
-          "name": "_stakingProvider",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": [
-        {
-          "name": "",
-          "type": "bool",
-          "internalType": "bool"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "isOperatorConfirmed",
-      "stateMutability": "view",
-      "inputs": [
-        {
-          "name": "_operator",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": [
-        {
-          "name": "",
-          "type": "bool",
-          "internalType": "bool"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "lastTimeRewardApplicable",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint256",
-          "internalType": "uint256"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "lastUpdateTime",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint256",
-          "internalType": "uint256"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "makeCommitment",
-      "stateMutability": "nonpayable",
-      "inputs": [
-        {
-          "name": "_stakingProvider",
-          "type": "address",
-          "internalType": "address"
-        },
-        {
-          "name": "_commitmentDuration",
-          "type": "uint64",
-          "internalType": "uint64"
-        }
-      ],
-      "outputs": []
-    },
-    {
-      "type": "function",
-      "name": "manualChildSynchronization",
-      "stateMutability": "nonpayable",
-      "inputs": [
-        {
-          "name": "_stakingProvider",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": []
-    },
-    {
-      "type": "function",
-      "name": "minOperatorSeconds",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint256",
-          "internalType": "uint256"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "minimumAuthorization",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint96",
-          "internalType": "uint96"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "operatorToStakingProvider",
-      "stateMutability": "view",
-      "inputs": [
-        {
-          "name": "_operator",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": [
-        {
-          "name": "",
-          "type": "address",
-          "internalType": "address"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "owner",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "address",
-          "internalType": "address"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "penalize",
-      "stateMutability": "nonpayable",
-      "inputs": [
-        {
-          "name": "_stakingProvider",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": []
-    },
-    {
-      "type": "function",
-      "name": "penaltyDefault",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint192",
-          "internalType": "uint192"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "penaltyDuration",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint256",
-          "internalType": "uint256"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "penaltyIncrement",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint192",
-          "internalType": "uint192"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "pendingAuthorizationDecrease",
-      "stateMutability": "view",
-      "inputs": [
-        {
-          "name": "_stakingProvider",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint96",
-          "internalType": "uint96"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "periodFinish",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint256",
-          "internalType": "uint256"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "pushReward",
-      "stateMutability": "nonpayable",
-      "inputs": [
-        {
-          "name": "_reward",
-          "type": "uint96",
-          "internalType": "uint96"
-        }
-      ],
-      "outputs": []
-    },
-    {
-      "type": "function",
-      "name": "registerOperator",
-      "stateMutability": "nonpayable",
-      "inputs": [
-        {
-          "name": "_operator",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": []
-    },
-    {
-      "type": "function",
-      "name": "remainingAuthorizationDecreaseDelay",
-      "stateMutability": "view",
-      "inputs": [
-        {
-          "name": "_stakingProvider",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint64",
-          "internalType": "uint64"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "renounceOwnership",
-      "stateMutability": "nonpayable",
-      "inputs": [],
-      "outputs": []
-    },
-    {
-      "type": "function",
-      "name": "resetReward",
-      "stateMutability": "nonpayable",
-      "inputs": [
-        {
-          "name": "_stakingProvider",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": []
-    },
-    {
-      "type": "function",
-      "name": "resynchronizeAuthorization",
-      "stateMutability": "nonpayable",
-      "inputs": [
-        {
-          "name": "_stakingProvider",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": []
-    },
-    {
-      "type": "function",
-      "name": "rewardContract",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "address",
-          "internalType": "address"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "rewardDistributor",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "address",
-          "internalType": "address"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "rewardDuration",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint256",
-          "internalType": "uint256"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "rewardPerToken",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint160",
-          "internalType": "uint160"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "rewardPerTokenStored",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint160",
-          "internalType": "uint160"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "rewardRateDecimals",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint256",
-          "internalType": "uint256"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "setAdjudicator",
-      "stateMutability": "nonpayable",
-      "inputs": [
-        {
-          "name": "_adjudicator",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": []
-    },
-    {
-      "type": "function",
-      "name": "setChildApplication",
-      "stateMutability": "nonpayable",
-      "inputs": [
-        {
-          "name": "_childApplication",
-          "type": "address",
-          "internalType": "contract ITACoRootToChild"
-        }
-      ],
-      "outputs": []
-    },
-    {
-      "type": "function",
-      "name": "setRewardContract",
-      "stateMutability": "nonpayable",
-      "inputs": [
-        {
-          "name": "_rewardContract",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": []
-    },
-    {
-      "type": "function",
-      "name": "setRewardDistributor",
-      "stateMutability": "nonpayable",
-      "inputs": [
-        {
-          "name": "_rewardDistributor",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": []
-    },
-    {
-      "type": "function",
-      "name": "slash",
-      "stateMutability": "nonpayable",
-      "inputs": [
-        {
-          "name": "_stakingProvider",
-          "type": "address",
-          "internalType": "address"
-        },
-        {
-          "name": "_penalty",
-          "type": "uint96",
-          "internalType": "uint96"
-        },
-        {
-          "name": "_investigator",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": []
-    },
-    {
-      "type": "function",
-      "name": "stakingProviderInfo",
-      "stateMutability": "view",
-      "inputs": [
-        {
-          "name": "",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": [
-        {
-          "name": "operator",
-          "type": "address",
-          "internalType": "address"
-        },
-        {
-          "name": "operatorConfirmed",
-          "type": "bool",
-          "internalType": "bool"
-        },
-        {
-          "name": "operatorStartTimestamp",
-          "type": "uint64",
-          "internalType": "uint64"
-        },
-        {
-          "name": "authorized",
-          "type": "uint96",
-          "internalType": "uint96"
-        },
-        {
-          "name": "deauthorizing",
-          "type": "uint96",
-          "internalType": "uint96"
-        },
-        {
-          "name": "endDeauthorization",
-          "type": "uint64",
-          "internalType": "uint64"
-        },
-        {
-          "name": "tReward",
-          "type": "uint96",
-          "internalType": "uint96"
-        },
-        {
-          "name": "rewardPerTokenPaid",
-          "type": "uint160",
-          "internalType": "uint160"
-        },
-        {
-          "name": "endCommitment",
-          "type": "uint64",
-          "internalType": "uint64"
-        },
-        {
-          "name": "stub",
-          "type": "uint256",
-          "internalType": "uint256"
-        },
-        {
-          "name": "penaltyPercent",
-          "type": "uint192",
-          "internalType": "uint192"
-        },
-        {
-          "name": "endPenalty",
-          "type": "uint64",
-          "internalType": "uint64"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "stakingProviderToOperator",
-      "stateMutability": "view",
-      "inputs": [
-        {
-          "name": "_stakingProvider",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": [
-        {
-          "name": "",
-          "type": "address",
-          "internalType": "address"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "stakingProviders",
-      "stateMutability": "view",
-      "inputs": [
-        {
-          "name": "",
-          "type": "uint256",
-          "internalType": "uint256"
-        }
-      ],
-      "outputs": [
-        {
-          "name": "",
-          "type": "address",
-          "internalType": "address"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "tStaking",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "address",
-          "internalType": "contract IStaking"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "token",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "address",
-          "internalType": "contract IERC20"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "transferOwnership",
-      "stateMutability": "nonpayable",
-      "inputs": [
-        {
-          "name": "newOwner",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": []
-    },
-    {
-      "type": "function",
-      "name": "withdrawRewards",
-      "stateMutability": "nonpayable",
-      "inputs": [
-        {
-          "name": "_stakingProvider",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": []
-    }
-  ],
-  "tx_hash": "0x178f50155caea7bb32dab5cd79280c66d19a52aa2d303174fa9f5d843ba2ea91",
-  "block_number": 20410589,
-  "deployer": "0xFfFd7092685bDeeBD121D1A0FEA3c349114Cce50"
-}
diff --git a/src/threshold-ts/mas/sepolia-artifacts/TacoRegistry.json b/src/threshold-ts/mas/sepolia-artifacts/TacoRegistry.json
deleted file mode 100644
index 968c9536e..000000000
--- a/src/threshold-ts/mas/sepolia-artifacts/TacoRegistry.json
+++ /dev/null
@@ -1,1431 +0,0 @@
-{
-  "address": "0xCcFf527698E78a536d80695D9Af4F4f3265ADA05",
-  "abi": [
-    {
-      "type": "constructor",
-      "stateMutability": "nonpayable",
-      "inputs": [
-        {
-          "name": "_token",
-          "type": "address",
-          "internalType": "contract IERC20"
-        },
-        {
-          "name": "_tStaking",
-          "type": "address",
-          "internalType": "contract IStaking"
-        },
-        {
-          "name": "_minimumAuthorization",
-          "type": "uint96",
-          "internalType": "uint96"
-        },
-        {
-          "name": "_minOperatorSeconds",
-          "type": "uint256",
-          "internalType": "uint256"
-        },
-        {
-          "name": "_rewardDuration",
-          "type": "uint256",
-          "internalType": "uint256"
-        },
-        {
-          "name": "_deauthorizationDuration",
-          "type": "uint256",
-          "internalType": "uint256"
-        },
-        {
-          "name": "_commitmentDurationOptions",
-          "type": "uint64[]",
-          "internalType": "uint64[]"
-        },
-        {
-          "name": "_commitmentDeadline",
-          "type": "uint64",
-          "internalType": "uint64"
-        }
-      ]
-    },
-    {
-      "type": "error",
-      "name": "AddressEmptyCode",
-      "inputs": [
-        {
-          "name": "target",
-          "type": "address",
-          "internalType": "address"
-        }
-      ]
-    },
-    {
-      "type": "error",
-      "name": "AddressInsufficientBalance",
-      "inputs": [
-        {
-          "name": "account",
-          "type": "address",
-          "internalType": "address"
-        }
-      ]
-    },
-    {
-      "type": "error",
-      "name": "FailedInnerCall",
-      "inputs": []
-    },
-    {
-      "type": "error",
-      "name": "InvalidInitialization",
-      "inputs": []
-    },
-    {
-      "type": "error",
-      "name": "NotInitializing",
-      "inputs": []
-    },
-    {
-      "type": "error",
-      "name": "OwnableInvalidOwner",
-      "inputs": [
-        {
-          "name": "owner",
-          "type": "address",
-          "internalType": "address"
-        }
-      ]
-    },
-    {
-      "type": "error",
-      "name": "OwnableUnauthorizedAccount",
-      "inputs": [
-        {
-          "name": "account",
-          "type": "address",
-          "internalType": "address"
-        }
-      ]
-    },
-    {
-      "type": "error",
-      "name": "SafeCastOverflowedUintDowncast",
-      "inputs": [
-        {
-          "name": "bits",
-          "type": "uint8",
-          "internalType": "uint8"
-        },
-        {
-          "name": "value",
-          "type": "uint256",
-          "internalType": "uint256"
-        }
-      ]
-    },
-    {
-      "type": "error",
-      "name": "SafeERC20FailedOperation",
-      "inputs": [
-        {
-          "name": "token",
-          "type": "address",
-          "internalType": "address"
-        }
-      ]
-    },
-    {
-      "type": "event",
-      "name": "AuthorizationDecreaseApproved",
-      "inputs": [
-        {
-          "name": "stakingProvider",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        },
-        {
-          "name": "fromAmount",
-          "type": "uint96",
-          "internalType": "uint96",
-          "indexed": false
-        },
-        {
-          "name": "toAmount",
-          "type": "uint96",
-          "internalType": "uint96",
-          "indexed": false
-        }
-      ],
-      "anonymous": false
-    },
-    {
-      "type": "event",
-      "name": "AuthorizationDecreaseRequested",
-      "inputs": [
-        {
-          "name": "stakingProvider",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        },
-        {
-          "name": "fromAmount",
-          "type": "uint96",
-          "internalType": "uint96",
-          "indexed": false
-        },
-        {
-          "name": "toAmount",
-          "type": "uint96",
-          "internalType": "uint96",
-          "indexed": false
-        }
-      ],
-      "anonymous": false
-    },
-    {
-      "type": "event",
-      "name": "AuthorizationIncreased",
-      "inputs": [
-        {
-          "name": "stakingProvider",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        },
-        {
-          "name": "fromAmount",
-          "type": "uint96",
-          "internalType": "uint96",
-          "indexed": false
-        },
-        {
-          "name": "toAmount",
-          "type": "uint96",
-          "internalType": "uint96",
-          "indexed": false
-        }
-      ],
-      "anonymous": false
-    },
-    {
-      "type": "event",
-      "name": "AuthorizationInvoluntaryDecreased",
-      "inputs": [
-        {
-          "name": "stakingProvider",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        },
-        {
-          "name": "fromAmount",
-          "type": "uint96",
-          "internalType": "uint96",
-          "indexed": false
-        },
-        {
-          "name": "toAmount",
-          "type": "uint96",
-          "internalType": "uint96",
-          "indexed": false
-        }
-      ],
-      "anonymous": false
-    },
-    {
-      "type": "event",
-      "name": "AuthorizationReSynchronized",
-      "inputs": [
-        {
-          "name": "stakingProvider",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        },
-        {
-          "name": "fromAmount",
-          "type": "uint96",
-          "internalType": "uint96",
-          "indexed": false
-        },
-        {
-          "name": "toAmount",
-          "type": "uint96",
-          "internalType": "uint96",
-          "indexed": false
-        }
-      ],
-      "anonymous": false
-    },
-    {
-      "type": "event",
-      "name": "CommitmentMade",
-      "inputs": [
-        {
-          "name": "stakingProvider",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        },
-        {
-          "name": "endCommitment",
-          "type": "uint256",
-          "internalType": "uint256",
-          "indexed": false
-        }
-      ],
-      "anonymous": false
-    },
-    {
-      "type": "event",
-      "name": "Initialized",
-      "inputs": [
-        {
-          "name": "version",
-          "type": "uint64",
-          "internalType": "uint64",
-          "indexed": false
-        }
-      ],
-      "anonymous": false
-    },
-    {
-      "type": "event",
-      "name": "ManualChildSynchronizationSent",
-      "inputs": [
-        {
-          "name": "stakingProvider",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        },
-        {
-          "name": "authorized",
-          "type": "uint96",
-          "internalType": "uint96",
-          "indexed": false
-        },
-        {
-          "name": "deauthorizing",
-          "type": "uint96",
-          "internalType": "uint96",
-          "indexed": false
-        },
-        {
-          "name": "endDeauthorization",
-          "type": "uint64",
-          "internalType": "uint64",
-          "indexed": false
-        },
-        {
-          "name": "operator",
-          "type": "address",
-          "internalType": "address",
-          "indexed": false
-        }
-      ],
-      "anonymous": false
-    },
-    {
-      "type": "event",
-      "name": "OperatorBonded",
-      "inputs": [
-        {
-          "name": "stakingProvider",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        },
-        {
-          "name": "operator",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        },
-        {
-          "name": "previousOperator",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        },
-        {
-          "name": "startTimestamp",
-          "type": "uint256",
-          "internalType": "uint256",
-          "indexed": false
-        }
-      ],
-      "anonymous": false
-    },
-    {
-      "type": "event",
-      "name": "OperatorConfirmed",
-      "inputs": [
-        {
-          "name": "stakingProvider",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        },
-        {
-          "name": "operator",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        }
-      ],
-      "anonymous": false
-    },
-    {
-      "type": "event",
-      "name": "OwnershipTransferred",
-      "inputs": [
-        {
-          "name": "previousOwner",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        },
-        {
-          "name": "newOwner",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        }
-      ],
-      "anonymous": false
-    },
-    {
-      "type": "event",
-      "name": "RewardAdded",
-      "inputs": [
-        {
-          "name": "reward",
-          "type": "uint256",
-          "internalType": "uint256",
-          "indexed": false
-        }
-      ],
-      "anonymous": false
-    },
-    {
-      "type": "event",
-      "name": "RewardDistributorSet",
-      "inputs": [
-        {
-          "name": "distributor",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        }
-      ],
-      "anonymous": false
-    },
-    {
-      "type": "event",
-      "name": "RewardPaid",
-      "inputs": [
-        {
-          "name": "stakingProvider",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        },
-        {
-          "name": "beneficiary",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        },
-        {
-          "name": "reward",
-          "type": "uint256",
-          "internalType": "uint256",
-          "indexed": false
-        }
-      ],
-      "anonymous": false
-    },
-    {
-      "type": "event",
-      "name": "RewardsWithdrawn",
-      "inputs": [
-        {
-          "name": "stakingProvider",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        },
-        {
-          "name": "amount",
-          "type": "uint96",
-          "internalType": "uint96",
-          "indexed": false
-        }
-      ],
-      "anonymous": false
-    },
-    {
-      "type": "event",
-      "name": "Slashed",
-      "inputs": [
-        {
-          "name": "stakingProvider",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        },
-        {
-          "name": "penalty",
-          "type": "uint256",
-          "internalType": "uint256",
-          "indexed": false
-        },
-        {
-          "name": "investigator",
-          "type": "address",
-          "internalType": "address",
-          "indexed": true
-        },
-        {
-          "name": "reward",
-          "type": "uint256",
-          "internalType": "uint256",
-          "indexed": false
-        }
-      ],
-      "anonymous": false
-    },
-    {
-      "type": "function",
-      "name": "REWARD_PER_TOKEN_MULTIPLIER",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint256",
-          "internalType": "uint256"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "adjudicator",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "address",
-          "internalType": "address"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "approveAuthorizationDecrease",
-      "stateMutability": "nonpayable",
-      "inputs": [
-        {
-          "name": "_stakingProvider",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": []
-    },
-    {
-      "type": "function",
-      "name": "authorizationDecreaseRequested",
-      "stateMutability": "nonpayable",
-      "inputs": [
-        {
-          "name": "_stakingProvider",
-          "type": "address",
-          "internalType": "address"
-        },
-        {
-          "name": "_fromAmount",
-          "type": "uint96",
-          "internalType": "uint96"
-        },
-        {
-          "name": "_toAmount",
-          "type": "uint96",
-          "internalType": "uint96"
-        }
-      ],
-      "outputs": []
-    },
-    {
-      "type": "function",
-      "name": "authorizationIncreased",
-      "stateMutability": "nonpayable",
-      "inputs": [
-        {
-          "name": "_stakingProvider",
-          "type": "address",
-          "internalType": "address"
-        },
-        {
-          "name": "_fromAmount",
-          "type": "uint96",
-          "internalType": "uint96"
-        },
-        {
-          "name": "_toAmount",
-          "type": "uint96",
-          "internalType": "uint96"
-        }
-      ],
-      "outputs": []
-    },
-    {
-      "type": "function",
-      "name": "authorizationParameters",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "_minimumAuthorization",
-          "type": "uint96",
-          "internalType": "uint96"
-        },
-        {
-          "name": "authorizationDecreaseDelay",
-          "type": "uint64",
-          "internalType": "uint64"
-        },
-        {
-          "name": "authorizationDecreaseChangePeriod",
-          "type": "uint64",
-          "internalType": "uint64"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "authorizedOverall",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint96",
-          "internalType": "uint96"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "authorizedStake",
-      "stateMutability": "view",
-      "inputs": [
-        {
-          "name": "_stakingProvider",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint96",
-          "internalType": "uint96"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "availableRewards",
-      "stateMutability": "view",
-      "inputs": [
-        {
-          "name": "_stakingProvider",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint96",
-          "internalType": "uint96"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "bondOperator",
-      "stateMutability": "nonpayable",
-      "inputs": [
-        {
-          "name": "_stakingProvider",
-          "type": "address",
-          "internalType": "address"
-        },
-        {
-          "name": "_operator",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": []
-    },
-    {
-      "type": "function",
-      "name": "childApplication",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "address",
-          "internalType": "contract ITACoRootToChild"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "commitmentDeadline",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint64",
-          "internalType": "uint64"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "commitmentDurationOption1",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint64",
-          "internalType": "uint64"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "commitmentDurationOption2",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint64",
-          "internalType": "uint64"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "commitmentDurationOption3",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint64",
-          "internalType": "uint64"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "commitmentDurationOption4",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint64",
-          "internalType": "uint64"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "confirmOperatorAddress",
-      "stateMutability": "nonpayable",
-      "inputs": [
-        {
-          "name": "_operator",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": []
-    },
-    {
-      "type": "function",
-      "name": "deauthorizationDuration",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint256",
-          "internalType": "uint256"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "eligibleStake",
-      "stateMutability": "view",
-      "inputs": [
-        {
-          "name": "_stakingProvider",
-          "type": "address",
-          "internalType": "address"
-        },
-        {
-          "name": "_endDate",
-          "type": "uint256",
-          "internalType": "uint256"
-        }
-      ],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint96",
-          "internalType": "uint96"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "getActiveStakingProviders",
-      "stateMutability": "view",
-      "inputs": [
-        {
-          "name": "_startIndex",
-          "type": "uint256",
-          "internalType": "uint256"
-        },
-        {
-          "name": "_maxStakingProviders",
-          "type": "uint256",
-          "internalType": "uint256"
-        },
-        {
-          "name": "_cohortDuration",
-          "type": "uint32",
-          "internalType": "uint32"
-        }
-      ],
-      "outputs": [
-        {
-          "name": "allAuthorizedTokens",
-          "type": "uint256",
-          "internalType": "uint256"
-        },
-        {
-          "name": "activeStakingProviders",
-          "type": "bytes32[]",
-          "internalType": "bytes32[]"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "getBeneficiary",
-      "stateMutability": "view",
-      "inputs": [
-        {
-          "name": "_stakingProvider",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": [
-        {
-          "name": "beneficiary",
-          "type": "address",
-          "internalType": "address payable"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "getStakingProvidersLength",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint256",
-          "internalType": "uint256"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "initialize",
-      "stateMutability": "nonpayable",
-      "inputs": [],
-      "outputs": []
-    },
-    {
-      "type": "function",
-      "name": "involuntaryAuthorizationDecrease",
-      "stateMutability": "nonpayable",
-      "inputs": [
-        {
-          "name": "_stakingProvider",
-          "type": "address",
-          "internalType": "address"
-        },
-        {
-          "name": "_fromAmount",
-          "type": "uint96",
-          "internalType": "uint96"
-        },
-        {
-          "name": "_toAmount",
-          "type": "uint96",
-          "internalType": "uint96"
-        }
-      ],
-      "outputs": []
-    },
-    {
-      "type": "function",
-      "name": "isAuthorized",
-      "stateMutability": "view",
-      "inputs": [
-        {
-          "name": "_stakingProvider",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": [
-        {
-          "name": "",
-          "type": "bool",
-          "internalType": "bool"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "isOperatorConfirmed",
-      "stateMutability": "view",
-      "inputs": [
-        {
-          "name": "_operator",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": [
-        {
-          "name": "",
-          "type": "bool",
-          "internalType": "bool"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "lastTimeRewardApplicable",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint256",
-          "internalType": "uint256"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "lastUpdateTime",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint256",
-          "internalType": "uint256"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "makeCommitment",
-      "stateMutability": "nonpayable",
-      "inputs": [
-        {
-          "name": "_stakingProvider",
-          "type": "address",
-          "internalType": "address"
-        },
-        {
-          "name": "_commitmentDuration",
-          "type": "uint64",
-          "internalType": "uint64"
-        }
-      ],
-      "outputs": []
-    },
-    {
-      "type": "function",
-      "name": "manualChildSynchronization",
-      "stateMutability": "nonpayable",
-      "inputs": [
-        {
-          "name": "_stakingProvider",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": []
-    },
-    {
-      "type": "function",
-      "name": "minOperatorSeconds",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint256",
-          "internalType": "uint256"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "minimumAuthorization",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint96",
-          "internalType": "uint96"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "operatorToStakingProvider",
-      "stateMutability": "view",
-      "inputs": [
-        {
-          "name": "_operator",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": [
-        {
-          "name": "",
-          "type": "address",
-          "internalType": "address"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "owner",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "address",
-          "internalType": "address"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "pendingAuthorizationDecrease",
-      "stateMutability": "view",
-      "inputs": [
-        {
-          "name": "_stakingProvider",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint96",
-          "internalType": "uint96"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "periodFinish",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint256",
-          "internalType": "uint256"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "pushReward",
-      "stateMutability": "nonpayable",
-      "inputs": [
-        {
-          "name": "_reward",
-          "type": "uint96",
-          "internalType": "uint96"
-        }
-      ],
-      "outputs": []
-    },
-    {
-      "type": "function",
-      "name": "registerOperator",
-      "stateMutability": "nonpayable",
-      "inputs": [
-        {
-          "name": "_operator",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": []
-    },
-    {
-      "type": "function",
-      "name": "remainingAuthorizationDecreaseDelay",
-      "stateMutability": "view",
-      "inputs": [
-        {
-          "name": "_stakingProvider",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint64",
-          "internalType": "uint64"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "renounceOwnership",
-      "stateMutability": "nonpayable",
-      "inputs": [],
-      "outputs": []
-    },
-    {
-      "type": "function",
-      "name": "resynchronizeAuthorization",
-      "stateMutability": "nonpayable",
-      "inputs": [
-        {
-          "name": "_stakingProvider",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": []
-    },
-    {
-      "type": "function",
-      "name": "rewardDistributor",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "address",
-          "internalType": "address"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "rewardDuration",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint256",
-          "internalType": "uint256"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "rewardPerToken",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint160",
-          "internalType": "uint160"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "rewardPerTokenStored",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint160",
-          "internalType": "uint160"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "rewardRateDecimals",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "uint256",
-          "internalType": "uint256"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "setAdjudicator",
-      "stateMutability": "nonpayable",
-      "inputs": [
-        {
-          "name": "_adjudicator",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": []
-    },
-    {
-      "type": "function",
-      "name": "setChildApplication",
-      "stateMutability": "nonpayable",
-      "inputs": [
-        {
-          "name": "_childApplication",
-          "type": "address",
-          "internalType": "contract ITACoRootToChild"
-        }
-      ],
-      "outputs": []
-    },
-    {
-      "type": "function",
-      "name": "setRewardDistributor",
-      "stateMutability": "nonpayable",
-      "inputs": [
-        {
-          "name": "_rewardDistributor",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": []
-    },
-    {
-      "type": "function",
-      "name": "slash",
-      "stateMutability": "nonpayable",
-      "inputs": [
-        {
-          "name": "_stakingProvider",
-          "type": "address",
-          "internalType": "address"
-        },
-        {
-          "name": "_penalty",
-          "type": "uint96",
-          "internalType": "uint96"
-        },
-        {
-          "name": "_investigator",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": []
-    },
-    {
-      "type": "function",
-      "name": "stakingProviderInfo",
-      "stateMutability": "view",
-      "inputs": [
-        {
-          "name": "",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": [
-        {
-          "name": "operator",
-          "type": "address",
-          "internalType": "address"
-        },
-        {
-          "name": "operatorConfirmed",
-          "type": "bool",
-          "internalType": "bool"
-        },
-        {
-          "name": "operatorStartTimestamp",
-          "type": "uint64",
-          "internalType": "uint64"
-        },
-        {
-          "name": "authorized",
-          "type": "uint96",
-          "internalType": "uint96"
-        },
-        {
-          "name": "deauthorizing",
-          "type": "uint96",
-          "internalType": "uint96"
-        },
-        {
-          "name": "endDeauthorization",
-          "type": "uint64",
-          "internalType": "uint64"
-        },
-        {
-          "name": "tReward",
-          "type": "uint96",
-          "internalType": "uint96"
-        },
-        {
-          "name": "rewardPerTokenPaid",
-          "type": "uint160",
-          "internalType": "uint160"
-        },
-        {
-          "name": "endCommitment",
-          "type": "uint64",
-          "internalType": "uint64"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "stakingProviderToOperator",
-      "stateMutability": "view",
-      "inputs": [
-        {
-          "name": "_stakingProvider",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": [
-        {
-          "name": "",
-          "type": "address",
-          "internalType": "address"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "stakingProviders",
-      "stateMutability": "view",
-      "inputs": [
-        {
-          "name": "",
-          "type": "uint256",
-          "internalType": "uint256"
-        }
-      ],
-      "outputs": [
-        {
-          "name": "",
-          "type": "address",
-          "internalType": "address"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "tStaking",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "address",
-          "internalType": "contract IStaking"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "token",
-      "stateMutability": "view",
-      "inputs": [],
-      "outputs": [
-        {
-          "name": "",
-          "type": "address",
-          "internalType": "contract IERC20"
-        }
-      ]
-    },
-    {
-      "type": "function",
-      "name": "transferOwnership",
-      "stateMutability": "nonpayable",
-      "inputs": [
-        {
-          "name": "newOwner",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": []
-    },
-    {
-      "type": "function",
-      "name": "withdrawRewards",
-      "stateMutability": "nonpayable",
-      "inputs": [
-        {
-          "name": "_stakingProvider",
-          "type": "address",
-          "internalType": "address"
-        }
-      ],
-      "outputs": []
-    }
-  ],
-  "tx_hash": "0x4824e7d3b6dae9ec69b79b9f0578853c51fd92a49b0edce45d892d6cdf7901bd",
-  "block_number": 5048617,
-  "deployer": "0x3B42d26E19FF860bC4dEbB920DD8caA53F93c600"
-}