From 3db541e778f13120dc77f874cd850bbf42275364 Mon Sep 17 00:00:00 2001 From: evandrosaturnino Date: Tue, 12 Nov 2024 10:00:22 -0300 Subject: [PATCH 01/32] 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 e7f53f4d5..1afd722c7 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 @@ -27,4 +26,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 d7fa0d572..0e3469729 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 }} @@ -60,6 +59,7 @@ jobs: TRM_API_KEY: ${{ secrets.TEST_TRM_API_KEY }} 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 }} @@ -68,9 +68,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 }} @@ -83,6 +82,7 @@ jobs: TRM_API_KEY: ${{ secrets.MAINNET_TRM_API_KEY }} 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 cad3cdc6c..70bbb6327 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= -REACT_APP_ETH_HOSTNAME_WS= +REACT_APP_DEFAULT_PROVIDER_CHAIN_ID=11155111 +REACT_APP_ALCHEMY_API= // 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/ -REACT_APP_ETH_HOSTNAME_WS=wss://sepolia.infura.io/v3/ +REACT_APP_DEFAULT_PROVIDER_CHAIN_ID=11155111 +REACT_APP_ALCHEMY_API= 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 5951a52e8..346d84757 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", @@ -27,7 +27,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 = 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 3cf9bc206f54860b8a9ea6bfffbadd92cc79d1c7 Mon Sep 17 00:00:00 2001 From: evandrosaturnino Date: Tue, 12 Nov 2024 10:01:10 -0300 Subject: [PATCH 02/32] 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 4b05db181916fc8b7453a7199d78d7e802e3d2f1 Mon Sep 17 00:00:00 2001 From: evandrosaturnino Date: Tue, 12 Nov 2024 10:12:15 -0300 Subject: [PATCH 03/32] 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 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 = ({ transactionHash, }) => { const { isOpen, onToggle } = useDisclosure() + const { chainId } = useIsActive() const errorTitle = "Error" @@ -113,6 +115,7 @@ const TransactionFailed: FC = ({ 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 type: Exclude + ethereumNetworkChainId?: string | number | never } | { chain?: Extract | never type: ExplorerDataType + ethereumNetworkChainId?: string | number | never } type CommonProps = { @@ -48,9 +55,14 @@ const ViewInBlockExplorer: FC = ({ type, text = "View in Block Explorer", chain = "ethereum", + ethereumNetworkChainId, ...restProps }) => { - const link = createLinkToBlockExplorerForChain[chain](id, type) + const link = createLinkToBlockExplorerForChain[chain]( + id, + type, + ethereumNetworkChainId + ) return ( 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, @@ -16,7 +17,7 @@ export const BridgeContractLink: FC = ({ ...props }) => { const address = useTBTCBridgeContractAddress() - return ( + return address ? ( = ({ {...props} data-ph-capture-attribute-button-name={`Bridge contract link (Deposit flow)`} /> + ) : ( + <> ) } @@ -31,13 +34,17 @@ export const TBTCTokenContractLink: FC = ({ text = "token address", ...props }) => { + const { chainId } = useIsActive() const address = useTBTCTokenAddress() - return ( + return address ? ( + ) : ( + <> ) } 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("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 = ({ children, }) => { const titleTextColor = useColorModeValue("gray.700", "gray.300") + const { chainId } = useIsActive() useEffect(() => { if (!isCompleted) return @@ -85,9 +87,10 @@ export const BridgeProcessStep: FC = ({ See transaction on{" "} 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 ae9a326d75606c7ec37ec81340d46efaec2af8ec Mon Sep 17 00:00:00 2001 From: evandrosaturnino Date: Tue, 12 Nov 2024 10:20:16 -0300 Subject: [PATCH 04/32] 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> = (props) => { const tbtcTokenContractAddress = useTBTCTokenAddress() const bridgeContractAddress = useTBTCBridgeContractAddress() + const { chainId } = useIsActive() return ( Contracts - - + {tbtcTokenContractAddress && ( + + )} + {bridgeContractAddress && ( + + )} ) 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 { + 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 { + 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 { + 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 { + 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 private walletConnectProjectId: string - constructor(args: Required) { - super({ - supportedChainIds: Object.keys(args.rpc).map((chainId) => - Number(chainId) - ), - }) + constructor({ + supportedChainIds, + rpc, + walletConnectProjectId, + }: Required) { + 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 { + this.handleChainChanged(chainId.toString()) + } + public async activate(): Promise { 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 10af473cf4bc7e1d51e78f14124570652c363ef5 Mon Sep 17 00:00:00 2001 From: evandrosaturnino Date: Tue, 12 Nov 2024 10:26:36 -0300 Subject: [PATCH 05/32] 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/index.ts | 1 - src/enums/trmNetworks.ts | 3 - 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/chainIdToTrmNetworkName.ts | 18 --- src/utils/createEtherscanLink.ts | 45 ------ src/utils/isSupportedNetwork.ts | 7 - 30 files changed, 542 insertions(+), 125 deletions(-) delete mode 100644 src/enums/trmNetworks.ts 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/chainIdToTrmNetworkName.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 = () => { Incorrect Network - Please connect to {chainIdToNetworkName(supportedChainId)} + Please connect to a supported network. 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 = ({ transactionHash, pendingText = "Pending...", }) => { + const { chainId } = useIsActive() + return ( <> Confirm (pending) @@ -36,6 +39,7 @@ const TransactionIsPending: FC = ({ text="View" id={transactionHash} type={ExplorerDataType.TRANSACTION} + ethereumNetworkChainId={chainId} />{" "} transaction on Etherscan 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 = ({ transactionHash, }) => { const { closeModal } = useModal() + const { chainId } = useIsActive() return ( <> @@ -69,6 +71,7 @@ const StakingSuccessModal: FC = ({ text="View" id={transactionHash} type={ExplorerDataType.TRANSACTION} + ethereumNetworkChainId={chainId} />{" "} transaction on Etherscan 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 = ({ mt="2rem" > This action is reversible via the{" "} - + {contract ? ( + + ) : ( + "vending machine contract." + )} 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({ btcAccount: undefined, setEthAccount: () => {}, setBtcAccount: () => {}, + ethAccountChainId: undefined, ledgerLiveAppEthereumSigner: undefined, }) export const LedgerLiveAppProvider: React.FC = ({ children }) => { + const { chainId } = useIsActive() const [ethAccount, _setEthAccount] = useState(undefined) + const [ethAccountChainId, setEthAccountChainId] = useState< + number | undefined + >(undefined) const [btcAccount, setBtcAccount] = useState(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 ( { setEthAccount, btcAccount, setBtcAccount, + ethAccountChainId, ledgerLiveAppEthereumSigner, }} > diff --git a/src/enums/index.ts b/src/enums/index.ts index eb735926d..a12c2d01d 100644 --- a/src/enums/index.ts +++ b/src/enums/index.ts @@ -5,5 +5,4 @@ export * from "./pool" export * from "./staking" export * from "./token" export * from "./transactionType" -export * from "./trmNetworks" export * from "./web3" diff --git a/src/enums/trmNetworks.ts b/src/enums/trmNetworks.ts deleted file mode 100644 index 84218c76a..000000000 --- a/src/enums/trmNetworks.ts +++ /dev/null @@ -1,3 +0,0 @@ -export enum TrmNetworksChainId { - ethereum = 1, -} 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 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( + 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/chainIdToTrmNetworkName.ts b/src/utils/chainIdToTrmNetworkName.ts deleted file mode 100644 index 78833c9ed..000000000 --- a/src/utils/chainIdToTrmNetworkName.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { TrmNetworksChainId } from "../enums" - -type TrmNetworksMap = { - [chainId: number]: string -} - -const trmNetworksMap: TrmNetworksMap = { - [TrmNetworksChainId.ethereum]: "ethereum", -} - -const chainIdToTrmNetworkName = ( - chainId: string | number = 1 -): string | null => { - const network = trmNetworksMap[Number(chainId)] - return network || null -} - -export default chainIdToTrmNetworkName 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 40383bd81bf209f5ddaafedafd2a3049885e3700 Mon Sep 17 00:00:00 2001 From: evandrosaturnino Date: Tue, 12 Nov 2024 10:36:44 -0300 Subject: [PATCH 06/32] 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/utils/trmAPI.ts | 2 +- 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 - 65 files changed, 23801 insertions(+), 256 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 = 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 => { - 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 ] => { + const { chainId } = useIsActive() const [rawData, setRawData] = useState(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 = [] + + 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 & { tStakingContractAddress: string } diff --git a/src/store/account/effects.ts b/src/store/account/effects.ts index eeb1af0e1..20f8b913a 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 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([ + ["TacoRegistry", TacoRegistryArtifactMainnet], + ["LegacyKeepStaking", LegacyKeepStakingArtifactMainnet], + ["RandomBeacon", RandomBeaconArtifactMainnet], + ["TokenStaking", StakingArtifactMainnet], ["Bridge", BridgeArtifactMainnet], ["NuCypherStakingEscrow", NuCypherStakingEscrowMainnet], ["NuCypherToken", NuCypherTokenMainnet], @@ -63,6 +84,10 @@ const mainnetArtifacts = new Map([ ["VendingMachineNuCypher", VendingMachineNuCypherMainnet], ]) const testnetArtifacts = new Map([ + ["TacoRegistry", TacoRegistryArtifactSepolia], + ["LegacyKeepStaking", LegacyKeepStakingArtifactSepolia], + ["RandomBeacon", RandomBeaconArtifactSepolia], + ["TokenStaking", StakingArtifactSepolia], ["Bridge", BridgeArtifactSepolia], ["NuCypherStakingEscrow", NuCypherStakingEscrowSepolia], ["NuCypherToken", NuCypherTokenSepolia], @@ -73,6 +98,10 @@ const testnetArtifacts = new Map([ ["VendingMachineNuCypher", VendingMachineNuCypherSepolia], ]) const testnetDevelopmentArtifacts = new Map([ + ["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 = { @@ -7,19 +7,28 @@ const stakingAppNameToAppLabel: Record = { taco: "TACo", } -const stakingAppAddressToAppName: Record = { - [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 = { + [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/utils/trmAPI.ts b/src/utils/trmAPI.ts index 014f1f200..986d93c08 100644 --- a/src/utils/trmAPI.ts +++ b/src/utils/trmAPI.ts @@ -1,7 +1,7 @@ import axios from "axios" import { getEnvVariable } from "./getEnvVariable" import { EnvVariable } from "../enums" -import chainIdToTrmNetworkName from "./chainIdToTrmNetworkName" +import { chainIdToTrmNetworkName } from "../networks/utils" import { TrmAccountDetails } from "../types" interface WalletScreeningRequest { 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( address: string, @@ -21,9 +19,7 @@ export function useContract( 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 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 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 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 + [SupportedChainIds.Localhost]: AddressZero, +} as Record + +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 - 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 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 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 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 + +// 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 + +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 5edbf2623f2bf90b2c55b8bd0ab22bb119a4d7a4 Mon Sep 17 00:00:00 2001 From: evandrosaturnino Date: Tue, 12 Nov 2024 10:38:26 -0300 Subject: [PATCH 07/32] 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 } /** @@ -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 => { + 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> => { // 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[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, @@ -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 e24ceb688df5773a9d055dcc6a263389b56294a6 Mon Sep 17 00:00:00 2001 From: evandrosaturnino Date: Tue, 12 Nov 2024 10:41:19 -0300 Subject: [PATCH 08/32] 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 = ({ - {chainId && } + {chainId && } = ({ 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: , - bg: "gray.700", + const iconMap: Record = { + [SupportedChainIds.Ethereum]: { + icon: , + bg: grayBackground, + }, + [SupportedChainIds.Sepolia]: { + icon: , + bg: grayBackground, + }, + [SupportedChainIds.Arbitrum]: { + icon: , + bg: grayBackground, + }, + [SupportedChainIds.ArbitrumSepolia]: { + icon: , + bg: grayBackground, }, - [ChainID.Sepolia]: { + [SupportedChainIds.Base]: { icon: , bg: grayBackground }, + [SupportedChainIds.BaseSepolia]: { + icon: , + bg: "blue.500", + }, + } + + return ( + iconMap[chainId] || { icon: ( ), - bg: "yellow.500", - }, - } + bg: "red.500", + } + ) +} - const networkIcon = networkIconMap[chainId || 0] || { - icon: ( - - ), - 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 ( + switchNetwork(network.chainId)} + iconSpacing="4" + display="flex" + gap="3" + > + {icon} + {network.chainParameters?.chainName} + + ) + }) return ( <> {/* Mobile */} - + + {({ isOpen }) => ( + <> + + {networkIcon.icon} + {isOpen ? : } + + } + aria-label="network" + /> + {renderMenuItems()} + + )} + {/* Desktop */} - + + {({ isOpen }) => ( + <> + : } + display={{ base: "none", md: "inherit" }} + > + {chainIdToChainParameterName(chainId)} + + {renderMenuItems()} + + )} + ) } 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: ( + + + + + + + + + + + + + + + + + + + + ), +}) 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: ( + <> + + + + ), +}) From d0dda9ddbecee799995c957081fae97d59f0b568 Mon Sep 17 00:00:00 2001 From: evandrosaturnino Date: Tue, 12 Nov 2024 10:42:19 -0300 Subject: [PATCH 09/32] 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 30ba8c22c31ddd01d1f7b386a63460793bd8d6b7 Mon Sep 17 00:00:00 2001 From: evandrosaturnino Date: Tue, 12 Nov 2024 10:43:23 -0300 Subject: [PATCH 10/32] 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 = ({ stakingProvider, txHash, decreaseAmount, + stakingAppName, closeModal, }) => { return ( @@ -45,8 +48,10 @@ const DeauthorizationInitiatedBase: FC = ({ - 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.`} @@ -76,12 +81,14 @@ const DeauthorizationInitiatedBase: FC = ({ - 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. 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 = ({ [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> = ( - 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. From 1dc44894d7e4e3ba66c6ca366ee8645320c888ea Mon Sep 17 00:00:00 2001 From: evandrosaturnino Date: Tue, 12 Nov 2024 10:45:18 -0300 Subject: [PATCH 11/32] 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 ( 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 + /** + * 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 + /** * Removes the deposit data assigned to `this._deposit` property. */ @@ -228,6 +253,19 @@ export interface ITBTC { depositScriptParameters: DepositScriptParameters ): Promise + /** + * 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 + /** * 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 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 { + 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 { 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 => { 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 => { + 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 => { const sdk = await this._getSdk() this._deposit = await sdk.deposits.initiateDeposit(btcRecoveryAddress) return this._deposit } + initiateCrossChainDeposit = async ( + btcRecoveryAddress: string, + chainId: number + ): Promise => { + 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 + ) + return this._deposit + } + removeDepositData = (): void => { this._deposit = undefined } @@ -606,19 +710,19 @@ export class TBTC implements ITBTC { ): Promise => { 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 => { + 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 + ) + + 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 => { 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 => { + 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> => { + 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> => { + 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 => { - 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 a07c8ff6f61bffa7611b249052b0b699e17666a6 Mon Sep 17 00:00:00 2001 From: evandrosaturnino Date: Tue, 12 Nov 2024 10:46:49 -0300 Subject: [PATCH 12/32] 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( - key, - {} - ) + const [tBTCDepositData, setTBTCLocalStorageData] = + useState({}) + + 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(key, newLocalStorageData) + writeStorage( + `${key}-${chainId?.toString()}`, + newLocalStorageData + ) } export function removeDataForAccount( account: string, - prevData: TBTCLocalStorageDepositData + prevData: TBTCLocalStorageDepositData, + chainId?: number | string ) { const newLocalStorageData = { ...prevData, } delete newLocalStorageData[`${account}`] - writeStorage(key, newLocalStorageData) + writeStorage( + `${key}-${chainId?.toString()}`, + newLocalStorageData + ) } From c7b1237b85b8c9b0dad32881dffa8e1c426d5896 Mon Sep 17 00:00:00 2001 From: evandrosaturnino Date: Tue, 12 Nov 2024 10:47:13 -0300 Subject: [PATCH 13/32] 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 = ({ // 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 = ({ + l2TransactionType, onSubmit, isLoading, isDisabled, @@ -21,8 +25,12 @@ const SubmitTxButton: FC = ({ 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 = ({ return ( { 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< - + {featureFlags.MULTI_APP_STAKING ? "Continue" : "Stake"} 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 > = ({ 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<
You're about to initiate the decrease of your{" "} - {getStakingAppLabelFromAppName(stakingAppName)} authorization. + {getStakingAppLabelFromAppName(appName)} authorization.
Initiation and confirmation of deauthorization is a two step action. @@ -78,7 +86,7 @@ const InitiateDeauthorization: FC< )}
- 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. - 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< - Initiate + + Initiate + ) 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<
- + Map Address 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 = ({ applications, closeModal, }) => { + const threshold = useThreshold() const tbtcAppAuthData = useAppSelector((state) => selectStakingAppByStakingProvider(state, "tbtc", stakingProvider) ) @@ -102,7 +104,11 @@ const AuthorizeStakingAppsBase: FC = ({ - + Authorize 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 = ({ 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 = ({ - + Confirm Deauthorization 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 = ({ stakingProvider, - stakingAppName, + appName, increaseAmount, closeModal, }) => { + const threshold = useThreshold() + const appContract = + threshold.multiAppStaking[appNameToThresholdApp[appName]]?.contract const { openModal } = useModal() const onSuccess = useCallback( (receipt) => { @@ -50,7 +57,7 @@ const IncreaseAuthorizationBase: FC = ({ [openModal, stakingProvider, increaseAmount] ) const { sendTransaction } = useIncreaseAuthorizationTransaction( - stakingAppName, + appName, onSuccess ) @@ -71,7 +78,7 @@ const IncreaseAuthorizationBase: FC = ({ = ({ - + Authorize Increase 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 = () => { 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 = () => { Cancel 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 = ({ [authorizedAmount] ) const { sendTransaction } = useSendTransactionFromFn( - threshold.multiAppStaking![stakingAppNameToThresholdAppService["taco"]] - .makeCommitment, + threshold.multiAppStaking.taco?.makeCommitment!, onSuccess ) @@ -167,6 +165,7 @@ const TACoCommitmentModal: FC = ({ Cancel 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 = { @@ -52,6 +53,7 @@ const LegacyTopUpModal: FC = ({ // 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 = ({ submitButtonText="Top-up" maxTokenAmount={tBalance} shouldDisplayMaxAmountInLabel + isDisabled={!stakingContract} /> {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( @@ -80,6 +81,7 @@ const TopupTModal: FC< Cancel { 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 { 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 = ({ }) => { 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 = ({ mt="2rem" > This action is reversible via the{" "} - {contract ? ( + {vendingMachineContract ? ( @@ -83,6 +83,7 @@ const TransactionIdle: FC = ({ Cancel { 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 = ({ Cancel { 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 ( void } const SubmitTxButton: FC = ({ - l2TransactionType, onSubmit, isLoading, isDisabled, @@ -25,12 +21,9 @@ const SubmitTxButton: FC = ({ 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 = ({ 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 = ({ 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 ( - + 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( - 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} /> )} @@ -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<{ )} {status === "deauthorization-initiation-needed" && ( - + Activate Deauthorization Request )} 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) => ( !!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<{ { const ResumeDepositForm: FC> = (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> = (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. */} 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 = ({ maxTokenAmount, bitcoinNetwork, }) => { + const threshold = useThreshold() const supportedPrefixesText = getBridgeBTCSupportedAddressPrefixesText( "unmint", bitcoinNetwork @@ -195,6 +196,7 @@ const UnmintFormBase: FC = ({ 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 20f8b913a..1be58ec11 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 => { 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 { - const calls: ContractCall[] = [ - { + async getSupportedAppsAuthParameters(): Promise< + Partial + > { + const calls: ContractCall[] = [] + const results: Partial = {} + + 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 { - const calls: ContractCall[] = [ - { + ): Promise> { + const calls: ContractCall[] = [] + const results: Partial = {} + + 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> /** - * 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 { + 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 => { + 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 => { - 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 => { + 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 => { + 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> => { - 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 => { + 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([ - ["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([ - ["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([ - ["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 => { 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 = { } 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 = { - [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 2e211a5fa87085021195a1a607a81a12e8bf6cd4 Mon Sep 17 00:00:00 2001 From: evandrosaturnino Date: Wed, 27 Nov 2024 05:18:23 -0300 Subject: [PATCH 26/32] 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 ( { 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 => { - if (!address || !threshold.staking) { + async ( + address?: string, + chainId?: string | number + ): Promise => { + 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 } > - - {_isFetching && } - {error && <>{error}} - {wasDataFetched && ( - <> - - - {!(shouldDisplaySuccessStep || shouldForceIsProcessCompleted) && ( - - {" "} - - In progress... - - )} - - - - - usual duration - 3-5 hours - - - - - - - - - - tBTC unwrapped - - - {error} + ) : ( + + {_isFetching && } + {wasDataFetched && ( + <> + + - - - {(isProcessCompleted || shouldForceIsProcessCompleted) && ( + {!( + shouldDisplaySuccessStep || shouldForceIsProcessCompleted + ) && ( + + {" "} + - In progress... + + )} + + + + + usual duration - 3-5 hours + + + + { right="0" textAlign="center" /> - )} - - - - - BTC sent - - - - {shouldDisplaySuccessStep || shouldForceIsProcessCompleted ? ( - - ) : ( - } - onComplete={() => setShouldDisplaySuccessStep(true)} - isIndeterminate - > - - Your redemption request is being processed. This will take - around 3-5 hours. - - - )} - - )} - + + + + + tBTC unwrapped + + + + + + {(isProcessCompleted || + shouldForceIsProcessCompleted) && ( + + )} + + + + + BTC sent + + + + {shouldDisplaySuccessStep || shouldForceIsProcessCompleted ? ( + + ) : ( + } + onComplete={() => setShouldDisplaySuccessStep(true)} + isIndeterminate + > + + Your redemption request is being processed. This will take + around 3-5 hours. + + + )} + + )} + + )} 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 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 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 -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 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 -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 dc729ba6614f7c9e0894a8a785d59f072dba6532 Mon Sep 17 00:00:00 2001 From: evandrosaturnino Date: Thu, 28 Nov 2024 06:04:51 -0300 Subject: [PATCH 27/32] 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({ + 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, }} > (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) && ( + + )} 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) + {/* 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. */} { - const { tBTCMintAmount, mintingFee, thresholdNetworkFee, ethAddress } = - useTbtcState() + const { + tBTCMintAmount, + mintingFee, + thresholdNetworkFee, + ethAddress, + crossChainFee, + } = useTbtcState() + const { chainId } = useIsActive() return ( @@ -31,6 +39,16 @@ const MintingTransactionDetails = () => { precision={6} higherPrecision={8} /> + {(chainId === SupportedChainIds.Arbitrum || + chainId === SupportedChainIds.ArbitrumSepolia) && ( + + )} { + const { + data: { depositTreasuryFeeDivisor, depositRevealedTxHash, depositTxMaxFee }, + } = useFetchTBTCFees() + + const { chainId } = useIsActive() + + return ( + + + + {(chainId === SupportedChainIds.Arbitrum || + chainId === SupportedChainIds.ArbitrumSepolia) && ( + + )} + + ) +} + +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> => { - 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 940c484cef77457275e083f7c05829ecf0add024 Mon Sep 17 00:00:00 2001 From: evandrosaturnino Date: Thu, 28 Nov 2024 06:23:20 -0300 Subject: [PATCH 28/32] 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 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 { + 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 62c5730763b47acc2f6aaf1eba116b5762d9110c Mon Sep 17 00:00:00 2001 From: evandrosaturnino Date: Thu, 28 Nov 2024 20:38:31 -0300 Subject: [PATCH 29/32] 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 = ({ , "tokenAmount" > & - Pick & { tokenAmount?: string } + Pick & { + 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 ( - - + + 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({ - 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 = () => { @@ -611,8 +611,8 @@ const StepSwitcher: FC = () => { chainId === SupportedChainIds.ArbitrumSepolia) && ( 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<{ 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 = () => { @@ -43,8 +43,8 @@ const MintingTransactionDetails = () => { chainId === SupportedChainIds.ArbitrumSepolia) && ( 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 = () => { {(chainId === SupportedChainIds.Arbitrum || chainId === SupportedChainIds.ArbitrumSepolia) && ( )} From 63705c788b4cab1955f8b33351a059ff929d553a Mon Sep 17 00:00:00 2001 From: evandrosaturnino Date: Fri, 29 Nov 2024 00:04:21 -0300 Subject: [PATCH 30/32] 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 = ({ 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 = ({ Confirm your deauthorization. Date: Tue, 10 Dec 2024 17:53:11 -0300 Subject: [PATCH 31/32] 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> = ( 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. 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 2a56e56936db11509dc68df9d6c5fb29ad545f09 Mon Sep 17 00:00:00 2001 From: evandrosaturnino Date: Tue, 10 Dec 2024 17:55:06 -0300 Subject: [PATCH 32/32] 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) => { 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 }