diff --git a/.env.example b/.env.example index c9ffec237..9e876f45b 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 @@ -19,11 +18,16 @@ REACT_APP_FEATURE_FLAG_SENTRY=false REACT_APP_SENTRY_DSN=$SENTRY_DSN REACT_APP_FEATURE_FLAG_TRM=false -REACT_APP_ELECTRUM_PROTOCOL=$ELECTRUM_PROTOCOL -REACT_APP_ELECTRUM_HOST=$ELECTRUM_HOST -REACT_APP_ELECTRUM_PORT=$ELECTRUM_PORT +REACT_APP_MAINNET_ELECTRUM_PROTOCOL=$MAINNET_ELECTRUM_PROTOCOL +REACT_APP_MAINNET_ELECTRUM_HOST=$MAINNET_ELECTRUM_HOST +REACT_APP_MAINNET_ELECTRUM_PORT=$MAINNET_ELECTRUM_PORT +REACT_APP_TESTNET_ELECTRUM_PROTOCOL=$TESTNET_ELECTRUM_PROTOCOL +REACT_APP_TESTNET_ELECTRUM_HOST=$TESTNET_ELECTRUM_HOST +REACT_APP_TESTNET_ELECTRUM_PORT=$TESTNET_ELECTRUM_PORT REACT_APP_MOCK_BITCOIN_CLIENT=true REACT_APP_WALLET_CONNECT_PROJECT_ID=$WALLET_CONNECT_PROJECT_ID +REACT_APP_TBTC_SUBGRAPH_API=$TBTC_SUBGRAPH_API + REACT_APP_TACO_DOMAIN=dashboard diff --git a/.env.production b/.env.production index e7f53f4d5..df08a6bba 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 @@ -21,10 +20,16 @@ REACT_APP_SENTRY_DSN=$SENTRY_DSN REACT_APP_TRM_API_KEY=$TRM_API_KEY REACT_APP_FEATURE_FLAG_TRM=$TRM_SUPPORT -REACT_APP_ELECTRUM_PROTOCOL=$ELECTRUM_PROTOCOL -REACT_APP_ELECTRUM_HOST=$ELECTRUM_HOST -REACT_APP_ELECTRUM_PORT=$ELECTRUM_PORT +REACT_APP_MAINNET_ELECTRUM_PROTOCOL=$MAINNET_ELECTRUM_PROTOCOL +REACT_APP_MAINNET_ELECTRUM_HOST=$MAINNET_ELECTRUM_HOST +REACT_APP_MAINNET_ELECTRUM_PORT=$MAINNET_ELECTRUM_PORT +REACT_APP_TESTNET_ELECTRUM_PROTOCOL=$TESTNET_ELECTRUM_PROTOCOL +REACT_APP_TESTNET_ELECTRUM_HOST=$TESTNET_ELECTRUM_HOST +REACT_APP_TESTNET_ELECTRUM_PORT=$TESTNET_ELECTRUM_PORT REACT_APP_MOCK_BITCOIN_CLIENT=false REACT_APP_WALLET_CONNECT_PROJECT_ID=$WALLET_CONNECT_PROJECT_ID + +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..3c52b07eb 100644 --- a/.github/workflows/dashboard-ci.yml +++ b/.github/workflows/dashboard-ci.yml @@ -86,14 +86,17 @@ 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 }} + MAINNET_ELECTRUM_PROTOCOL: ${{ secrets.MAINNET_ELECTRUMX_PROTOCOL }} + MAINNET_ELECTRUM_HOST: ${{ secrets.MAINNET_ELECTRUMX_HOST }} + MAINNET_ELECTRUM_PORT: ${{ secrets.MAINNET_ELECTRUMX_PORT }} + TESTNET_ELECTRUM_PROTOCOL: ${{ secrets.TESTNET_ELECTRUMX_PROTOCOL }} + TESTNET_ELECTRUM_HOST: ${{ secrets.TESTNET_ELECTRUMX_HOST }} + TESTNET_ELECTRUM_PORT: ${{ secrets.TESTNET_ELECTRUMX_PORT }} WALLET_CONNECT_PROJECT_ID: ${{ secrets.WALLET_CONNECT_PROJECT_ID }} + TBTC_SUBGRAPH_API: ${{ secrets.TBTC_SUBGRAPH_API }} # FIXME: Tests are missing, will this step be needed? # - name: Test @@ -121,14 +124,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 +155,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 +181,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..b9ca7d0e1 100644 --- a/.github/workflows/dashboard-mainnet.yml +++ b/.github/workflows/dashboard-mainnet.yml @@ -48,18 +48,21 @@ 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 }} - ELECTRUM_PORT: ${{ secrets.MAINNET_ELECTRUMX_PORT }} + MAINNET_ELECTRUM_PROTOCOL: ${{ secrets.MAINNET_ELECTRUMX_PROTOCOL }} + MAINNET_ELECTRUM_HOST: ${{ secrets.MAINNET_ELECTRUMX_HOST }} + MAINNET_ELECTRUM_PORT: ${{ secrets.MAINNET_ELECTRUMX_PORT }} + TESTNET_ELECTRUM_PROTOCOL: ${{ secrets.TESTNET_ELECTRUMX_PROTOCOL }} + TESTNET_ELECTRUM_HOST: ${{ secrets.TESTNET_ELECTRUMX_HOST }} + TESTNET_ELECTRUM_PORT: ${{ secrets.TESTNET_ELECTRUMX_PORT }} SENTRY_SUPPORT: true SENTRY_DSN: ${{ secrets.MAINNET_SENTRY_DSN }} TRM_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 +71,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 +85,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..bc1579df5 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. @@ -75,6 +72,9 @@ on: Project Id gathered from WalletConnect cloud. Required for WalletConnect v2. required: true + tbtcSubgraphApi: + description: The API endpoint for the tBTC subgraph. + required: true jobs: build-and-publish: @@ -161,16 +161,19 @@ 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 }} - ELECTRUM_PORT: ${{ secrets.electrumPort }} + MAINNET_ELECTRUM_PROTOCOL: ${{ secrets.mainnetElectrumProtocol }} + MAINNET_ELECTRUM_HOST: ${{ secrets.mainnetElectrumHost }} + MAINNET_ELECTRUM_PORT: ${{ secrets.mainnetElectrumPort }} + TESTNET_ELECTRUM_PROTOCOL: ${{ secrets.testnetElectrumProtocol }} + TESTNET_ELECTRUM_HOST: ${{ secrets.testnetElectrumHost }} + TESTNET_ELECTRUM_PORT: ${{ secrets.testnetElectrumPort }} SENTRY_SUPPORT: true SENTRY_DSN: ${{ secrets.sentryDsn }} WALLET_CONNECT_PROJECT_ID: ${{ secrets.walletConnectProjectId }} + TBTC_SUBGRAPH_API: ${{ secrets.tbtcSubgraphApi }} DAPP_DEVELOPMENT_TESTNET_CONTRACTS: ${{ inputs.preview == true }} - name: Build @@ -179,16 +182,19 @@ 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 }} - ELECTRUM_PORT: ${{ secrets.electrumPort }} + MAINNET_ELECTRUM_PROTOCOL: ${{ secrets.mainnetElectrumProtocol }} + MAINNET_ELECTRUM_HOST: ${{ secrets.mainnetElectrumHost }} + MAINNET_ELECTRUM_PORT: ${{ secrets.mainnetElectrumPort }} + TESTNET_ELECTRUM_PROTOCOL: ${{ secrets.testnetElectrumProtocol }} + TESTNET_ELECTRUM_HOST: ${{ secrets.testnetElectrumHost }} + TESTNET_ELECTRUM_PORT: ${{ secrets.testnetElectrumPort }} SENTRY_SUPPORT: true SENTRY_DSN: ${{ secrets.sentryDsn }} WALLET_CONNECT_PROJECT_ID: ${{ secrets.walletConnectProjectId }} + 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..3c8a542f0 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 @@ -129,13 +127,18 @@ REACT_APP_FEATURE_FLAG_SENTRY=false REACT_APP_SENTRY_DSN=$SENTRY_DSN REACT_APP_FEATURE_FLAG_TRM=false -REACT_APP_ELECTRUM_PROTOCOL=wss -REACT_APP_ELECTRUM_HOST=electrumx-server.test.tbtc.network -REACT_APP_ELECTRUM_PORT=8443 +REACT_APP_MAINNET_ELECTRUM_PROTOCOL=$MAINNET_ELECTRUM_PROTOCOL +REACT_APP_MAINNET_ELECTRUM_HOST=$MAINNET_ELECTRUM_HOST +REACT_APP_MAINNET_ELECTRUM_PORT=$MAINNET_ELECTRUM_PORT +REACT_APP_TESTNET_ELECTRUM_PROTOCOL=wss +REACT_APP_TESTNET_ELECTRUM_HOST=electrumx-server.test.tbtc.network +REACT_APP_TESTNET_ELECTRUM_PORT=8443 REACT_APP_MOCK_BITCOIN_CLIENT=false REACT_APP_WALLET_CONNECT_PROJECT_ID=$WALLET_CONNECT_PROJECT_ID +REACT_APP_TBTC_SUBGRAPH_API=$TBTC_SUBGRAPH_API + REACT_APP_TACO_DOMAIN=dashboard ``` diff --git a/package.json b/package.json index 3d87f0b88..780d9e516 100644 --- a/package.json +++ b/package.json @@ -18,11 +18,11 @@ "@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", - "@nucypher/nucypher-contracts": "0.13.0", + "@nucypher/nucypher-contracts": "0.23.0", "@reduxjs/toolkit": "^1.6.1", "@rehooks/local-storage": "^2.4.4", "@sentry/react": "^7.33.0", diff --git a/src/App.tsx b/src/App.tsx index a28b23132..1eb7a8ab9 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 { @@ -63,6 +63,9 @@ import { useIsEmbed } from "./hooks/useIsEmbed" import TBTC from "./pages/tBTC" import { useDetectIfEmbed } from "./hooks/useDetectIfEmbed" import { useGoogleTagManager } from "./hooks/google-tag-manager" +import { hexToNumber, isSameChainId } from "./networks/utils" +import { walletConnected } from "./store/account" +import { useIsActive } from "./hooks/useIsActive" const Web3EventHandlerComponent = () => { useSubscribeToVendingMachineContractEvents() @@ -133,15 +136,19 @@ const useSubscribeToVendingMachineContractEvents = () => { const AppBody = () => { const dispatch = useDispatch() - const { connector, account, chainId, deactivate } = useWeb3React() + const { connector, account, chainId } = useIsActive() useEffect(() => { const updateHandler = (update: ConnectorUpdate) => { - // if chain is changed then just deactivate the current provider and reset - // store + // if chain is changed then just update the redux store for the wallet + // connection if (update.chainId && !isSameChainId(update.chainId, chainId as number)) { - dispatch(resetStoreAction()) - deactivate() + dispatch( + walletConnected({ + address: account || "", + chainId: hexToNumber(update.chainId), + }) + ) } else if ( update.account && !isSameETHAddress(update.account, account as string) @@ -169,7 +176,7 @@ const AppBody = () => { connector?.removeListener(ConnectorEvent.Update, updateHandler) connector?.removeListener(ConnectorEvent.Deactivate, deactivateHandler) } - }, [connector, dispatch, account]) + }, [connector, dispatch, account, chainId]) useEffect(() => { dispatch(fetchETHPriceUSD()) diff --git a/src/components/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/Forms/HelperErrorText.tsx b/src/components/Forms/HelperErrorText.tsx index 817b0818c..3d090740e 100644 --- a/src/components/Forms/HelperErrorText.tsx +++ b/src/components/Forms/HelperErrorText.tsx @@ -1,20 +1,26 @@ import { FC } from "react" -import { FormErrorMessage, FormHelperText } from "@threshold-network/components" +import { + Box, + FormErrorMessage, + FormHelperText, +} from "@threshold-network/components" const HelperErrorText: FC<{ errorMsgText?: string | JSX.Element hasError?: boolean helperText?: string | JSX.Element }> = ({ errorMsgText, helperText, hasError }) => { - if (hasError) { - return ( - - {errorMsgText || "Please enter a valid value"} - - ) - } - - return helperText ? {helperText} : null + return ( + + {hasError ? ( + + {errorMsgText || "Please enter a valid value"} + + ) : helperText ? ( + {helperText} + ) : null} + + ) } export default HelperErrorText 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/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/Modal/ClaimingRewards/index.tsx b/src/components/Modal/ClaimingRewards/index.tsx index 9d7c504df..5e2ca0c48 100644 --- a/src/components/Modal/ClaimingRewards/index.tsx +++ b/src/components/Modal/ClaimingRewards/index.tsx @@ -34,6 +34,7 @@ import { useModal } from "../../../hooks/useModal" import { ModalType } from "../../../enums" import ModalCloseButton from "../ModalCloseButton" import SubmitTxButton from "../../SubmitTxButton" +import { useMerkleDropContract } from "../../../web3/hooks/useMerkleDropContract" const ClaimingRewardsBase: FC< BaseModalProps & { @@ -44,6 +45,7 @@ const ClaimingRewardsBase: FC< const { openModal } = useModal() const beneficiaryRewards = useSelector(selectAccumulatedRewardsPerBeneficiary) const rewards = useSelector(selectInterimRewards) + const merkleDropContract = useMerkleDropContract() const onClaimSuccess = useCallback( (receipt) => { @@ -99,6 +101,7 @@ const ClaimingRewardsBase: FC< Cancel { 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 e7d967f74..2404f0b20 100644 --- a/src/components/Modal/MapOperatorToStakingProviderModal/index.tsx +++ b/src/components/Modal/MapOperatorToStakingProviderModal/index.tsx @@ -72,30 +72,35 @@ 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 = - 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/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/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/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..38f7077dd 100644 --- a/src/components/Modal/StakingApplications/ConfirmDeauthorization.tsx +++ b/src/components/Modal/StakingApplications/ConfirmDeauthorization.tsx @@ -19,24 +19,31 @@ 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 - stakingAppName: StakingAppName + appName: StakingAppName decreaseAmount: string } const ConfirmDeauthorizationBase: FC = ({ stakingProvider, - stakingAppName, + appName, decreaseAmount, closeModal, }) => { - const { sendTransaction } = - useConfirmDeatuhorizationTransaction(stakingAppName) + const threshold = useThreshold() + const stakingAppContract = + threshold.multiAppStaking[appNameToThresholdApp[appName]]?.contract + + const { sendTransaction } = useConfirmDeauthorizationTransaction(appName) const onDeauthorize = async () => { await sendTransaction(stakingProvider) @@ -52,7 +59,7 @@ const ConfirmDeauthorizationBase: FC = ({ Confirm your deauthorization. = ({ - + Confirm Deauthorization 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/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/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/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/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 c9248f798..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/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/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/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 900aa8f3a..f3a8ec96d 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" @@ -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,11 +65,15 @@ const TransactionIdle: FC = ({ mt="2rem" > This action is reversible via the{" "} - + {vendingMachineContract ? ( + + ) : ( + "vending machine contract." + )} @@ -79,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..d86050215 100644 --- a/src/components/Modal/tBTC/InitiateUnminting.tsx +++ b/src/components/Modal/tBTC/InitiateUnminting.tsx @@ -101,17 +101,17 @@ const InitiateUnmintingBase: FC = ({ = ({ Cancel = ({ - {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/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/components/Navbar/index.tsx b/src/components/Navbar/index.tsx index bbc64d4e6..c9cec894f 100644 --- a/src/components/Navbar/index.tsx +++ b/src/components/Navbar/index.tsx @@ -24,8 +24,10 @@ const Navbar: FC = () => { useEffect(() => { if (ledgerLiveAccountAddress && isEmbed) { dispatch(walletConnected({ address: ledgerLiveAccountAddress, chainId })) + } else if (account) { + dispatch(walletConnected({ address: account, chainId })) } - }, [ledgerLiveAccountAddress, dispatch, isEmbed]) + }, [account, chainId, ledgerLiveAccountAddress, dispatch, isEmbed]) return ( = ({ const { isActive } = useIsActive() const connectWallet = useConnectWallet() + const isButtonDisabled = isBlocked || isDisabled const onConnectWalletClick = () => { connectWallet() @@ -32,7 +33,7 @@ const SubmitTxButton: FC = ({ return ( )} {status === "deauthorization-initiation-needed" && ( - + Activate Deauthorization Request )} diff --git a/src/pages/Staking/AuthorizeStakingApps/index.tsx b/src/pages/Staking/AuthorizeStakingApps/index.tsx index e8689cf15..97c7196a6 100644 --- a/src/pages/Staking/AuthorizeStakingApps/index.tsx +++ b/src/pages/Staking/AuthorizeStakingApps/index.tsx @@ -38,10 +38,12 @@ import { FormValues } from "../../../components/Forms" import { useAppDispatch } from "../../../hooks/store" import { stakingApplicationsSlice } from "../../../store/staking-applications" import BundledRewardsAlert from "../../../components/BundledRewardsAlert" +import { useThreshold } from "../../../contexts/ThresholdContext" const AuthorizeStakingAppsPage: FC = () => { const { stakingProviderAddress } = useParams() - const { account, active } = useWeb3React() + const { account, active, chainId } = useWeb3React() + const threshold = useThreshold() const navigate = useNavigate() const { openModal } = useModal() const tbtcAppFormRef = useRef>(null) @@ -75,10 +77,14 @@ const AuthorizeStakingAppsPage: FC = () => { }, [stakingProviderAddress, navigate]) useEffect(() => { + if (!chainId) return + dispatch( - requestStakeByStakingProvider({ stakingProvider: stakingProviderAddress }) + requestStakeByStakingProvider({ + stakingProvider: stakingProviderAddress, + }) ) - }, [stakingProviderAddress, account, dispatch]) + }, [stakingProviderAddress, account, threshold.staking, dispatch]) useEffect(() => { dispatch(stakingApplicationsSlice.actions.getSupportedApps({})) diff --git a/src/pages/Staking/HowItWorks/StakingOverview/AuthorizingApplicationsCard.tsx b/src/pages/Staking/HowItWorks/StakingOverview/AuthorizingApplicationsCard.tsx index be6609a53..b7b75fdc5 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, and 6 months for TACo. 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/pages/Staking/StakeDetailsPage/index.tsx b/src/pages/Staking/StakeDetailsPage/index.tsx index 36c638576..cb52eb83f 100644 --- a/src/pages/Staking/StakeDetailsPage/index.tsx +++ b/src/pages/Staking/StakeDetailsPage/index.tsx @@ -34,10 +34,12 @@ import { useWeb3React } from "@web3-react/core" import { AddressZero } from "@ethersproject/constants" import { isAddress } from "../../../web3/utils" import { stakingApplicationsSlice } from "../../../store/staking-applications" +import { useThreshold } from "../../../contexts/ThresholdContext" const StakeDetailsPage: FC = () => { const { stakingProviderAddress } = useParams() const { account, active } = useWeb3React() + const threshold = useThreshold() const { openModal } = useModal() const navigate = useNavigate() const dispatch = useAppDispatch() @@ -52,9 +54,11 @@ const StakeDetailsPage: FC = () => { useEffect(() => { dispatch( - requestStakeByStakingProvider({ stakingProvider: stakingProviderAddress }) + requestStakeByStakingProvider({ + stakingProvider: stakingProviderAddress, + }) ) - }, [stakingProviderAddress, account, dispatch]) + }, [stakingProviderAddress, account, threshold.staking, dispatch]) const stake = useAppSelector((state) => selectStakeByStakingProvider(state, stakingProviderAddress!) diff --git a/src/pages/tBTC/Bridge/DepositDetails.tsx b/src/pages/tBTC/Bridge/DepositDetails.tsx index cbdfaaeb5..662b9c18d 100644 --- a/src/pages/tBTC/Bridge/DepositDetails.tsx +++ b/src/pages/tBTC/Bridge/DepositDetails.tsx @@ -63,13 +63,19 @@ import { useSubscribeToOptimisticMintingFinalizedEventBase, } from "../../../hooks/tbtc" import { tbtcSlice } from "../../../store/tbtc" -import { ExplorerDataType } from "../../../utils/createEtherscanLink" +import { + ExplorerDataType, + SupportedChainIds, +} 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 { DepositState } from "@keep-network/tbtc-v2.ts" +import { chainIdToChainParameterName } from "../../../networks/utils" +import { useIsActive } from "../../../hooks/useIsActive" export const DepositDetails: PageComponent = () => { const { depositKey } = useParams() @@ -113,6 +119,9 @@ export const DepositDetails: PageComponent = () => { data?.optimisticMintingRequestedTxHash const optimisticMintingFinalizedTxHash = data?.optimisticMintingFinalizedTxHash + const l1BitcoinDepositorDepositStatus = data?.l1BitcoinDepositorDepositStatus + const isCrossChainDeposit = !!data?.isCrossChainDeposit + const crossChainFee = data?.crossChainFee const thresholdNetworkFee = data?.treasuryFee const mintingFee = data?.optimisticMintFee @@ -141,6 +150,8 @@ export const DepositDetails: PageComponent = () => { requiredConfirmations, optimisticMintingFinalizedTxHash, optimisticMintingRequestedTxHash, + l1BitcoinDepositorDepositStatus, + isCrossChainDeposit, }) ) }, [ @@ -148,6 +159,8 @@ export const DepositDetails: PageComponent = () => { requiredConfirmations, optimisticMintingFinalizedTxHash, optimisticMintingRequestedTxHash, + l1BitcoinDepositorDepositStatus, + isCrossChainDeposit, shouldStartFromFirstStep, ]) @@ -180,11 +193,14 @@ export const DepositDetails: PageComponent = () => { optimisticMintingRequestedTxHash ?? mintingRequestedTxHash, optimisticMintingFinalizedTxHash: optimisticMintingFinalizedTxHash ?? mintingFinalizedTxHash, + l1BitcoinDepositorDepositStatus, confirmations: confirmations || txConfirmations, requiredConfirmations: requiredConfirmations!, amount: amount, thresholdNetworkFee, mintingFee, + isCrossChainDeposit: !!data?.isCrossChainDeposit, + crossChainFee, }} > & { btcTxHash?: string confirmations?: number requiredConfirmations?: number updateStep: (step: DepositDetailsTimelineStep) => void step: DepositDetailsTimelineStep + isCrossChainDeposit: boolean amount?: string mintingFee?: string thresholdNetworkFee?: string + crossChainFee?: string }) | undefined >(undefined) @@ -453,6 +473,7 @@ const getMintingProgressStep = ( | "amount" | "optimisticMintFee" | "treasuryFee" + | "crossChainFee" > ): DepositDetailsTimelineStep => { if (!depositDetails) return "bitcoin-confirmations" @@ -462,9 +483,15 @@ const getMintingProgressStep = ( requiredConfirmations, optimisticMintingRequestedTxHash, optimisticMintingFinalizedTxHash, + l1BitcoinDepositorDepositStatus, + isCrossChainDeposit, } = depositDetails - if (optimisticMintingFinalizedTxHash) return "completed" + if ( + (!isCrossChainDeposit && optimisticMintingFinalizedTxHash) || + l1BitcoinDepositorDepositStatus === DepositState.FINALIZED + ) + return "completed" if (optimisticMintingRequestedTxHash) return "guardian-check" @@ -490,12 +517,16 @@ const StepSwitcher: FC = () => { requiredConfirmations, optimisticMintingRequestedTxHash, optimisticMintingFinalizedTxHash, + l1BitcoinDepositorDepositStatus, btcTxHash, updateStep, amount, thresholdNetworkFee, + crossChainFee, mintingFee, + isCrossChainDeposit, } = useDepositDetailsPageContext() + const { chainId } = useIsActive() const onComplete = useCallback(() => { if (step === "completed") return @@ -532,6 +563,8 @@ const StepSwitcher: FC = () => { return ( ) @@ -541,30 +574,49 @@ const StepSwitcher: FC = () => { Success! - - Add the tBTC to your Ethereum wallet. - + + {isCrossChainDeposit ? ( + + Your tokens have been minted and bridged to the depositor wallet + on the {chainIdToChainParameterName(chainId)} network - This + action usually takes a few minutes to complete this process. + + ) : ( + + Add the tBTC to your Ethereum wallet. + + )} + {(chainId === SupportedChainIds.Arbitrum || + chainId === SupportedChainIds.ArbitrumSepolia) && ( + + )} New mint diff --git a/src/pages/tBTC/Bridge/Mint.tsx b/src/pages/tBTC/Bridge/Mint.tsx index 97c29e2cd..253ccd5b8 100644 --- a/src/pages/tBTC/Bridge/Mint.tsx +++ b/src/pages/tBTC/Bridge/Mint.tsx @@ -18,6 +18,8 @@ import { import { BridgeProcessEmptyState } from "./components/BridgeProcessEmptyState" import { MintDurationWidget } from "../../../components/MintDurationWidget" import { useThreshold } from "../../../contexts/ThresholdContext" +import { useCheckDepositExpirationTime } from "../../../hooks/tbtc/useCheckDepositExpirationTime" +import { useRemoveDepositData } from "../../../hooks/tbtc/useRemoveDepositData" export const MintPage: PageComponent = ({}) => { return @@ -25,40 +27,62 @@ export const MintPage: PageComponent = ({}) => { export const MintingFormPage: PageComponent = ({ ...props }) => { const { tBTCDepositData } = useTBTCDepositDataFromLocalStorage() - const { btcDepositAddress, updateState } = useTbtcState() - const { account } = useIsActive() + const { btcDepositAddress, updateState, resetDepositData } = useTbtcState() + const { account, chainId } = useIsActive() + const checkDepositExpiration = useCheckDepositExpirationTime() + const removeDepositData = useRemoveDepositData() useEffect(() => { + const updateDepositData = async () => { + if ( + tBTCDepositData && + account && + chainId && + tBTCDepositData[account] && + isSameETHAddress(tBTCDepositData[account].ethAddress, account) && + tBTCDepositData[account].btcDepositAddress !== btcDepositAddress + ) { + const { + depositor: { identifierHex: depositorAddress }, + btcDepositAddress, + ethAddress, + blindingFactor, + btcRecoveryAddress, + walletPublicKeyHash, + refundLocktime, + extraData, + chainName, + } = tBTCDepositData[account] + const { isExpired } = await checkDepositExpiration(refundLocktime) + if (isExpired) { + resetDepositData() + removeDepositData() + return + } + + updateState("ethAddress", ethAddress) + updateState("blindingFactor", blindingFactor) + updateState("btcRecoveryAddress", btcRecoveryAddress) + updateState("walletPublicKeyHash", walletPublicKeyHash) + updateState("refundLocktime", refundLocktime) + updateState("depositor", depositorAddress) + updateState("extraData", extraData) + updateState("chainName", chainName) + // We reset the minting step to undefined to show skeleton and the + // useEffect in MintingFlowRouter will update and set the proper minting + // step when it recognizes the "btcDepositAddress" change. + updateState("mintingStep", undefined) + updateState("btcDepositAddress", btcDepositAddress) + } else { + resetDepositData() + } + } + // Update the store with the deposit data if the account is placed in tbtc // local storage. - if ( - tBTCDepositData && - account && - tBTCDepositData[account] && - isSameETHAddress(tBTCDepositData[account].ethAddress, account) && - tBTCDepositData[account].btcDepositAddress !== btcDepositAddress - ) { - const { - btcDepositAddress, - ethAddress, - blindingFactor, - btcRecoveryAddress, - walletPublicKeyHash, - refundLocktime, - } = tBTCDepositData[account] - updateState("ethAddress", ethAddress) - updateState("blindingFactor", blindingFactor) - updateState("btcRecoveryAddress", btcRecoveryAddress) - updateState("walletPublicKeyHash", walletPublicKeyHash) - updateState("refundLocktime", refundLocktime) - // We reset the minting step to undefined to show skeleton and the - // useEffect in MintingFlowRouter will update and set the proper minting - // step when it recognizes the "btcDepositAddress" change. - updateState("mintingStep", undefined) - updateState("btcDepositAddress", btcDepositAddress) - } - }, [account]) + updateDepositData() + }, [account, tBTCDepositData]) return } diff --git a/src/pages/tBTC/Bridge/MintUnmintNav.tsx b/src/pages/tBTC/Bridge/MintUnmintNav.tsx index e8d365c69..9a60b7583 100644 --- a/src/pages/tBTC/Bridge/MintUnmintNav.tsx +++ b/src/pages/tBTC/Bridge/MintUnmintNav.tsx @@ -8,6 +8,8 @@ import { import { Box, Card, FilterTabs, FilterTab } from "@threshold-network/components" import Link from "../../../components/Link" import { PageComponent } from "../../../types" +import { isL2Network } from "../../../networks/utils" +import { useIsActive } from "../../../hooks/useIsActive" const renderNavItem = (page: PageComponent, index: number) => ( ( export const MintUnmintNav: FC< ComponentProps & { pages: PageComponent[] } > = ({ pages, ...props }) => { + const { chainId } = useIsActive() const resolved = useResolvedPath("") const location = useLocation() @@ -41,7 +44,17 @@ export const MintUnmintNav: FC< return ( - {pages.filter((page) => !!page.route.title).map(renderNavItem)} + {isL2Network(chainId) + ? pages + .filter( + (page) => + !!page.route.title && + 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 0939b6d23..d632d4dbf 100644 --- a/src/pages/tBTC/Bridge/Minting/InitiateMinting.tsx +++ b/src/pages/tBTC/Bridge/Minting/InitiateMinting.tsx @@ -40,16 +40,17 @@ 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() - }, [depositedAmount, updateState, threshold]) + }, [depositedAmount, updateState, threshold.tbtc]) const initiateMintTransaction = async () => { await revealDeposit(utxo) @@ -97,6 +98,7 @@ const InitiateMintingComponent: FC<{ = ({ + + + + Please ensure your deposit is at least 0.01 BTC to proceed with + minting tBTC. + + { const dispatch = useAppDispatch() - const { account } = useIsActive() + const { account, chainId } = useIsActive() const { mintingStep, updateState, btcDepositAddress, utxo } = useTbtcState() const removeDepositData = useRemoveDepositData() const { openModal } = useModal() @@ -36,13 +36,16 @@ const MintingFlowRouterBase = () => { } useEffect(() => { - if (!btcDepositAddress || !account) { + if (!btcDepositAddress || !account || !chainId) { return } dispatch( - tbtcSlice.actions.findUtxo({ btcDepositAddress, depositor: account }) + tbtcSlice.actions.findUtxo({ + btcDepositAddress, + chainId, + }) ) - }, [btcDepositAddress, account, dispatch]) + }, [btcDepositAddress, account, chainId, dispatch]) switch (mintingStep) { case MintingStep.ProvideData: { diff --git a/src/pages/tBTC/Bridge/Minting/MintingSuccess.tsx b/src/pages/tBTC/Bridge/Minting/MintingSuccess.tsx index 37449f492..36c28e55d 100644 --- a/src/pages/tBTC/Bridge/Minting/MintingSuccess.tsx +++ b/src/pages/tBTC/Bridge/Minting/MintingSuccess.tsx @@ -4,27 +4,38 @@ import withOnlyConnectedWallet from "../../../../components/withOnlyConnectedWal import { useThreshold } from "../../../../contexts/ThresholdContext" import { Navigate } from "react-router" import { useRemoveDepositData } from "../../../../hooks/tbtc/useRemoveDepositData" +import { useFetchDepositDetails } from "../../../../hooks/tbtc" +import { BridgeProcessDetailsPageSkeleton } from "../components/BridgeProcessDetailsPageSkeleton" const MintingSuccessComponent: FC = () => { const threshold = useThreshold() const { utxo } = useTbtcState() const removeDepositData = useRemoveDepositData() - const btcDepositTxHash = utxo.transactionHash.toString() + const btcDepositTxHash = utxo?.transactionHash?.toString() const depositKey = threshold.tbtc.buildDepositKey( btcDepositTxHash, utxo.outputIndex, "big-endian" ) + const { isFetching, data, error } = useFetchDepositDetails(depositKey) useEffect(() => { - removeDepositData() - }, [removeDepositData]) + if (!isFetching && data && !error) { + removeDepositData() + } + }, [isFetching, data, error, removeDepositData]) + + if ((isFetching || !data) && !error) { + return + } return ( ) diff --git a/src/pages/tBTC/Bridge/Minting/ProvideData.tsx b/src/pages/tBTC/Bridge/Minting/ProvideData.tsx index a52ca4ea4..646a5b9d3 100644 --- a/src/pages/tBTC/Bridge/Minting/ProvideData.tsx +++ b/src/pages/tBTC/Bridge/Minting/ProvideData.tsx @@ -1,6 +1,5 @@ import { BodyMd, - Button, Checkbox, useColorModeValue, } from "@threshold-network/components" @@ -19,14 +18,22 @@ import { validateBTCAddress, validateETHAddress, } from "../../../../utils/forms" -import { supportedChainId } from "../../../../utils/getEnvVariable" +import { SupportedChainIds } from "../../../../networks/enums/networks" +import { + getChainIdToNetworkName, + isL1Network, + isSupportedNetwork, + isTestnetNetwork, +} from "../../../../networks/utils" import { getBridgeBTCSupportedAddressPrefixesText } from "../../../../utils/tBTC" import { downloadFile, isSameETHAddress } from "../../../../web3/utils" import { BridgeProcessCardSubTitle } from "../components/BridgeProcessCardSubTitle" 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" +import { Deposit } from "@keep-network/tbtc-v2.ts" export interface FormValues { ethAddress: string @@ -38,11 +45,6 @@ type ComponentProps = { formId: string } -const resolvedBTCAddressPrefix = getBridgeBTCSupportedAddressPrefixesText( - "mint", - supportedChainId === "1" ? BitcoinNetwork.Mainnet : BitcoinNetwork.Testnet -) - /** * Renders the form for the minting process. * @param {string} formId - The ID of the form. @@ -51,6 +53,14 @@ const resolvedBTCAddressPrefix = getBridgeBTCSupportedAddressPrefixesText( const MintingProcessFormBase: FC> = ({ formId, }) => { + const { chainId } = useIsActive() + const resolvedBTCAddressPrefix = getBridgeBTCSupportedAddressPrefixesText( + "mint", + isTestnetNetwork(chainId as number) + ? BitcoinNetwork.Testnet + : BitcoinNetwork.Mainnet + ) + return (
>(null) const threshold = useThreshold() - const { account } = useIsActive() + const { account, chainId } = useIsActive() const { setDepositDataInLocalStorage } = useTBTCDepositDataFromLocalStorage() const depositTelemetry = useDepositTelemetry(threshold.tbtc.bitcoinNetwork) @@ -137,31 +147,60 @@ export const ProvideDataComponent: FC<{ "The account used to generate the deposit address must be the same as the connected wallet." ) } + + if (!isSupportedNetwork(chainId)) { + throw new Error( + "You are currently connected to an unsupported network. Switch to a supported network" + ) + } + + const chainName = getChainIdToNetworkName(chainId) + setSubmitButtonLoading(true) - const deposit = await threshold.tbtc.initiateDeposit( - values.btcRecoveryAddress - ) + + let deposit: Deposit + if (isL1Network(chainId)) { + deposit = await threshold.tbtc.initiateDeposit( + values.btcRecoveryAddress + ) + } else { + deposit = await threshold.tbtc.initiateCrossChainDeposit( + values.btcRecoveryAddress, + chainId as SupportedChainIds + ) + } const depositAddress = await threshold.tbtc.calculateDepositAddress() const receipt = deposit.getReceipt() // update state, updateState("ethAddress", values.ethAddress) + updateState("depositor", receipt.depositor.identifierHex.toString()) updateState("blindingFactor", receipt.blindingFactor.toString()) updateState("btcRecoveryAddress", values.btcRecoveryAddress) updateState("walletPublicKeyHash", receipt.walletPublicKeyHash.toString()) updateState("refundLocktime", receipt.refundLocktime.toString()) + updateState("extraData", receipt.extraData?.toString()) + updateState("chainName", chainName) // create a new deposit address, updateState("btcDepositAddress", depositAddress) - setDepositDataInLocalStorage({ - ethAddress: values.ethAddress, - blindingFactor: receipt.blindingFactor.toString(), - btcRecoveryAddress: values.btcRecoveryAddress, - walletPublicKeyHash: receipt.walletPublicKeyHash.toString(), - refundLocktime: receipt.refundLocktime.toString(), - btcDepositAddress: depositAddress, - }) + setDepositDataInLocalStorage( + { + depositor: { + identifierHex: receipt.depositor.identifierHex.toString(), + }, + chainName: chainName, + ethAddress: values.ethAddress, + blindingFactor: receipt.blindingFactor.toString(), + btcRecoveryAddress: values.btcRecoveryAddress, + walletPublicKeyHash: receipt.walletPublicKeyHash.toString(), + refundLocktime: receipt.refundLocktime.toString(), + btcDepositAddress: depositAddress, + extraData: receipt.extraData?.toString() || "", + }, + chainId + ) depositTelemetry(receipt, depositAddress) @@ -175,18 +214,23 @@ export const ProvideDataComponent: FC<{ depositor: { identifierHex: receipt.depositor.identifierHex.toString(), }, + networkInfo: { + chainName: chainName, + chainId: chainId!.toString(), + }, refundLocktime: receipt.refundLocktime.toString(), refundPublicKeyHash: receipt.refundPublicKeyHash.toString(), blindingFactor: receipt.blindingFactor.toString(), ethAddress: values.ethAddress, walletPublicKeyHash: receipt.walletPublicKeyHash.toString(), btcRecoveryAddress: values.btcRecoveryAddress, + extraData: receipt.extraData?.toString() ?? "", } downloadFile(JSON.stringify(finalData), fileName, "text/json") } updateState("mintingStep", MintingStep.Deposit) }, - [shouldDownloadDepositReceipt] + [shouldDownloadDepositReceipt, chainId] ) return ( @@ -216,9 +260,11 @@ 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 { updateState } = useTbtcState() - const { account, isActive } = useIsActive() + const { account, chainId, isActive } = useIsActive() const navigate = useNavigate() const { setDepositDataInLocalStorage } = useTBTCDepositDataFromLocalStorage() + const checkDepositExpiration = useCheckDepositExpirationTime() const threshold = useThreshold() + if (!isActive || !isSupportedNetwork(chainId)) { + return ( + + + + ) + } + const navigateToMintPage = () => { navigate("/tBTC/mint") } const onSubmit = async (values: FormValues) => { if (!values.depositParameters) return - const { depositParameters } = values - await threshold.tbtc.initiateDepositFromDepositScriptParameters( - depositParameters - ) - const btcDepositAddress = await threshold.tbtc.calculateDepositAddress() - - updateState("mintingStep", undefined) - - setDepositDataInLocalStorage({ - ethAddress: depositParameters?.depositor.identifierHex!, - blindingFactor: depositParameters?.blindingFactor!, - btcRecoveryAddress: depositParameters?.btcRecoveryAddress!, - walletPublicKeyHash: depositParameters?.walletPublicKeyHash!, - refundLocktime: depositParameters?.refundLocktime!, - btcDepositAddress, - }) - navigateToMintPage() + try { + if (isL1Network(chainId)) { + await threshold.tbtc.initiateDepositFromDepositScriptParameters( + depositParameters + ) + } else { + await threshold.tbtc.initiateCrossChainDepositFromScriptParameters( + depositParameters, + chainId! + ) + } + const btcDepositAddress = await threshold.tbtc.calculateDepositAddress() + updateState("mintingStep", undefined) + setDepositDataInLocalStorage( + { + depositor: { + identifierHex: depositParameters.depositor.identifierHex, + }, + chainName: depositParameters.networkInfo.chainName, + ethAddress: depositParameters.ethAddress, + blindingFactor: depositParameters.blindingFactor, + btcRecoveryAddress: depositParameters.btcRecoveryAddress, + walletPublicKeyHash: depositParameters.walletPublicKeyHash, + refundLocktime: depositParameters.refundLocktime, + extraData: depositParameters.extraData || "", + btcDepositAddress, + }, + chainId + ) + navigateToMintPage() + } catch (error) { + console.error("Error during deposit initiation:", error) + } } return ( - - {isActive ? ( - <> - - - - Resume Minting - {" "} - - Upload .JSON file - - - To resume your minting you need to upload your .JSON file and sign - the Minting Initiation transaction triggered in the dApp. - - - - - - - ) : ( - - )} + + <> + + + + Resume Minting + {" "} + - Upload .JSON file + + + To resume your minting you need to upload your .JSON file and sign the + Minting Initiation transaction triggered in the dApp. + + + + + + ) } @@ -99,6 +138,7 @@ export const ResumeDepositPage: PageComponent = () => { const ResumeDepositForm: FC> = (props) => { const { setValues, getFieldMeta, setFieldError, isSubmitting, values } = props const { error } = getFieldMeta("depositParameters") + const threshold = useThreshold() const isError = Boolean(error) @@ -134,7 +174,12 @@ const ResumeDepositForm: FC> = (props) => { size="lg" isFullWidth mt="6" - isDisabled={!values.depositParameters || isError || isSubmitting} + isDisabled={ + !values.depositParameters || + isError || + isSubmitting || + !threshold.tbtc.bridgeContract + } type="submit" isLoading={isSubmitting} > @@ -153,37 +198,64 @@ type FormValues = { type ResumeDepositFormikProps = { onSubmitForm: (values: FormValues) => void address: string + checkDepositExpiration: ReturnType + bitcoinNetwork: BitcoinNetwork + chainId: SupportedChainIds } const ResumeDepositFormik = withFormik({ mapPropsToValues: () => ({ depositParameters: null }), - validate: (values, { address }) => { + validate: async ( + values, + { address, checkDepositExpiration, bitcoinNetwork, chainId } + ) => { const errors: FormikErrors = {} - if (!values.depositParameters) { + const dp = values.depositParameters + + if (!dp) { errors.depositParameters = "Required." } else if ( - !values.depositParameters?.depositor || - !values.depositParameters?.depositor?.identifierHex || - !isAddress(values.depositParameters?.depositor?.identifierHex) || - !values.depositParameters?.refundLocktime || - !values.depositParameters?.refundPublicKeyHash || - !values.depositParameters?.blindingFactor || - !values.depositParameters?.walletPublicKeyHash || - !values.depositParameters?.btcRecoveryAddress + !dp.depositor || + !dp.depositor.identifierHex || + !dp.networkInfo?.chainName || + !dp.networkInfo?.chainId || + !isAddress(dp.depositor.identifierHex) || + !dp.refundLocktime || + !dp.refundPublicKeyHash || + !dp.blindingFactor || + !dp.walletPublicKeyHash || + !dp.btcRecoveryAddress ) { errors.depositParameters = "Invalid .JSON file." - } else if ( - !isSameETHAddress( - values.depositParameters?.depositor?.identifierHex, - address + } else if (!isSameChainId(dp.networkInfo.chainId, chainId)) { + errors.depositParameters = "Chain Id mismatch." + } else if (isL2Network(chainId) && !dp.extraData) { + errors.depositParameters = "Extra data is required for L2 networks." + } else { + const btcAddressError = validateBTCAddress( + dp.btcRecoveryAddress as string, + bitcoinNetwork ) - ) { - errors.depositParameters = "You are not a depositor." + if (btcAddressError) { + errors.depositParameters = btcAddressError + } else { + // Check deposit expiration + const { isExpired } = await checkDepositExpiration(dp.refundLocktime) + if (isExpired) { + errors.depositParameters = "Deposit reveal time is expired." + } else if ( + isL1Network(chainId) && + !isSameETHAddress(dp.depositor.identifierHex, address) + ) { + errors.depositParameters = "You are not a depositor." + } + } } return getErrorsObj(errors) }, + handleSubmit: (values, { props }) => { props.onSubmitForm(values) }, diff --git a/src/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/pages/tBTC/Bridge/UnmintDetails.tsx b/src/pages/tBTC/Bridge/UnmintDetails.tsx index a410727f7..25310cc0c 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" @@ -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/pages/tBTC/Bridge/components/BridgeProcessStep.tsx b/src/pages/tBTC/Bridge/components/BridgeProcessStep.tsx index 3cf86ced0..0e39a4305 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 @@ -85,7 +86,7 @@ export const BridgeProcessStep: FC = ({ See transaction on{" "} & { txHash?: string } +type CrossChainStepProps = CommonStepProps & { + l1BitcoinDepositorDepositStatus?: DepositState + isCrossChainDeposit: boolean +} + export const Step1: FC< { confirmations?: number; requiredConfirmations?: number } & Pick< BridgeProcessStepProps, @@ -140,7 +146,16 @@ export const Step3: FC = ({ txHash, onComplete }) => { ) } -export const Step4: FC = ({ txHash, onComplete }) => { +export const Step4: FC = ({ + txHash, + l1BitcoinDepositorDepositStatus, + isCrossChainDeposit, + onComplete, +}) => { + const isComplete = isCrossChainDeposit + ? l1BitcoinDepositorDepositStatus === DepositState.FINALIZED + : true + return ( = ({ txHash, onComplete }) => { chain="ethereum" txHash={txHash} progressBarColor="teal.500" - isCompleted={true} + isCompleted={isComplete} onComplete={onComplete} isIndeterminate > diff --git a/src/pages/tBTC/Bridge/components/MintingTransactionDetails.tsx b/src/pages/tBTC/Bridge/components/MintingTransactionDetails.tsx index 607db7b50..fe0af5151 100644 --- a/src/pages/tBTC/Bridge/components/MintingTransactionDetails.tsx +++ b/src/pages/tBTC/Bridge/components/MintingTransactionDetails.tsx @@ -5,32 +5,50 @@ import { } from "../../../../components/TransactionDetails" import { useTbtcState } from "../../../../hooks/useTbtcState" import shortenAddress from "../../../../utils/shortenAddress" +import { useIsActive } from "../../../../hooks/useIsActive" +import { SupportedChainIds } from "../../../../networks/enums/networks" const MintingTransactionDetails = () => { - const { tBTCMintAmount, mintingFee, thresholdNetworkFee, ethAddress } = - useTbtcState() + const { + tBTCMintAmount, + mintingFee, + thresholdNetworkFee, + ethAddress, + crossChainFee, + } = useTbtcState() + const { chainId } = useIsActive() return ( + {(chainId === SupportedChainIds.Arbitrum || + chainId === SupportedChainIds.ArbitrumSepolia) && ( + + )} { + const { + data: { depositTreasuryFee, optimisticMintingFee, depositTxMaxFee }, + isFetching, + } = useFetchTBTCFees() + + const { chainId } = useIsActive() + + return ( + + + + {(chainId === SupportedChainIds.Arbitrum || + chainId === SupportedChainIds.ArbitrumSepolia) && ( + + )} + + ) +} + +export default TbtcFees diff --git a/src/pages/tBTC/Bridge/index.tsx b/src/pages/tBTC/Bridge/index.tsx index f4fb63866..d7ff72ab8 100644 --- a/src/pages/tBTC/Bridge/index.tsx +++ b/src/pages/tBTC/Bridge/index.tsx @@ -9,11 +9,11 @@ import { ModalType } from "../../../enums" import { useTBTCTerms } from "../../../hooks/useTBTCTerms" import { useAppDispatch, useAppSelector } from "../../../hooks/store" import { selectBridgeActivity, tbtcSlice } from "../../../store/tbtc" -import { useWeb3React } from "@web3-react/core" import { Outlet } from "react-router" import { MintPage } from "./Mint" import { UnmintPage } from "./Unmint" import { useIsActive } from "../../../hooks/useIsActive" +import { useThreshold } from "../../../contexts/ThresholdContext" const gridTemplateAreas = { base: ` @@ -31,7 +31,9 @@ const TBTCBridge: PageComponent = (props) => { const isBridgeActivityFetching = useAppSelector( (state) => state.tbtc.bridgeActivity.isFetching ) + const mintingStep = useAppSelector((state) => state.tbtc.mintingStep) const { account } = useIsActive() + const threshold = useThreshold() useEffect(() => { if (!hasUserResponded) openModal(ModalType.NewTBTCApp) @@ -39,13 +41,12 @@ const TBTCBridge: PageComponent = (props) => { useEffect(() => { if (!account) return - dispatch( tbtcSlice.actions.requestBridgeActivity({ depositor: account, }) ) - }, [dispatch, account]) + }, [dispatch, account, mintingStep, threshold.tbtc.ethereumChainId]) return ( > = (props) => { const tbtcTokenContractAddress = useTBTCTokenAddress() const bridgeContractAddress = useTBTCBridgeContractAddress() + const { chainId } = useIsActive() return ( Contracts - - + {tbtcTokenContractAddress && ( + + )} + {bridgeContractAddress && ( + + )} ) 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: ( + <> + + + + ), +}) diff --git a/src/store/account/effects.ts b/src/store/account/effects.ts index eeb1af0e1..1be58ec11 100644 --- a/src/store/account/effects.ts +++ b/src/store/account/effects.ts @@ -26,6 +26,16 @@ 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.ecdsa || + !threshold.multiAppStaking.randomBeacon || + !threshold.multiAppStaking.taco + ) + return const stake = stakes.find((_: StakeData) => isSameETHAddress(_.stakingProvider, address) @@ -37,7 +47,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,15 +62,15 @@ export const getStakingProviderOperatorInfo = async ( listenerApi.dispatch(accountUsedAsStakingProvider()) const mappedOperators = - await listenerApi.extra.threshold.multiAppStaking.getMappedOperatorsForStakingProvider( + await threshold.multiAppStaking.getMappedOperatorsForStakingProvider( address ) 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 dcaf10726..f6b4874f9 100644 --- a/src/store/staking-applications/effects.ts +++ b/src/store/staking-applications/effects.ts @@ -24,11 +24,26 @@ import { import { isAddressZero } from "../../web3/utils" import { BigNumber } from "ethers" import { MAX_UINT64 } from "../../threshold-ts/utils" +import { isSameChainId } from "../../networks/utils" export const getSupportedAppsEffect = async ( action: ReturnType, listenerApi: AppListenerEffectAPI ) => { + const { account } = listenerApi.getState() + + if ( + !account.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 + try { listenerApi.unsubscribe() listenerApi.dispatch( @@ -50,31 +65,33 @@ export const getSupportedAppsEffect = async ( 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( @@ -124,27 +141,43 @@ export const getSupportedAppsStakingProvidersData = async ( action: ReturnType, listenerApi: AppListenerEffectAPI ) => { + const { account } = listenerApi.getState() + const threshold = listenerApi.extra.threshold + + if ( + !account.chainId || + !isSameChainId(account.chainId, threshold.config.ethereum.chainId) || + !threshold.multiAppStaking.ecdsa || + !threshold.multiAppStaking.randomBeacon || + !threshold.multiAppStaking.taco + ) + return + 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() 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 ) @@ -392,6 +425,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..4180d3955 100644 --- a/src/store/staking/effects.ts +++ b/src/store/staking/effects.ts @@ -1,5 +1,6 @@ +import { isSameChainId } from "../../networks/utils" import { StakeData } from "../../types" -import { AddressZero, isAddress, isAddressZero } from "../../web3/utils" +import { isAddress, isAddressZero } from "../../web3/utils" import { AppListenerEffectAPI } from "../listener" import { selectStakeByStakingProvider } from "./selectors" import { requestStakeByStakingProvider, setStakes } from "./stakingSlice" @@ -8,12 +9,17 @@ export const fetchStakeByStakingProviderEffect = async ( actionCreator: ReturnType, listenerApi: AppListenerEffectAPI ) => { + const { account } = listenerApi.getState() const { stakingProvider } = actionCreator.payload + const { config } = listenerApi.extra.threshold if ( + !listenerApi.extra.threshold.staking || !stakingProvider || !isAddress(stakingProvider) || - isAddressZero(stakingProvider) + isAddressZero(stakingProvider) || + !account.chainId || + !isSameChainId(account.chainId, config.ethereum.chainId) ) return diff --git a/src/store/staking/stakingSlice.ts b/src/store/staking/stakingSlice.ts index 89f347301..3e5c2f71b 100644 --- a/src/store/staking/stakingSlice.ts +++ b/src/store/staking/stakingSlice.ts @@ -9,7 +9,6 @@ import { ToppedUpActionPayload, } from "../../types/staking" import { StakeType, TopUpType, UnstakeType } from "../../enums" -import { AddressZero } from "../../web3/utils" import { UpdateStateActionPayload } from "../../types/state" import { startAppListening } from "../listener" import { fetchStakeByStakingProviderEffect } from "./effects" diff --git a/src/store/tbtc/effects.ts b/src/store/tbtc/effects.ts index e59c9a474..2e0626361 100644 --- a/src/store/tbtc/effects.ts +++ b/src/store/tbtc/effects.ts @@ -6,28 +6,39 @@ import { } from "../../threshold-ts/utils" import { MintingStep } from "../../types/tbtc" import { ONE_SEC_IN_MILISECONDS } from "../../utils/date" -import { - key, - removeDataForAccount, - TBTCLocalStorageDepositData, -} from "../../utils/tbtcLocalStorageData" import { isAddress, isAddressZero } from "../../web3/utils" import { AppListenerEffectAPI } from "../listener" import { tbtcSlice } from "./tbtcSlice" +import { + getChainIdToNetworkName, + isL1Network, + isSameChainId, +} from "../../networks/utils" export const fetchBridgeactivityEffect = async ( action: ReturnType, listenerApi: AppListenerEffectAPI ) => { + const { account } = listenerApi.getState() const { depositor } = action.payload - if (!isAddress(depositor) || isAddressZero(depositor)) return + + if ( + !isAddress(depositor) || + isAddressZero(depositor) || + !account.chainId || + !isSameChainId( + account.chainId, + listenerApi.extra.threshold.config.ethereum.chainId + ) + ) + return listenerApi.unsubscribe() listenerApi.dispatch(tbtcSlice.actions.fetchingBridgeActivity()) try { - const data = await listenerApi.extra.threshold.tbtc.bridgeActivity( + const data = await listenerApi.extra.threshold.tbtc.getBridgeActivity( depositor ) listenerApi.dispatch(tbtcSlice.actions.bridgeActivityFetched(data)) @@ -39,6 +50,8 @@ export const fetchBridgeactivityEffect = async ( error: "Could not fetch bridge activity.", }) ) + } finally { + listenerApi.subscribe() } } @@ -46,15 +59,17 @@ export const findUtxoEffect = async ( action: ReturnType, listenerApi: AppListenerEffectAPI ) => { - const { btcDepositAddress, depositor } = action.payload + const { btcDepositAddress, chainId } = action.payload const { tbtc: { - ethAddress, + depositor, blindingFactor, walletPublicKeyHash, refundLocktime, btcRecoveryAddress, + chainName, + extraData, }, } = listenerApi.getState() @@ -70,6 +85,9 @@ export const findUtxoEffect = async ( const pollingTask = listenerApi.fork(async (forkApi) => { try { while (true) { + if (getChainIdToNetworkName(chainId) !== chainName) { + throw new Error("Chain ID and deposit chain name mismatch") + } // Initiating deposit from redux store (if deposit object is empty) if (!listenerApi.extra.threshold.tbtc.deposit) { const bitcoinNetwork = listenerApi.extra.threshold.tbtc.bitcoinNetwork @@ -83,17 +101,31 @@ export const findUtxoEffect = async ( btcRecoveryAddress, bitcoinNetwork ).toString() - await forkApi.pause( - listenerApi.extra.threshold.tbtc.initiateDepositFromDepositScriptParameters( - { - depositor: getChainIdentifier(ethAddress), - blindingFactor, - walletPublicKeyHash, - refundPublicKeyHash, - refundLocktime, - } + const depositParams = { + depositor: getChainIdentifier(depositor), + blindingFactor, + walletPublicKeyHash, + refundPublicKeyHash, + refundLocktime, + } + + if (isL1Network(chainId)) { + await forkApi.pause( + listenerApi.extra.threshold.tbtc.initiateDepositFromDepositScriptParameters( + depositParams + ) ) - ) + } else { + await forkApi.pause( + listenerApi.extra.threshold.tbtc.initiateCrossChainDepositFromScriptParameters( + { + ...depositParams, + extraData, + }, + chainId + ) + ) + } } // Looking for utxo. @@ -141,36 +173,30 @@ export const findUtxoEffect = async ( } } + listenerApi.dispatch( + tbtcSlice.actions.updateState({ + key: "utxo", + value: { + ...utxo, + transactionHash: utxo.transactionHash.toString(), + value: utxo.value.toString(), + }, + }) + ) + if (areAllDepositRevealed) { // All deposits are already revealed. Force start from step 1 and // remove deposit data. - removeDataForAccount( - depositor, - JSON.parse( - localStorage.getItem(key) || "{}" - ) as TBTCLocalStorageDepositData - ) listenerApi.dispatch( tbtcSlice.actions.updateState({ key: "mintingStep", - value: MintingStep.ProvideData, + value: MintingStep.MintingSuccess, }) ) } else { // UTXO exists for a given Bitcoin deposit address and deposit is not // yet revealed. Redirect to step 3 to reveal the deposit and set // utxo. - - listenerApi.dispatch( - tbtcSlice.actions.updateState({ - key: "utxo", - value: { - ...utxo, - transactionHash: utxo.transactionHash.toString(), - value: utxo.value.toString(), - }, - }) - ) listenerApi.dispatch( tbtcSlice.actions.updateState({ key: "mintingStep", diff --git a/src/store/tbtc/tbtcSlice.ts b/src/store/tbtc/tbtcSlice.ts index c0ce5ea11..c19b06ad3 100644 --- a/src/store/tbtc/tbtcSlice.ts +++ b/src/store/tbtc/tbtcSlice.ts @@ -108,7 +108,7 @@ export const tbtcSlice = createSlice({ state, action: PayloadAction<{ btcDepositAddress: string - depositor: string + chainId: number }> ) => {}, fetchUtxoConfirmations: ( 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 09e9019c1..94ecd70c0 100644 --- a/src/threshold-ts/index.ts +++ b/src/threshold-ts/index.ts @@ -19,19 +19,17 @@ 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 - ) + const { ethereum, bitcoin } = config + + 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, - config.ethereum + ethereum ) - this.tbtc = new TBTC(config.ethereum, config.bitcoin, this.multicall) + this.tbtc = new TBTC(ethereum, bitcoin) } updateConfig = (config: ThresholdConfig) => { diff --git a/src/threshold-ts/mas/index.ts b/src/threshold-ts/mas/index.ts index 42700c642..8b4e01113 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 @@ -43,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, @@ -54,94 +34,145 @@ export class MultiAppStaking { ) { this._staking = staking this._multicall = multicall - this.randomBeacon = new Application(this._staking, this._multicall, { - address: RandomBeacon.address, - abi: RandomBeacon.abi, - ...config, - }) + const randomBeaconArtifact = getArtifact( + "RandomBeacon", + config.chainId, + config.shouldUseTestnetDevelopmentContracts + ) + 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.taco = new Application(this._staking, this._multicall, { - address: TacoRegistry.address, - abi: TacoRegistry.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 = 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 [mappedOperatorTbtc, mappedOperatorRandomBeacon, mappedOperatorTaco] = - await this._multicall.aggregate(calls) + const callResults = await this._multicall.aggregate(calls) - return { - tbtc: mappedOperatorTbtc.toString(), - randomBeacon: mappedOperatorRandomBeacon.toString(), - taco: mappedOperatorTaco.toString(), + if (this.ecdsa) { + results.tbtc = callResults[index++].toString() } + + if (this.randomBeacon) { + results.randomBeacon = callResults[index++].toString() + } + + if (this.taco) { + results.taco = callResults[index++].toString() + } + + return results } } 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..1127b57d4 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,30 +39,40 @@ 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.ArbitrumSepolia]: + "0xcA11bde05977b3631167028862bE2a173976CA11", + [SupportedChainIds.Arbitrum]: "0xcA11bde05977b3631167028862bE2a173976CA11", + [SupportedChainIds.Base]: "0xcA11bde05977b3631167028862bE2a173976CA11", + [SupportedChainIds.BaseSepolia]: "0xcA11bde05977b3631167028862bE2a173976CA11", + [SupportedChainIds.Localhost]: process.env.REACT_APP_MULTICALL_ADDRESS, } as Record export class Multicall implements IMulticall { - private _multicall: Contract + private _multicall: Contract | null constructor(config: EthereumConfig) { - const address = MULTICALL_ADDRESSESS[config.chainId] - if (!address) { - throw new Error("Unsupported chain id") - } + const address = MULTICALL_ADDRESSES[config.chainId] - 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), @@ -76,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, 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..686fd7716 100644 --- a/src/threshold-ts/staking/index.ts +++ b/src/threshold-ts/staking/index.ts @@ -1,12 +1,15 @@ -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 { + BigNumber, + BigNumberish, + Contract, + ContractTransaction, + constants, +} from "ethers" import { ContractCall, IMulticall } from "../multicall" import { EthereumConfig } from "../types" import { getArtifact, getContract, - getContractAddressFromTruffleArtifact, getContractPastEvents, isAddress, isSameETHAddress, @@ -49,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. @@ -68,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( @@ -107,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 @@ -120,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 @@ -132,30 +135,48 @@ export class Staking implements IStaking { multicall: IMulticall, vendingMachines: IVendingMachines ) { - this.STAKING_CONTRACT_DEPLOYMENT_BLOCK = config.chainId === 1 ? 14113768 : 0 - this._staking = getContract( - TokenStaking.address, - TokenStaking.abi, - config.providerOrSigner, - config.account + this.STAKING_CONTRACT_DEPLOYMENT_BLOCK = + config.chainId === 1 ? 14113768 : 4320502 + + const stakingArtifact = getArtifact( + "TokenStaking", + config.chainId, + config.shouldUseTestnetDevelopmentContracts ) - this._legacyKeepStaking = getContract( - getContractAddressFromTruffleArtifact(KeepTokenStaking), - KeepTokenStaking.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 ) - const NuCypherStakingEscrowArtifact = getArtifact( + 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 } @@ -164,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) } @@ -180,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, @@ -191,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 + + let nuStakingProvider = constants.AddressZero + let nuStake = ZERO - const possibleNuTopUpInT = + 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) ) @@ -261,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, @@ -276,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, @@ -310,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( @@ -342,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], }) @@ -357,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/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/index.ts b/src/threshold-ts/tbtc/index.ts index d8c2d178f..8a7de996c 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, @@ -41,7 +43,17 @@ import { isSameETHAddress, isValidBtcAddress, ZERO, + ArtifactNameType, + L2_RELAYER_BOT_WALLET, } from "../utils" +import { + isL1Network, + isL2Network, + getChainIdToNetworkName, + getMainnetOrTestnetChainId, +} from "../../networks/utils" +import { SupportedChainIds } from "../../networks/enums/networks" +import { getThresholdLibProvider } from "../../utils/getThresholdLib" export enum BridgeActivityStatus { PENDING = "PENDING", @@ -80,6 +92,16 @@ export interface RevealedDepositEvent { blockNumber: number } +export interface RevealedL2DepositEvent { + depositKey: string + l2DepositOwner: string + l1Sender: string + initialAmount: string + tbtcAmount: string + txHash: string + blockNumber: number +} + export interface RedemptionRequestedEvent { amount: string walletPublicKeyHash: string @@ -156,6 +178,7 @@ export type DepositScriptParameters = { walletPublicKeyHash: string refundPublicKeyHash: string refundLocktime: string + extraData?: string } class EmptySdkObjectError extends Error { @@ -184,14 +207,18 @@ export interface ITBTC { */ readonly bitcoinNetwork: BitcoinNetwork - readonly bridgeContract: Contract + readonly bridgeContract: Contract | null + + readonly vaultContract: Contract | null - readonly vaultContract: Contract + readonly tokenContract: Contract | null - readonly tokenContract: Contract + readonly l1BitcoinDepositorContract: 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 +238,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 +266,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. @@ -253,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 }> /** @@ -296,7 +360,7 @@ export interface ITBTC { * @param account Ethereum address. * @returns Bridge transaction history @see {@link BridgeActivity}. */ - bridgeActivity(account: string): Promise + getBridgeActivity(account: string): Promise /** * Builds the deposit key required to refer a revealed deposit. @@ -413,11 +477,12 @@ export interface ITBTC { } export class TBTC implements ITBTC { - private _bridgeContract: Contract - private _tbtcVaultContract: Contract - private _tokenContract: Contract - private _bitcoinClient: BitcoinClient + 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 private _bitcoinConfig: BitcoinConfig private readonly _satoshiMultiplier = BigNumber.from(10).pow(10) @@ -443,12 +508,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 +522,80 @@ export class TBTC implements ITBTC { providerOrSigner, account, } = ethereumConfig - - const tbtcVaultArtifact = getArtifact( - "TBTCVault", - chainId, - shouldUseTestnetDevelopmentContracts + this._isCrossChain = isL2Network(chainId) + + // This ensures that, if the user is connected to an L2 network, the TBTC + // contracts are connected to the corresponding Ethereum mainnet or testnet + // based on which type of network the user is connected to. + const mainnetOrTestnetEthereumChainId = getMainnetOrTestnetChainId(chainId) + const defaultOrConnectedProvider = getThresholdLibProvider( + mainnetOrTestnetEthereumChainId ) + const bridgeArtifact = getArtifact( "Bridge", - chainId, + mainnetOrTestnetEthereumChainId, + shouldUseTestnetDevelopmentContracts + ) + const tbtcVaultArtifact = getArtifact( + "TBTCVault", + mainnetOrTestnetEthereumChainId, shouldUseTestnetDevelopmentContracts ) const tbtcTokenArtifact = getArtifact( "TBTC", - chainId, + mainnetOrTestnetEthereumChainId, shouldUseTestnetDevelopmentContracts ) - this._bridgeContract = getContract( - bridgeArtifact.address, - bridgeArtifact.abi, - providerOrSigner, - account - ) - this._tbtcVaultContract = getContract( - tbtcVaultArtifact.address, - tbtcVaultArtifact.abi, - providerOrSigner, - account - ) - this._tokenContract = getContract( - tbtcTokenArtifact.address, - tbtcTokenArtifact.abi, - providerOrSigner, - 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, + chainId: mainnetOrTestnetEthereumChainId, + }) + + if (this._isCrossChain) { + const networkName = getChainIdToNetworkName(chainId) + const l1BitcoinDepositorArtifact = getArtifact( + `${networkName}L1BitcoinDepositor` as ArtifactNameType, + mainnetOrTestnetEthereumChainId, + shouldUseTestnetDevelopmentContracts + ) + + this._l1BitcoinDepositorContract = l1BitcoinDepositorArtifact + ? getContract( + l1BitcoinDepositorArtifact.address, + l1BitcoinDepositorArtifact.abi, + defaultOrConnectedProvider, + account + ) + : null + } + // @ts-ignore this._bitcoinClient = bitcoinConfig.client ?? @@ -503,7 +604,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 +615,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 +651,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 +670,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 +706,14 @@ export class TBTC implements ITBTC { return this._tokenContract } + get l1BitcoinDepositorContract() { + return this._l1BitcoinDepositorContract + } + + get isCrossChain(): boolean { + return this._isCrossChain + } + private _getSdk = async (): Promise => { const sdk = await this._sdkPromise if (!sdk) throw new EmptySdkObjectError() @@ -591,12 +721,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 +766,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 +789,62 @@ 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, + 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() @@ -641,8 +857,15 @@ export class TBTC implements ITBTC { } getEstimatedDepositFees = async (depositAmount: string) => { - const { depositTreasuryFeeDivisor, optimisticMintingFeeDivisor } = - await this._getDepositFees() + const { + depositTreasuryFeeDivisor, + optimisticMintingFeeDivisor, + depositTxMaxFee, + } = await this.getDepositFees() + + const crossChainTxFee = this.isCrossChain + ? BigNumber.from(depositTxMaxFee) + : ZERO // https://github.com/keep-network/tbtc-v2/blob/main/solidity/contracts/bridge/Deposit.sol#L258-L260 const treasuryFee = BigNumber.from(depositTreasuryFeeDivisor).gt(0) @@ -653,41 +876,45 @@ export class TBTC implements ITBTC { this._calculateOptimisticMintingAmountAndFee( BigNumber.from(depositAmount), treasuryFee, - optimisticMintingFeeDivisor + optimisticMintingFeeDivisor, + depositTxMaxFee ) return { treasuryFee: treasuryFee.mul(this._satoshiMultiplier).toString(), optimisticMintFee: optimisticMintFee.toString(), amountToMint: amountToMint.toString(), + crossChainFee: crossChainTxFee.mul(this._satoshiMultiplier).toString(), } } - private _getDepositFees = async (): Promise<{ + getDepositFees = async (): Promise<{ depositTreasuryFeeDivisor: BigNumber optimisticMintingFeeDivisor: BigNumber + depositTxMaxFee: BigNumber }> => { 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 ) + const depositTxMaxFee = BigNumber.from(depositParams.depositTxMaxFee) const optimisticMintingFeeDivisor = BigNumber.from( _optimisticMintingFeeDivisor[0] ) @@ -695,15 +922,22 @@ export class TBTC implements ITBTC { return { depositTreasuryFeeDivisor, optimisticMintingFeeDivisor, + depositTxMaxFee, } } 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) @@ -758,8 +992,8 @@ export class TBTC implements ITBTC { return 6 } - bridgeActivity = async (account: string): Promise => { - const depositActivities = await this._findDepositActivities(account) + getBridgeActivity = async (account: string): Promise => { + const depositActivities = await this._findAllDepositActivities(account) const redemptionActivities: BridgeActivity[] = await this._findRedemptionActivities(account) @@ -769,21 +1003,81 @@ export class TBTC implements ITBTC { .sort((a, b) => b.blockNumber - a.blockNumber) } - private _findDepositActivities = async ( + private _findAllDepositActivities = async ( + depositor: string + ): Promise => { + const l1DepositActivities = await this._findL1DepositActivities(depositor) + + let l2DepositActivities: BridgeActivity[] = [] + if (this.isCrossChain) { + l2DepositActivities = await this._findL2DepositActivities(depositor) + } + + const depositActivities = [...l1DepositActivities, ...l2DepositActivities] + depositActivities.sort((a, b) => a.blockNumber - b.blockNumber) + + return depositActivities + } + + findAllRevealedDeposits = async ( + depositor: string + ): Promise => { + const chainId = getMainnetOrTestnetChainId(this.ethereumChainId) + + const bridgeArtifact = getArtifact( + "Bridge", + chainId, + this._ethereumConfig.shouldUseTestnetDevelopmentContracts + ) + + 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", + }) + + return deposits + .map((deposit) => { + const fundingTxHash = deposit.args?.fundingTxHash + const fundingOutputIndex = deposit.args?.fundingOutputIndex + + const depositKey = this.buildDepositKey( + fundingTxHash, + fundingOutputIndex + ) + + return { + amount: deposit.args?.amount.toString(), + walletPublicKeyHash: deposit.args?.walletPubKeyHash, + fundingTxHash, + fundingOutputIndex, + depositKey, + txHash: deposit.transactionHash, + blockNumber: deposit.blockNumber, + } + }) + .reverse() + } + + private _findL1DepositActivities = async ( depositor: string ): Promise => { - // We can assume that all revealed deposits have `PENDING` status. const revealedDeposits = await this.findAllRevealedDeposits(depositor) const depositKeys = revealedDeposits.map((_) => _.depositKey) + const estimatedAmountToMintByDepositKey = + await this._calculateEstimatedAmountToMintForRevealedDeposits(depositKeys) + const mintedDepositEvents = await this._findAllMintedDeposits( depositor, depositKeys ) - const estimatedAmountToMintByDepositKey = - await this._calculateEstimatedAmountToMintForRevealedDeposits(depositKeys) - const mintedDeposits = new Map( mintedDepositEvents.map((event) => [ (event.args?.depositKey as BigNumber).toHexString(), @@ -797,6 +1091,7 @@ export class TBTC implements ITBTC { event.transactionHash, ]) ) + const mintedAmountByTxHash = new Map( await Promise.all( Array.from(mintedDeposits.values()).map((txHash) => @@ -827,57 +1122,141 @@ export class TBTC implements ITBTC { activityKey: depositKey, bridgeProcess: "mint", blockNumber, - } + } as BridgeActivity }) } - findAllRevealedDeposits = async ( + private _findL2DepositActivities = async ( depositor: string - ): Promise => { - const bridgeArtifact = getArtifact( - "Bridge", - this.ethereumChainId, - this._ethereumConfig.shouldUseTestnetDevelopmentContracts + ): Promise => { + const l2DepositActivities: BridgeActivity[] = [] + + const l2AllRevealedDeposits = await this.findAllRevealedDeposits( + this.l1BitcoinDepositorContract?.address as string ) - const deposits = await getContractPastEvents(this._bridgeContract, { - fromBlock: bridgeArtifact.receipt.blockNumber, - filterParams: [null, null, depositor], - eventName: "DepositRevealed", + const l2DepositKeys = l2AllRevealedDeposits.map((_) => _.depositKey) + + const estimatedAmountToMintByDepositKey = + await this._calculateEstimatedAmountToMintForRevealedDeposits( + l2DepositKeys + ) + + const l2InitializedDepositsEvents = + await this._findAllInitializedL2Deposits(depositor) + const l2FinalizedDepositsEvents = await this._findAllFinalizedL2Deposits( + depositor + ) + + const l2InitializedDeposits = new Map( + l2InitializedDepositsEvents.map((event) => [ + (event.args?.depositKey as BigNumber).toHexString(), + event.transactionHash, + ]) + ) + + const l2FinalizedDeposits = new Map( + l2FinalizedDepositsEvents.map((event) => [ + (event.args?.depositKey as BigNumber).toHexString(), + event.transactionHash, + ]) + ) + + const l2FinalizedDepositAmountByTxHash = new Map( + l2FinalizedDepositsEvents.map((event) => [ + event.transactionHash, + event.args?.tbtcAmount as BigNumber, + ]) + ) + + for (const l2Deposit of l2AllRevealedDeposits) { + const { depositKey, txHash: depositTxHash, blockNumber } = l2Deposit + + if (!l2InitializedDeposits.has(depositKey)) continue + + let status = BridgeActivityStatus.PENDING + let txHash = depositTxHash + let amount = estimatedAmountToMintByDepositKey.get(depositKey) ?? ZERO + + if (l2FinalizedDeposits.has(depositKey)) { + status = BridgeActivityStatus.MINTED + txHash = l2FinalizedDeposits.get(depositKey)! + amount = l2FinalizedDepositAmountByTxHash.get(txHash)! + } + + l2DepositActivities.push({ + amount: amount.toString(), + txHash, + status, + activityKey: depositKey, + bridgeProcess: "mint", + blockNumber, + } as BridgeActivity) + } + + return l2DepositActivities + } + + private _findAllFinalizedL2Deposits = async ( + depositor: string + ): Promise> => { + const l2DepositOwner = depositor + const l1Sender = L2_RELAYER_BOT_WALLET + + const l1BitcoinDepositorArtifact = getArtifact( + `${getChainIdToNetworkName( + this.ethereumChainId + )}L1BitcoinDepositor` as ArtifactNameType, + 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], + eventName: "DepositFinalized", }) + } - return deposits - .map((deposit) => { - const fundingTxHash = deposit.args?.fundingTxHash - const fundingOutputIndex = deposit.args?.fundingOutputIndex + private _findAllInitializedL2Deposits = async ( + depositor: string + ): Promise> => { + const l2DepositOwner = depositor + const l1Sender = L2_RELAYER_BOT_WALLET + + const l1BitcoinDepositorArtifact = getArtifact( + `${getChainIdToNetworkName( + this.ethereumChainId + )}L1BitcoinDepositor` as ArtifactNameType, + getMainnetOrTestnetChainId(this.ethereumChainId) + ) - const depositKey = this.buildDepositKey( - fundingTxHash, - fundingOutputIndex - ) + if (!l1BitcoinDepositorArtifact || !this._l1BitcoinDepositorContract) { + console.warn("L1 Bitcoin Depositor contract is not initialized.") + return [] + } - return { - amount: deposit.args?.amount.toString(), - walletPublicKeyHash: deposit.args?.walletPubKeyHash, - fundingTxHash, - fundingOutputIndex, - depositKey, - txHash: deposit.transactionHash, - blockNumber: deposit.blockNumber, - } - }) - .reverse() + return await getContractPastEvents(this._l1BitcoinDepositorContract!, { + fromBlock: l1BitcoinDepositorArtifact.receipt.blockNumber, + filterParams: [null, l2DepositOwner, l1Sender], + eventName: "DepositInitialized", + }) } private _calculateEstimatedAmountToMintForRevealedDeposits = async ( depositKeys: string[] ): Promise> => { - const { optimisticMintingFeeDivisor } = await this._getDepositFees() + const { optimisticMintingFeeDivisor, depositTxMaxFee } = + await this.getDepositFees() const deposits = ( 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], })) @@ -895,7 +1274,8 @@ export class TBTC implements ITBTC { this._calculateOptimisticMintingAmountAndFee( deposit.amount, deposit.treasuryFee, - optimisticMintingFeeDivisor + optimisticMintingFeeDivisor, + depositTxMaxFee ).amountToMint, ] }) @@ -906,16 +1286,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,11 +1309,19 @@ 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 ) + + 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], @@ -944,11 +1332,19 @@ 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 ) + + if (!tbtcVaultArtifact || !this._tbtcVaultContract) { + console.warn("TBTC vault contract is not initialized.") + return [] + } + return getContractPastEvents(this._tbtcVaultContract, { fromBlock: tbtcVaultArtifact.receipt.blockNumber, filterParams: [null, depositKeys], @@ -967,7 +1363,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 +1558,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 +1570,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 +1611,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 +1667,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 +1699,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 +1755,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 } diff --git a/src/threshold-ts/tbtc/mainnet-artifacts/ArbitrumL1BitcoinDepositor.json b/src/threshold-ts/tbtc/mainnet-artifacts/ArbitrumL1BitcoinDepositor.json new file mode 100644 index 000000000..979987aff --- /dev/null +++ b/src/threshold-ts/tbtc/mainnet-artifacts/ArbitrumL1BitcoinDepositor.json @@ -0,0 +1,737 @@ +{ + "address": "0x75A6e4A7C8fAa162192FAD6C1F7A6d48992c619A", + "abi": [ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "depositKey", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "l2DepositOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "l1Sender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "initialAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tbtcAmount", + "type": "uint256" + } + ], + "name": "DepositFinalized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "depositKey", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "l2DepositOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "l1Sender", + "type": "address" + } + ], + "name": "DepositInitialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "initializeDepositGasOffset", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "finalizeDepositGasOffset", + "type": "uint256" + } + ], + "name": "GasOffsetParametersUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "l2FinalizeDepositGasLimit", + "type": "uint256" + } + ], + "name": "L2FinalizeDepositGasLimitUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "_address", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "authorization", + "type": "bool" + } + ], + "name": "ReimbursementAuthorizationUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "newReimbursementPool", + "type": "address" + } + ], + "name": "ReimbursementPoolUpdated", + "type": "event" + }, + { + "inputs": [], + "name": "SATOSHI_MULTIPLIER", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_l2BitcoinDepositor", + "type": "address" + } + ], + "name": "attachL2BitcoinDepositor", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "bridge", + "outputs": [ + { + "internalType": "contract IBridge", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "deposits", + "outputs": [ + { + "internalType": "enum L1BitcoinDepositor.DepositState", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "depositKey", + "type": "uint256" + } + ], + "name": "finalizeDeposit", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "finalizeDepositGasOffset", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "gasReimbursements", + "outputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "uint96", + "name": "gasSpent", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_tbtcBridge", + "type": "address" + }, + { + "internalType": "address", + "name": "_tbtcVault", + "type": "address" + }, + { + "internalType": "address", + "name": "_wormhole", + "type": "address" + }, + { + "internalType": "address", + "name": "_wormholeRelayer", + "type": "address" + }, + { + "internalType": "address", + "name": "_wormholeTokenBridge", + "type": "address" + }, + { + "internalType": "address", + "name": "_l2WormholeGateway", + "type": "address" + }, + { + "internalType": "uint16", + "name": "_l2ChainId", + "type": "uint16" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes4", + "name": "version", + "type": "bytes4" + }, + { + "internalType": "bytes", + "name": "inputVector", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "outputVector", + "type": "bytes" + }, + { + "internalType": "bytes4", + "name": "locktime", + "type": "bytes4" + } + ], + "internalType": "struct IBridgeTypes.BitcoinTxInfo", + "name": "fundingTx", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint32", + "name": "fundingOutputIndex", + "type": "uint32" + }, + { + "internalType": "bytes8", + "name": "blindingFactor", + "type": "bytes8" + }, + { + "internalType": "bytes20", + "name": "walletPubKeyHash", + "type": "bytes20" + }, + { + "internalType": "bytes20", + "name": "refundPubKeyHash", + "type": "bytes20" + }, + { + "internalType": "bytes4", + "name": "refundLocktime", + "type": "bytes4" + }, + { + "internalType": "address", + "name": "vault", + "type": "address" + } + ], + "internalType": "struct IBridgeTypes.DepositRevealInfo", + "name": "reveal", + "type": "tuple" + }, + { + "internalType": "address", + "name": "l2DepositOwner", + "type": "address" + } + ], + "name": "initializeDeposit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "initializeDepositGasOffset", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "l2BitcoinDepositor", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "l2ChainId", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "l2FinalizeDepositGasLimit", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "l2WormholeGateway", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "quoteFinalizeDeposit", + "outputs": [ + { + "internalType": "uint256", + "name": "cost", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "reimbursementAuthorizations", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "reimbursementPool", + "outputs": [ + { + "internalType": "contract ReimbursementPool", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "tbtcToken", + "outputs": [ + { + "internalType": "contract IERC20Upgradeable", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "tbtcVault", + "outputs": [ + { + "internalType": "contract ITBTCVault", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_initializeDepositGasOffset", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_finalizeDepositGasOffset", + "type": "uint256" + } + ], + "name": "updateGasOffsetParameters", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_l2FinalizeDepositGasLimit", + "type": "uint256" + } + ], + "name": "updateL2FinalizeDepositGasLimit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_address", + "type": "address" + }, + { + "internalType": "bool", + "name": "authorization", + "type": "bool" + } + ], + "name": "updateReimbursementAuthorization", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract ReimbursementPool", + "name": "_reimbursementPool", + "type": "address" + } + ], + "name": "updateReimbursementPool", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "wormhole", + "outputs": [ + { + "internalType": "contract IWormhole", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "wormholeRelayer", + "outputs": [ + { + "internalType": "contract IWormholeRelayer", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "wormholeTokenBridge", + "outputs": [ + { + "internalType": "contract IWormholeTokenBridge", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "transactionHash": "0x51e2686f22fd29a987096d0c27b9d1c7256e64cd37fd0a31a0bc316bbfc2b92b", + "receipt": { + "to": null, + "from": "0x949f0ADFDA95351829E49aEec0f99371A227572d", + "contractAddress": "0x75A6e4A7C8fAa162192FAD6C1F7A6d48992c619A", + "transactionIndex": 75, + "gasUsed": "866087", + "logsBloom": "0x00000000000000000000000080001000400000000000000000800000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000002000001400000000000000000000000000000000000020000000000000000000800000000800000000000000000000000400000000000000000000000000000000000000200000080000080040004800000000000000000000000000000000400000000000000000000000000000000000000000020000000000000000000040000000000000400100000000000000020000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xca28b9305b8bd5685b90d6dc17819fb68d14198e4812b0675e93aab068836f3f", + "transactionHash": "0x51e2686f22fd29a987096d0c27b9d1c7256e64cd37fd0a31a0bc316bbfc2b92b", + "logs": [ + { + "transactionIndex": 75, + "blockNumber": 20632547, + "transactionHash": "0x51e2686f22fd29a987096d0c27b9d1c7256e64cd37fd0a31a0bc316bbfc2b92b", + "address": "0x75A6e4A7C8fAa162192FAD6C1F7A6d48992c619A", + "topics": [ + "0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b", + "0x000000000000000000000000ff79fca71751a5a0c4487a1ace268d6cd2a64db1" + ], + "data": "0x", + "logIndex": 148, + "blockHash": "0xca28b9305b8bd5685b90d6dc17819fb68d14198e4812b0675e93aab068836f3f" + }, + { + "transactionIndex": 75, + "blockNumber": 20632547, + "transactionHash": "0x51e2686f22fd29a987096d0c27b9d1c7256e64cd37fd0a31a0bc316bbfc2b92b", + "address": "0x75A6e4A7C8fAa162192FAD6C1F7A6d48992c619A", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000949f0adfda95351829e49aeec0f99371a227572d" + ], + "data": "0x", + "logIndex": 149, + "blockHash": "0xca28b9305b8bd5685b90d6dc17819fb68d14198e4812b0675e93aab068836f3f" + }, + { + "transactionIndex": 75, + "blockNumber": 20632547, + "transactionHash": "0x51e2686f22fd29a987096d0c27b9d1c7256e64cd37fd0a31a0bc316bbfc2b92b", + "address": "0x75A6e4A7C8fAa162192FAD6C1F7A6d48992c619A", + "topics": [ + "0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498" + ], + "data": "0x0000000000000000000000000000000000000000000000000000000000000001", + "logIndex": 150, + "blockHash": "0xca28b9305b8bd5685b90d6dc17819fb68d14198e4812b0675e93aab068836f3f" + }, + { + "transactionIndex": 75, + "blockNumber": 20632547, + "transactionHash": "0x51e2686f22fd29a987096d0c27b9d1c7256e64cd37fd0a31a0bc316bbfc2b92b", + "address": "0x75A6e4A7C8fAa162192FAD6C1F7A6d48992c619A", + "topics": [ + "0x7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f" + ], + "data": "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000037169570d846cc05d5848aaa30194d308b355638", + "logIndex": 151, + "blockHash": "0xca28b9305b8bd5685b90d6dc17819fb68d14198e4812b0675e93aab068836f3f" + } + ], + "blockNumber": 20632547, + "cumulativeGasUsed": "6345110", + "status": 1, + "byzantium": true + }, + "numDeployments": 1, + "implementation": "0xFf79fca71751A5A0C4487a1aCE268d6cd2A64Db1", + "devdoc": "Contract deployed as upgradable proxy" +} diff --git a/src/threshold-ts/tbtc/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/ArbitrumL1BitcoinDepositor.json b/src/threshold-ts/tbtc/sepolia-artifacts/ArbitrumL1BitcoinDepositor.json new file mode 100644 index 000000000..3d4267f71 --- /dev/null +++ b/src/threshold-ts/tbtc/sepolia-artifacts/ArbitrumL1BitcoinDepositor.json @@ -0,0 +1,737 @@ +{ + "address": "0xD9B523fb879C63b00ef14e48C98f4e3398d3BA2D", + "abi": [ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "depositKey", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "l2DepositOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "l1Sender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "initialAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tbtcAmount", + "type": "uint256" + } + ], + "name": "DepositFinalized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "depositKey", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "l2DepositOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "l1Sender", + "type": "address" + } + ], + "name": "DepositInitialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "initializeDepositGasOffset", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "finalizeDepositGasOffset", + "type": "uint256" + } + ], + "name": "GasOffsetParametersUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "l2FinalizeDepositGasLimit", + "type": "uint256" + } + ], + "name": "L2FinalizeDepositGasLimitUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "_address", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "authorization", + "type": "bool" + } + ], + "name": "ReimbursementAuthorizationUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "newReimbursementPool", + "type": "address" + } + ], + "name": "ReimbursementPoolUpdated", + "type": "event" + }, + { + "inputs": [], + "name": "SATOSHI_MULTIPLIER", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_l2BitcoinDepositor", + "type": "address" + } + ], + "name": "attachL2BitcoinDepositor", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "bridge", + "outputs": [ + { + "internalType": "contract IBridge", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "deposits", + "outputs": [ + { + "internalType": "enum L1BitcoinDepositor.DepositState", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "depositKey", + "type": "uint256" + } + ], + "name": "finalizeDeposit", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "finalizeDepositGasOffset", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "gasReimbursements", + "outputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "uint96", + "name": "gasSpent", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_tbtcBridge", + "type": "address" + }, + { + "internalType": "address", + "name": "_tbtcVault", + "type": "address" + }, + { + "internalType": "address", + "name": "_wormhole", + "type": "address" + }, + { + "internalType": "address", + "name": "_wormholeRelayer", + "type": "address" + }, + { + "internalType": "address", + "name": "_wormholeTokenBridge", + "type": "address" + }, + { + "internalType": "address", + "name": "_l2WormholeGateway", + "type": "address" + }, + { + "internalType": "uint16", + "name": "_l2ChainId", + "type": "uint16" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes4", + "name": "version", + "type": "bytes4" + }, + { + "internalType": "bytes", + "name": "inputVector", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "outputVector", + "type": "bytes" + }, + { + "internalType": "bytes4", + "name": "locktime", + "type": "bytes4" + } + ], + "internalType": "struct IBridgeTypes.BitcoinTxInfo", + "name": "fundingTx", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint32", + "name": "fundingOutputIndex", + "type": "uint32" + }, + { + "internalType": "bytes8", + "name": "blindingFactor", + "type": "bytes8" + }, + { + "internalType": "bytes20", + "name": "walletPubKeyHash", + "type": "bytes20" + }, + { + "internalType": "bytes20", + "name": "refundPubKeyHash", + "type": "bytes20" + }, + { + "internalType": "bytes4", + "name": "refundLocktime", + "type": "bytes4" + }, + { + "internalType": "address", + "name": "vault", + "type": "address" + } + ], + "internalType": "struct IBridgeTypes.DepositRevealInfo", + "name": "reveal", + "type": "tuple" + }, + { + "internalType": "address", + "name": "l2DepositOwner", + "type": "address" + } + ], + "name": "initializeDeposit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "initializeDepositGasOffset", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "l2BitcoinDepositor", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "l2ChainId", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "l2FinalizeDepositGasLimit", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "l2WormholeGateway", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "quoteFinalizeDeposit", + "outputs": [ + { + "internalType": "uint256", + "name": "cost", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "reimbursementAuthorizations", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "reimbursementPool", + "outputs": [ + { + "internalType": "contract ReimbursementPool", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "tbtcToken", + "outputs": [ + { + "internalType": "contract IERC20Upgradeable", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "tbtcVault", + "outputs": [ + { + "internalType": "contract ITBTCVault", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_initializeDepositGasOffset", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_finalizeDepositGasOffset", + "type": "uint256" + } + ], + "name": "updateGasOffsetParameters", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_l2FinalizeDepositGasLimit", + "type": "uint256" + } + ], + "name": "updateL2FinalizeDepositGasLimit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_address", + "type": "address" + }, + { + "internalType": "bool", + "name": "authorization", + "type": "bool" + } + ], + "name": "updateReimbursementAuthorization", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract ReimbursementPool", + "name": "_reimbursementPool", + "type": "address" + } + ], + "name": "updateReimbursementPool", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "wormhole", + "outputs": [ + { + "internalType": "contract IWormhole", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "wormholeRelayer", + "outputs": [ + { + "internalType": "contract IWormholeRelayer", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "wormholeTokenBridge", + "outputs": [ + { + "internalType": "contract IWormholeTokenBridge", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "transactionHash": "0x2673ee5eb6ce999663c7897ab29bf0e0fda955dccc1f7d374968322d0148ade3", + "receipt": { + "to": null, + "from": "0x992500f42A48371c2c9f91EE6165ba8F9dfB1692", + "contractAddress": "0xD9B523fb879C63b00ef14e48C98f4e3398d3BA2D", + "transactionIndex": 46, + "gasUsed": "866135", + "logsBloom": "0x00000000000000000000000000000000400000000000000000800000000000000000000000000000000020000000000000000000000280000000080000000000000000000000000000000000000002000001000000000000000000000000000000000000020000000000000000000800000000800000000000000000000000400000000000000000000000000000000000000000000080000000000000800004000000000000000000000000000400000000000000000800000000000000000000000020010000000000000000040000000000000400000000000000000020000000000800000000000000000000000000000000000000000000000000000000", + "blockHash": "0x10400e7cfcdc42e3080b7580fcaa58ba8a8023b10d785a58db624c9a7fdc8b2f", + "transactionHash": "0x2673ee5eb6ce999663c7897ab29bf0e0fda955dccc1f7d374968322d0148ade3", + "logs": [ + { + "transactionIndex": 46, + "blockNumber": 6281003, + "transactionHash": "0x2673ee5eb6ce999663c7897ab29bf0e0fda955dccc1f7d374968322d0148ade3", + "address": "0xD9B523fb879C63b00ef14e48C98f4e3398d3BA2D", + "topics": [ + "0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b", + "0x000000000000000000000000f90292a39014033de50c81f651365cb6a1040bb6" + ], + "data": "0x", + "logIndex": 78, + "blockHash": "0x10400e7cfcdc42e3080b7580fcaa58ba8a8023b10d785a58db624c9a7fdc8b2f" + }, + { + "transactionIndex": 46, + "blockNumber": 6281003, + "transactionHash": "0x2673ee5eb6ce999663c7897ab29bf0e0fda955dccc1f7d374968322d0148ade3", + "address": "0xD9B523fb879C63b00ef14e48C98f4e3398d3BA2D", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000992500f42a48371c2c9f91ee6165ba8f9dfb1692" + ], + "data": "0x", + "logIndex": 79, + "blockHash": "0x10400e7cfcdc42e3080b7580fcaa58ba8a8023b10d785a58db624c9a7fdc8b2f" + }, + { + "transactionIndex": 46, + "blockNumber": 6281003, + "transactionHash": "0x2673ee5eb6ce999663c7897ab29bf0e0fda955dccc1f7d374968322d0148ade3", + "address": "0xD9B523fb879C63b00ef14e48C98f4e3398d3BA2D", + "topics": [ + "0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498" + ], + "data": "0x0000000000000000000000000000000000000000000000000000000000000001", + "logIndex": 80, + "blockHash": "0x10400e7cfcdc42e3080b7580fcaa58ba8a8023b10d785a58db624c9a7fdc8b2f" + }, + { + "transactionIndex": 46, + "blockNumber": 6281003, + "transactionHash": "0x2673ee5eb6ce999663c7897ab29bf0e0fda955dccc1f7d374968322d0148ade3", + "address": "0xD9B523fb879C63b00ef14e48C98f4e3398d3BA2D", + "topics": [ + "0x7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f" + ], + "data": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000008d58747ef805317270ff7f8e51a8018d3488b17b", + "logIndex": 81, + "blockHash": "0x10400e7cfcdc42e3080b7580fcaa58ba8a8023b10d785a58db624c9a7fdc8b2f" + } + ], + "blockNumber": 6281003, + "cumulativeGasUsed": "11146181", + "status": 1, + "byzantium": true + }, + "numDeployments": 1, + "implementation": "0xf90292a39014033DE50c81f651365cB6A1040Bb6", + "devdoc": "Contract deployed as upgradable proxy" +} diff --git a/src/threshold-ts/tbtc/sepolia-artifacts/BaseL1BitcoinDepositor.json b/src/threshold-ts/tbtc/sepolia-artifacts/BaseL1BitcoinDepositor.json new file mode 100644 index 000000000..fbd7dddff --- /dev/null +++ b/src/threshold-ts/tbtc/sepolia-artifacts/BaseL1BitcoinDepositor.json @@ -0,0 +1,681 @@ +{ + "address": "0x0c5e36731008f4AFC1AF5Da2C4D5E07eE4a3EB69", + "abi": [ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "depositKey", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "l2DepositOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "l1Sender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "initialAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tbtcAmount", + "type": "uint256" + } + ], + "name": "DepositFinalized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "depositKey", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "l2DepositOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "l1Sender", + "type": "address" + } + ], + "name": "DepositInitialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "initializeDepositGasOffset", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "finalizeDepositGasOffset", + "type": "uint256" + } + ], + "name": "GasOffsetParametersUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "l2FinalizeDepositGasLimit", + "type": "uint256" + } + ], + "name": "L2FinalizeDepositGasLimitUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "newReimbursementPool", + "type": "address" + } + ], + "name": "ReimbursementPoolUpdated", + "type": "event" + }, + { + "inputs": [], + "name": "SATOSHI_MULTIPLIER", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_l2BitcoinDepositor", + "type": "address" + } + ], + "name": "attachL2BitcoinDepositor", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "bridge", + "outputs": [ + { + "internalType": "contract IBridge", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "deposits", + "outputs": [ + { + "internalType": "enum L1BitcoinDepositor.DepositState", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "depositKey", + "type": "uint256" + } + ], + "name": "finalizeDeposit", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "finalizeDepositGasOffset", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "gasReimbursements", + "outputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "uint96", + "name": "gasSpent", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_tbtcBridge", + "type": "address" + }, + { + "internalType": "address", + "name": "_tbtcVault", + "type": "address" + }, + { + "internalType": "address", + "name": "_wormhole", + "type": "address" + }, + { + "internalType": "address", + "name": "_wormholeRelayer", + "type": "address" + }, + { + "internalType": "address", + "name": "_wormholeTokenBridge", + "type": "address" + }, + { + "internalType": "address", + "name": "_l2WormholeGateway", + "type": "address" + }, + { + "internalType": "uint16", + "name": "_l2ChainId", + "type": "uint16" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes4", + "name": "version", + "type": "bytes4" + }, + { + "internalType": "bytes", + "name": "inputVector", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "outputVector", + "type": "bytes" + }, + { + "internalType": "bytes4", + "name": "locktime", + "type": "bytes4" + } + ], + "internalType": "struct IBridgeTypes.BitcoinTxInfo", + "name": "fundingTx", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint32", + "name": "fundingOutputIndex", + "type": "uint32" + }, + { + "internalType": "bytes8", + "name": "blindingFactor", + "type": "bytes8" + }, + { + "internalType": "bytes20", + "name": "walletPubKeyHash", + "type": "bytes20" + }, + { + "internalType": "bytes20", + "name": "refundPubKeyHash", + "type": "bytes20" + }, + { + "internalType": "bytes4", + "name": "refundLocktime", + "type": "bytes4" + }, + { + "internalType": "address", + "name": "vault", + "type": "address" + } + ], + "internalType": "struct IBridgeTypes.DepositRevealInfo", + "name": "reveal", + "type": "tuple" + }, + { + "internalType": "address", + "name": "l2DepositOwner", + "type": "address" + } + ], + "name": "initializeDeposit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "initializeDepositGasOffset", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "l2BitcoinDepositor", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "l2ChainId", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "l2FinalizeDepositGasLimit", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "l2WormholeGateway", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "quoteFinalizeDeposit", + "outputs": [ + { + "internalType": "uint256", + "name": "cost", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "reimbursementPool", + "outputs": [ + { + "internalType": "contract ReimbursementPool", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "tbtcToken", + "outputs": [ + { + "internalType": "contract IERC20Upgradeable", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "tbtcVault", + "outputs": [ + { + "internalType": "contract ITBTCVault", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_initializeDepositGasOffset", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_finalizeDepositGasOffset", + "type": "uint256" + } + ], + "name": "updateGasOffsetParameters", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_l2FinalizeDepositGasLimit", + "type": "uint256" + } + ], + "name": "updateL2FinalizeDepositGasLimit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract ReimbursementPool", + "name": "_reimbursementPool", + "type": "address" + } + ], + "name": "updateReimbursementPool", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "wormhole", + "outputs": [ + { + "internalType": "contract IWormhole", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "wormholeRelayer", + "outputs": [ + { + "internalType": "contract IWormholeRelayer", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "wormholeTokenBridge", + "outputs": [ + { + "internalType": "contract IWormholeTokenBridge", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "transactionHash": "0x5a405183332f623649fcf19f8506cf2582882d5dc2b05582e0066388ef122229", + "receipt": { + "to": null, + "from": "0x68ad60CC5e8f3B7cC53beaB321cf0e6036962dBc", + "contractAddress": "0x0c5e36731008f4AFC1AF5Da2C4D5E07eE4a3EB69", + "transactionIndex": 94, + "gasUsed": "887851", + "logsBloom": "0x00000000000000000000000000000000400000000000000400800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000202000001000000000000000000000000000000000000020000000000000000000800000000800000000000000008000000400000000200000000000000000000000000000040000080000000000000800000000000000000000000000000000400000000000000000000000000000010000000000020000000000000200020040000000000000400000000000000000020000000000000000000000000000000100000000000000000000000000000000000", + "blockHash": "0x9d4a08d2b6fd26df76447aa1b5e0054686b1d462dc12be4d271dca1299060a2c", + "transactionHash": "0x5a405183332f623649fcf19f8506cf2582882d5dc2b05582e0066388ef122229", + "logs": [ + { + "transactionIndex": 94, + "blockNumber": 5441536, + "transactionHash": "0x5a405183332f623649fcf19f8506cf2582882d5dc2b05582e0066388ef122229", + "address": "0x0c5e36731008f4AFC1AF5Da2C4D5E07eE4a3EB69", + "topics": [ + "0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b", + "0x000000000000000000000000720cb49a8b3c03e199075544f7f1f4d772dd6d06" + ], + "data": "0x", + "logIndex": 75, + "blockHash": "0x9d4a08d2b6fd26df76447aa1b5e0054686b1d462dc12be4d271dca1299060a2c" + }, + { + "transactionIndex": 94, + "blockNumber": 5441536, + "transactionHash": "0x5a405183332f623649fcf19f8506cf2582882d5dc2b05582e0066388ef122229", + "address": "0x0c5e36731008f4AFC1AF5Da2C4D5E07eE4a3EB69", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x00000000000000000000000068ad60cc5e8f3b7cc53beab321cf0e6036962dbc" + ], + "data": "0x", + "logIndex": 76, + "blockHash": "0x9d4a08d2b6fd26df76447aa1b5e0054686b1d462dc12be4d271dca1299060a2c" + }, + { + "transactionIndex": 94, + "blockNumber": 5441536, + "transactionHash": "0x5a405183332f623649fcf19f8506cf2582882d5dc2b05582e0066388ef122229", + "address": "0x0c5e36731008f4AFC1AF5Da2C4D5E07eE4a3EB69", + "topics": [ + "0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498" + ], + "data": "0x0000000000000000000000000000000000000000000000000000000000000001", + "logIndex": 77, + "blockHash": "0x9d4a08d2b6fd26df76447aa1b5e0054686b1d462dc12be4d271dca1299060a2c" + }, + { + "transactionIndex": 94, + "blockNumber": 5441536, + "transactionHash": "0x5a405183332f623649fcf19f8506cf2582882d5dc2b05582e0066388ef122229", + "address": "0x0c5e36731008f4AFC1AF5Da2C4D5E07eE4a3EB69", + "topics": [ + "0x7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f" + ], + "data": "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000dd0007713cb99564b7835fd628a1718e8f9f9785", + "logIndex": 78, + "blockHash": "0x9d4a08d2b6fd26df76447aa1b5e0054686b1d462dc12be4d271dca1299060a2c" + } + ], + "blockNumber": 5441536, + "cumulativeGasUsed": "8903785", + "status": 1, + "byzantium": true + }, + "numDeployments": 1, + "implementation": "0x720Cb49A8b3c03E199075544F7f1F4d772Dd6d06", + "devdoc": "Contract deployed as upgradable proxy" +} diff --git a/src/threshold-ts/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/constants.ts b/src/threshold-ts/utils/constants.ts index 46483a3c6..bae4a9819 100644 --- a/src/threshold-ts/utils/constants.ts +++ b/src/threshold-ts/utils/constants.ts @@ -2,5 +2,7 @@ import { BigNumber, constants } from "ethers" export const MAX_UINT64 = BigNumber.from("18446744073709551615") // 2^64 - 1 export const ZERO = constants.Zero +export const L2_RELAYER_BOT_WALLET = + "0x45332EEE9b495b1dda896FD53112eaaCC10b2c19" export const STANDARD_ERC20_DECIMALS = 18 diff --git a/src/threshold-ts/utils/contract.ts b/src/threshold-ts/utils/contract.ts index 36c3b3a3e..db82d828e 100644 --- a/src/threshold-ts/utils/contract.ts +++ b/src/threshold-ts/utils/contract.ts @@ -8,8 +8,10 @@ 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 ArbitrumL1BitcoinDepositorArtifactMainnet from "../tbtc/mainnet-artifacts/ArbitrumL1BitcoinDepositor.json" import BridgeArtifactMainnet from "@keep-network/tbtc-v2.ts/src/lib/ethereum/artifacts/mainnet/Bridge.json" import NuCypherStakingEscrowMainnet from "../staking/mainnet-artifacts/NuCypherStakingEscrow.json" import NuCypherTokenMainnet from "../tokens/mainnet-artifacts/NuCypherToken.json" @@ -18,7 +20,13 @@ 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 TacoArtifactMainnet from "@nucypher/nucypher-contracts/deployment/artifacts/mainnet.json" +import ArbitrumL1BitcoinDepositorArtifactSepolia from "../tbtc/sepolia-artifacts/ArbitrumL1BitcoinDepositor.json" +import BaseL1BitcoinDepositorArtifactSepolia from "../tbtc/sepolia-artifacts/BaseL1BitcoinDepositor.json" import BridgeArtifactSepolia from "@keep-network/tbtc-v2.ts/src/lib/ethereum/artifacts/sepolia/Bridge.json" import NuCypherStakingEscrowSepolia from "../staking/sepolia-artifacts/NuCypherStakingEscrow.json" import NuCypherTokenSepolia from "../tokens/sepolia-artifacts/NuCypherToken.json" @@ -27,6 +35,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 TacoArtifactSepolia from "@nucypher/nucypher-contracts/deployment/artifacts/tapir.json" import BridgeArtifactDappDevelopmentSepolia from "../tbtc/dapp-development-sepolia-artifacts/Bridge.json" import NuCypherStakingEscrowDappDevelopmentSepolia from "../staking/dapp-development-sepolia-artifacts/NuCypherStakingEscrow.json" @@ -36,8 +48,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 TacoArtifactDappDevelopmentSepolia from "@nucypher/nucypher-contracts/deployment/artifacts/dashboard.json" -type ArtifactNameType = +export type ArtifactNameType = + | "TacoRegistry" + | "LegacyKeepStaking" + | "RandomBeacon" + | "TokenStaking" | "Bridge" | "NuCypherStakingEscrow" | "NuCypherToken" @@ -46,42 +66,68 @@ type ArtifactNameType = | "VendingMachineKeep" | "VendingMachineNuCypher" | "WalletRegistry" + | "ArbitrumL1BitcoinDepositor" + | "BaseL1BitcoinDepositor" type ArtifactType = { address: string abi: ContractInterface [key: string]: any } +type ContractArtifacts = { + [chainId in SupportedChainIds]?: { + [artifactName in ArtifactNameType]?: ArtifactType + } +} -const mainnetArtifacts = new Map([ - ["Bridge", BridgeArtifactMainnet], - ["NuCypherStakingEscrow", NuCypherStakingEscrowMainnet], - ["NuCypherToken", NuCypherTokenMainnet], - ["TBTCVault", TbtcVaultArtifactMainnet], - ["TBTC", TbtcTokenArtifactMainnet], - ["WalletRegistry", WalletRegistryArtifactMainnet], - ["VendingMachineKeep", VendingMachineKeepMainnet], - ["VendingMachineNuCypher", VendingMachineNuCypherMainnet], -]) -const testnetArtifacts = new Map([ - ["Bridge", BridgeArtifactSepolia], - ["NuCypherStakingEscrow", NuCypherStakingEscrowSepolia], - ["NuCypherToken", NuCypherTokenSepolia], - ["TBTCVault", TbtcVaultArtifactSepolia], - ["TBTC", TbtcTokenArtifactSepolia], - ["WalletRegistry", WalletRegistryArtifactSepolia], - ["VendingMachineKeep", VendingMachineKeepSepolia], - ["VendingMachineNuCypher", VendingMachineNuCypherSepolia], -]) -const testnetDevelopmentArtifacts = new Map([ - ["Bridge", BridgeArtifactDappDevelopmentSepolia], - ["NuCypherStakingEscrow", NuCypherStakingEscrowDappDevelopmentSepolia], - ["NuCypherToken", NuCypherTokenDappDevelopmentSepolia], - ["TBTCVault", TbtcVaultArtifactDappDevelopmentSepolia], - ["TBTC", TbtcTokenArtifactDappDevelopmentSepolia], - ["WalletRegistry", WalletRegistryArtifactDappDevelopmentSepolia], - ["VendingMachineKeep", VendingMachineKeepDappDevelopmentSepolia], - ["VendingMachineNuCypher", VendingMachineNuCypherDappDevelopmentSepolia], -]) +const contractArtifacts: ContractArtifacts = { + [SupportedChainIds.Ethereum]: { + ArbitrumL1BitcoinDepositor: ArbitrumL1BitcoinDepositorArtifactMainnet, + TacoRegistry: + TacoArtifactMainnet[SupportedChainIds.Ethereum].TACoApplication, + 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: + TacoArtifactSepolia[SupportedChainIds.Sepolia].TACoApplication, + RandomBeacon: RandomBeaconArtifactSepolia, + TokenStaking: StakingArtifactSepolia, + Bridge: BridgeArtifactSepolia, + NuCypherStakingEscrow: NuCypherStakingEscrowSepolia, + NuCypherToken: NuCypherTokenSepolia, + TBTCVault: TbtcVaultArtifactSepolia, + TBTC: TbtcTokenArtifactSepolia, + WalletRegistry: WalletRegistryArtifactSepolia, + VendingMachineKeep: VendingMachineKeepSepolia, + VendingMachineNuCypher: VendingMachineNuCypherSepolia, + }, + [SupportedChainIds.Localhost]: { + TacoRegistry: + TacoArtifactSepolia[SupportedChainIds.Sepolia].TACoApplication, + 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( @@ -111,7 +157,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) @@ -152,22 +198,18 @@ export function getContractAddressFromTruffleArtifact( export const getArtifact = ( artifactName: ArtifactNameType, - chainId: string | number, - shouldUseTestnetDevelopmentContracts = false -): ArtifactType => { - switch (chainId.toString()) { - case "1": - // Ethereum mainnet. - return mainnetArtifacts.get(artifactName)! - case "11155111": - // Ethereum Sepolia testnet. - const artifacts = shouldUseTestnetDevelopmentContracts - ? testnetDevelopmentArtifacts - : testnetArtifacts - return artifacts.get(artifactName)! - default: - throw new Error("Can't get tbtc-v2 artifacts!") + 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 3729e46dc..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! @@ -106,7 +111,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/types/tbtc.ts b/src/types/tbtc.ts index 799dd9c48..3e0c04257 100644 --- a/src/types/tbtc.ts +++ b/src/types/tbtc.ts @@ -2,10 +2,12 @@ import { BitcoinUtxo } from "@keep-network/tbtc-v2.ts" import { FetchingState } from "." import { BridgeActivity, BridgeProcess } from "../threshold-ts/tbtc" import { UpdateStateActionPayload } from "./state" +import { NetworkName } from "../networks/types/networks" export interface TbtcState { mintingStep: MintingStep // deposit data + depositor: string btcRecoveryAddress: string btcDepositAddress: string ethAddress: string @@ -20,7 +22,10 @@ export interface TbtcState { optimisticMintingFinalizedTxHash?: string tBTCMintAmount: string thresholdNetworkFee: string + crossChainFee: string mintingFee: string + chainName: NetworkName + extraData?: string bridgeActivity: FetchingState } 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/getBitcoinCredentials.ts b/src/utils/getBitcoinCredentials.ts new file mode 100644 index 000000000..57e424827 --- /dev/null +++ b/src/utils/getBitcoinCredentials.ts @@ -0,0 +1,29 @@ +import { BitcoinNetwork } from "@keep-network/tbtc-v2.ts" +import { BitcoinClientCredentials } from "../threshold-ts/types" +import { EnvVariable } from "../enums" +import { getEnvVariable } from "./getEnvVariable" + +export const getBitcoinCredentials = (bitcoinNetwork: BitcoinNetwork) => { + const credentials: BitcoinClientCredentials[] = + bitcoinNetwork === BitcoinNetwork.Mainnet + ? [ + { + host: getEnvVariable(EnvVariable.MAINNET_ELECTRUM_HOST), + port: +getEnvVariable(EnvVariable.MAINNET_ELECTRUM_PORT), + protocol: getEnvVariable( + EnvVariable.MAINNET_ELECTRUM_PROTOCOL + ) as BitcoinClientCredentials["protocol"], + }, + ] + : [ + { + host: getEnvVariable(EnvVariable.TESTNET_ELECTRUM_HOST), + port: +getEnvVariable(EnvVariable.TESTNET_ELECTRUM_PORT), + protocol: getEnvVariable( + EnvVariable.TESTNET_ELECTRUM_PROTOCOL + ) as BitcoinClientCredentials["protocol"], + }, + ] + + return credentials +} diff --git a/src/utils/getEnvVariable.ts b/src/utils/getEnvVariable.ts index 4b8943cc2..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 } @@ -13,7 +14,12 @@ export const getEnvVariable = (envVar: EnvVariableKey) => { return envMap[envVar] } -export const supportedChainId = getEnvVariable(EnvVariable.SUPPORTED_CHAIN_ID) +export const getDefaultProviderChainId = () => { + const chainId = + getEnvVariable(EnvVariable.DEFAULT_PROVIDER_CHAIN_ID) || + SupportedChainIds.Ethereum + return Number(chainId) +} export const shouldUseTestnetDevelopmentContracts = getEnvVariable(EnvVariable.DAPP_DEVELOPMENT_TESTNET_CONTRACTS) === "true" 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/getStakingAppLabel.ts b/src/utils/getStakingAppLabel.ts index ec57b3c67..3c592fcd1 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,32 @@ 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 threshold = useThreshold() + + if ( + !threshold.multiAppStaking.ecdsa || + !threshold.multiAppStaking.randomBeacon || + !threshold.multiAppStaking.taco + ) { + return null + } + + const stakingAppAddressToAppName: Record = { + [threshold.multiAppStaking.ecdsa.address]: "tbtc", + [threshold.multiAppStaking.randomBeacon.address]: "randomBeacon", + [threshold.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/getThresholdLib.ts b/src/utils/getThresholdLib.ts index c49153e7a..5ecf1bc1b 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,47 +19,50 @@ import { BitcoinClientCredentials, EthereumConfig, } from "../threshold-ts/types" +import { SupportedChainIds } from "../networks/enums/networks" +import { getBitcoinCredentials } from "./getBitcoinCredentials" + +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 bitcoinNetwork = isTestnetNetwork(defaultProviderChainId) + ? BitcoinNetwork.Testnet + : BitcoinNetwork.Mainnet const shouldMockBitcoinClient = getEnvVariable(EnvVariable.MOCK_BITCOIN_CLIENT) === "true" - const credentials: BitcoinClientCredentials[] = [ - { - host: getEnvVariable(EnvVariable.ELECTRUM_HOST), - port: +getEnvVariable(EnvVariable.ELECTRUM_PORT), - protocol: getEnvVariable( - EnvVariable.ELECTRUM_PROTOCOL - ) as BitcoinClientCredentials["protocol"], - }, - ] + const credentials: BitcoinClientCredentials[] = + getBitcoinCredentials(bitcoinNetwork) return { client: shouldMockBitcoinClient ? new MockBitcoinClient() : undefined, - network, + network: bitcoinNetwork, credentials: !shouldMockBitcoinClient ? credentials : undefined, } } -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 +72,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/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 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/utils/percentage.ts b/src/utils/percentage.ts index 13171725f..803963c86 100644 --- a/src/utils/percentage.ts +++ b/src/utils/percentage.ts @@ -24,6 +24,7 @@ export const formatPercentage = ( displayLessThanGreaterThanSigns = false, displaySign = true ): string => { + if (!(typeof percentage === "number")) return "" if (percentage < 1 && percentage > 0 && displayLessThanGreaterThanSigns) { return `<1${displaySign ? "%" : ""}` } else if ( diff --git a/src/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 diff --git a/src/utils/tBTC.ts b/src/utils/tBTC.ts index 78b3eea80..6e7aae583 100644 --- a/src/utils/tBTC.ts +++ b/src/utils/tBTC.ts @@ -7,11 +7,15 @@ import { } from "../threshold-ts/utils" import { BigNumberish, BigNumber } from "ethers" -const MINTING_MAINNET_BTC_RECOVERY_ADDRESS_PREFIXES = ["1", "bc1"] as const -const MINTING_TESTNET_BTC_RECOVERY_ADDRESS_PREFIXES = ["m", "n", "tb1"] as const - -const UNMINTING_MAINNET_BTC_ADDRESS_PREFIXES = ["1", "bc1", "3"] as const -const UNMINTING_TESTNET_BTC_ADDRESS_PREFIXES = ["m", "n", "tb1", "2"] as const +const MINTING_MAINNET_BTC_RECOVERY_ADDRESS_PREFIXES = ["1", "bc1q"] as const +const MINTING_TESTNET_BTC_RECOVERY_ADDRESS_PREFIXES = [ + "m", + "n", + "tb1q", +] as const + +const UNMINTING_MAINNET_BTC_ADDRESS_PREFIXES = ["1", "bc1q", "3"] as const +const UNMINTING_TESTNET_BTC_ADDRESS_PREFIXES = ["m", "n", "tb1q", "2"] as const type SupportedBitcoinNetworks = Exclude diff --git a/src/utils/tbtcLocalStorageData.ts b/src/utils/tbtcLocalStorageData.ts index b3742ff14..3b98e65de 100644 --- a/src/utils/tbtcLocalStorageData.ts +++ b/src/utils/tbtcLocalStorageData.ts @@ -1,12 +1,19 @@ import { writeStorage } from "@rehooks/local-storage" +export type Depositor = { + identifierHex: string +} + export type TBTCDepositData = { + depositor: Depositor + chainName: string ethAddress: string blindingFactor: string btcRecoveryAddress: string walletPublicKeyHash: string refundLocktime: string btcDepositAddress: string + extraData?: string } export type TBTCLocalStorageDepositData = { @@ -18,7 +25,8 @@ export const key = "tBTCDepositData" export function write( account: string, newDepositData: TBTCDepositData, - prevData: TBTCLocalStorageDepositData + prevData: TBTCLocalStorageDepositData, + chainId?: number | string ) { if (!account) return @@ -27,17 +35,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 + ) } 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/connectors/coinbaseWallet.ts b/src/web3/connectors/coinbaseWallet.ts index 1ec6838be..dcd785c29 100644 --- a/src/web3/connectors/coinbaseWallet.ts +++ b/src/web3/connectors/coinbaseWallet.ts @@ -1,17 +1,19 @@ 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, + hexToNumber, + 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 +22,9 @@ export class CoinbaseWalletConnector extends WalletLinkConnector { (p) => p.isCoinbaseWallet ) ?? (window.ethereum as CoinbaseWalletProvider) + const chainIdHex = provider.chainId || (await this.getChainId()) + const chainId = hexToNumber(chainIdHex) + if (provider.isCoinbaseWallet) { // Force the Coinbase Wallet provider to use our RPC url. We can't fetch // past events from block range greater than `1000` when using the default @@ -30,7 +35,7 @@ export class CoinbaseWalletConnector extends WalletLinkConnector { // only enforced during type checking. This means that JavaScript runtime // constructs like `in` or simple property lookup can still access a // `private` or `protected` member. - provider.updateProviderInfo(rpcUrl, +supportedChainId, true) + provider.updateProviderInfo(getRpcUrl(chainId), chainId, true) } return await super.activate() @@ -38,7 +43,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/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/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, }) 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) }) diff --git a/src/web3/hooks/useCheckDuplicateProviderAddress.ts b/src/web3/hooks/useCheckDuplicateProviderAddress.ts index fa79883c7..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 @@ -17,31 +18,54 @@ 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 (!multicall) { + return { + isProviderUsedForKeep: false, + isProviderUsedForT: false, + } } - const [{ owner }, [, createdAt]] = await threshold.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 isProviderUsedForKeep = createdAt.gt(BigNumber.from(0)) - const isProviderUsedForT = !isAddressZero(owner) + const tRolesResult = results[0] || {} + const owner = tRolesResult?.owner || AddressZero - return { isProviderUsedForKeep, isProviderUsedForT } + const keepDelegationResult = results[1] || {} + const createdAt = keepDelegationResult?.createdAt || BigNumber.from(0) + + const isProviderUsedForKeep = + BigNumber.isBigNumber(createdAt) && createdAt.gt(0) + const isProviderUsedForT = !isAddressZero(owner) + + return { isProviderUsedForKeep, isProviderUsedForT } + } catch (error) { + console.error("Multicall failed:", error) + return { + isProviderUsedForKeep: false, + isProviderUsedForT: false, + } + } }, [tStakingContract, keepStakingContract, threshold] ) 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/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( diff --git a/src/web3/hooks/useKeep.ts b/src/web3/hooks/useKeep.ts index 91d093981..05859e91a 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 { useConnectedOrDefaultChainId } from "../../networks/hooks/useConnectedOrDefaultChainId" + +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 = useConnectedOrDefaultChainId() + 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..ef0c5bfce 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 { useConnectedOrDefaultChainId } from "../../networks/hooks/useConnectedOrDefaultChainId" + +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 = useConnectedOrDefaultChainId() + 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..7cd0b1b54 100644 --- a/src/web3/hooks/useKeepTokenStakingContract.ts +++ b/src/web3/hooks/useKeepTokenStakingContract.ts @@ -1,10 +1,20 @@ 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 { useConnectedOrDefaultChainId } from "../../networks/hooks/useConnectedOrDefaultChainId" -const KEEP_TOKEN_STAKING_ADDRESS = - getContractAddressFromTruffleArtifact(KeepTokenStaking) +const KEEP_STAKING_ADDRESSES = { + // https://etherscan.io/address/0x1293a54e160D1cd7075487898d65266081A15458 + [SupportedChainIds.Ethereum]: "0x1293a54e160D1cd7075487898d65266081A15458", + [SupportedChainIds.Localhost]: AddressZero, +} as Record export const useKeepTokenStakingContract = () => { - return useContract(KEEP_TOKEN_STAKING_ADDRESS, KeepTokenStaking.abi) + const defaultOrConnectedChainId = useConnectedOrDefaultChainId() + + 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..d08c594e6 100644 --- a/src/web3/hooks/useMerkleDropContract.ts +++ b/src/web3/hooks/useMerkleDropContract.ts @@ -1,25 +1,31 @@ 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 { useWeb3React } from "@web3-react/core" -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 = (chainId?: string | number) => { + return DEPLOYMENT_BLOCKS[Number(chainId)] || 0 +} export const useMerkleDropContract = () => { + const { chainId } = useWeb3React() return useContract( - CONTRACT_ADDRESSESS[supportedChainId], + MERKLE_DROP_ADDRESSES[Number(chainId)], 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..f383768c9 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 { useConnectedOrDefaultChainId } from "../../networks/hooks/useConnectedOrDefaultChainId" 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 = useConnectedOrDefaultChainId() + 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..7927e184e 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 { getMainnetOrTestnetChainId } from "../../networks/utils" +import { SupportedChainIds } from "../../networks/enums/networks" export interface UseNu { (): { approveNu: () => void @@ -22,10 +16,19 @@ export interface UseNu { } export const useNu: UseNu = () => { + const { chainId } = useIsActive() + const supportedChainId = getMainnetOrTestnetChainId(chainId) + + const nuCupherTokenArtifact = getArtifact( + "NuCypherToken", + supportedChainId, + shouldUseTestnetDevelopmentContracts + ) + const { balanceOf, approve, contract } = useErc20TokenContract( - nuCupherTokenArtifact.address, + nuCupherTokenArtifact?.address!, undefined, - nuCupherTokenArtifact.abi + nuCupherTokenArtifact?.abi! ) const approveNu = () => { 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/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 } diff --git a/src/web3/hooks/useT.ts b/src/web3/hooks/useT.ts index 68907448d..96981d84d 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 { useConnectedOrDefaultChainId } from "../../networks/hooks/useConnectedOrDefaultChainId" + +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 = useConnectedOrDefaultChainId() 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..7a91e0cd7 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 { useConnectedOrDefaultChainId } from "../../networks/hooks/useConnectedOrDefaultChainId" + +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 = useConnectedOrDefaultChainId() + return useErc20TokenContract( + TBTC_ADDRESSES[Number(defaultOrConnectedChainId)] + ) } diff --git a/src/web3/hooks/useTBTCv2TokenContract.ts b/src/web3/hooks/useTBTCv2TokenContract.ts index dfe429ab0..91e20a7b2 100644 --- a/src/web3/hooks/useTBTCv2TokenContract.ts +++ b/src/web3/hooks/useTBTCv2TokenContract.ts @@ -1,6 +1,27 @@ -import { useThreshold } from "../../contexts/ThresholdContext" +import { useErc20TokenContract } from "./useERC20" +import { AddressZero } from "@ethersproject/constants" +import { SupportedChainIds } from "../../networks/enums/networks" +import { useConnectedOrDefaultChainId } from "../../networks/hooks/useConnectedOrDefaultChainId" +export const TBTCV2_ADDRESSES = { + // https://etherscan.io/address/0x18084fbA666a33d37592fA2633fD49a74DD93a88 + [SupportedChainIds.Ethereum]: "0x18084fbA666a33d37592fA2633fD49a74DD93a88", + // https://sepolia.etherscan.io/address/0x517f2982701695D4E52f1ECFBEf3ba31Df470161 + [SupportedChainIds.Sepolia]: "0x517f2982701695D4E52f1ECFBEf3ba31Df470161", + [SupportedChainIds.ArbitrumSepolia]: + "0xb8f31A249bcb45267d06b9E51252c4793B917Cd0", + [SupportedChainIds.Arbitrum]: "0x6c84a8f1c29108F47a79964b5Fe888D4f4D0dE40", + [SupportedChainIds.Base]: "0x236aa50979D5f3De3Bd1Eeb40E81137F22ab794b", + [SupportedChainIds.BaseSepolia]: "0xb8f31A249bcb45267d06b9E51252c4793B917Cd0", + [SupportedChainIds.Localhost]: AddressZero, +} as Record + +// 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 = useConnectedOrDefaultChainId() + return useErc20TokenContract( + TBTCV2_ADDRESSES[Number(defaultOrConnectedChainId)] + ) } diff --git a/src/web3/hooks/useTStakingContract.ts b/src/web3/hooks/useTStakingContract.ts index 07869937a..82340222a 100644 --- a/src/web3/hooks/useTStakingContract.ts +++ b/src/web3/hooks/useTStakingContract.ts @@ -1,10 +1,28 @@ -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 { useWeb3React } from "@web3-react/core" -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 = (chainId?: number | string) => { + return DEPLOYMENT_BLOCKS[Number(chainId)] || 0 +} export const useTStakingContract = () => { - return useContract(TStakingContract.address, TStakingContract.abi) + const { chainId } = useWeb3React() + return useContract(T_STAKING_ADDRESSES[Number(chainId)], 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" diff --git a/src/web3/utils/network.ts b/src/web3/utils/network.ts deleted file mode 100644 index bccf6f080..000000000 --- a/src/web3/utils/network.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { ethers } from "ethers" - -export const toHex = (value: string | number): string => - ethers.utils.hexlify(value) - -export const isSameChainId = ( - chainId1: string | number, - chainId2: string | number -): boolean => toHex(chainId1) === toHex(chainId2) diff --git a/yarn.lock b/yarn.lock index fb9c7583d..a4bb5bd31 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3299,33 +3299,16 @@ resolved "https://registry.yarnpkg.com/@keep-network/bitcoin-spv-sol/-/bitcoin-spv-sol-3.4.0-solc-0.8.tgz#8b44c246ffab8ea993efe196f6bf385b1a3b84dc" integrity sha512-KlpY9BbasyLvYXSS7dsJktgRChu/yjdFLOX8ldGA/pltLicCm/l0F4oqxL8wSws9XD12vq9x0B5qzPygVLB2TQ== -"@keep-network/ecdsa@2.0.1": - version "2.0.1" - resolved "https://registry.yarnpkg.com/@keep-network/ecdsa/-/ecdsa-2.0.1.tgz#f9de5e4ae68c48493b8a46d1d956c8bc157b1145" - integrity sha512-51Ef0FGak9dzuTF4e80ed1G2+3v+kQYPieYa3hX7eKg3XG0/C/xOtMSpIOxU7IMdYBHeeH+hRIqDiL5AuOidOg== +"@keep-network/ecdsa@2.1.0-dev.19": + version "2.1.0-dev.19" + resolved "https://registry.yarnpkg.com/@keep-network/ecdsa/-/ecdsa-2.1.0-dev.19.tgz#749af8bd65f70135d1734f7c5f9bff82ae308fdb" + integrity sha512-cyqRqK/sOqyaXZWY/O9ij6EINQuJ+bHLMiuufOFyP5YCj4GCuNqOcCytGAZPT+mED/0J/xn0vm+fgiCBq/uJkQ== dependencies: - "@keep-network/random-beacon" "2.0.0" - "@keep-network/sortition-pools" "2.0.0" + "@keep-network/random-beacon" "2.1.0-dev.18" + "@keep-network/sortition-pools" "^2.0.0-pre.16" "@openzeppelin/contracts" "^4.6.0" "@openzeppelin/contracts-upgradeable" "^4.6.0" - "@threshold-network/solidity-contracts" "1.2.1" - -"@keep-network/keep-core@1.3.0": - version "1.3.0" - resolved "https://registry.yarnpkg.com/@keep-network/keep-core/-/keep-core-1.3.0.tgz#09c1fd4d8d021b2afdff4801c7743d4c65b7bce3" - integrity sha512-c8efKWPx5da6OSdcm9/uvdDqrfwDcYAExNqPvomhLFC0dATEEFHsr/QOAqiBm4wCZZtWMKt0dYTm5QpGtx5TXQ== - dependencies: - "@openzeppelin/contracts-ethereum-package" "^2.4.0" - "@openzeppelin/upgrades" "^2.7.2" - openzeppelin-solidity "2.4.0" - -"@keep-network/keep-core@1.7.0": - version "1.7.0" - resolved "https://registry.yarnpkg.com/@keep-network/keep-core/-/keep-core-1.7.0.tgz#0923d539fc431810bd9b239f91e09a92a2b255a0" - integrity sha512-jU0ol4L5a7vFUXCTlYGsjZYhl87cUpiAYz9LgDgvM3sGmwNIVZ9dY3gziINXIbSSFZjoqh3eGDxDPcQmA+Rjrg== - dependencies: - "@openzeppelin/upgrades" "^2.7.2" - openzeppelin-solidity "2.4.0" + "@threshold-network/solidity-contracts" "1.3.0-dev.12" "@keep-network/keep-core@1.8.0-dev.5": version "1.8.0-dev.5" @@ -3351,16 +3334,6 @@ "@openzeppelin/upgrades" "^2.7.2" openzeppelin-solidity "2.4.0" -"@keep-network/keep-ecdsa@1.2.1": - version "1.2.1" - resolved "https://registry.yarnpkg.com/@keep-network/keep-ecdsa/-/keep-ecdsa-1.2.1.tgz#5dcbc2c3808cce55a6e0d9e524868a0e9a0f1562" - integrity sha512-Oz0thgLoemt/nK6dl+MONU7TEoNR3lfbnMY/Aa0oWGcwR5PlNMiBVzYY7OT4oLZIK/MxEHDOWRQAijZEQffI7g== - dependencies: - "@keep-network/keep-core" "1.3.0" - "@keep-network/sortition-pools" "1.1.2" - "@openzeppelin/upgrades" "^2.7.2" - openzeppelin-solidity "2.3.0" - "@keep-network/keep-ecdsa@>1.9.0-dev <1.9.0-ropsten": version "1.9.0-goerli.0" resolved "https://registry.yarnpkg.com/@keep-network/keep-ecdsa/-/keep-ecdsa-1.9.0-goerli.0.tgz#ce58b6639062bb4f73a257557aebb16447889e08" @@ -3389,15 +3362,15 @@ version "0.0.1" resolved "https://codeload.github.com/keep-network/prettier-config-keep/tar.gz/d6ec02e80dd76edfba073ca58ef99aee39002c2c" -"@keep-network/random-beacon@2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@keep-network/random-beacon/-/random-beacon-2.0.0.tgz#ac52dd03da49ec5b0d39ba85c51de6c4c8f1b1dc" - integrity sha512-c5AodlBkMRTEID7bDE7BA9lqDZcH3AFqOPz5b9f5syy62DnuiMkHTHIEIvdWWCL26m21A4PPyPjw7XirauE/OA== +"@keep-network/random-beacon@2.1.0-dev.18": + version "2.1.0-dev.18" + resolved "https://registry.yarnpkg.com/@keep-network/random-beacon/-/random-beacon-2.1.0-dev.18.tgz#2647731eea35f931afb565988cc8d8cf6a34f6b7" + integrity sha512-UrVq///+jqOLQ5k8/aFvD1ZUMvVe49iS81U8mDoi9A005FiQzKUK9QFKv3Z0h6joG4prF/hlABRTEQ1UA7tgRA== dependencies: - "@keep-network/sortition-pools" "2.0.0" - "@openzeppelin/contracts" "^4.6.0" + "@keep-network/sortition-pools" "^2.0.0-pre.16" + "@openzeppelin/contracts" "4.7.3" "@thesis/solidity-contracts" "github:thesis/solidity-contracts#4985bcf" - "@threshold-network/solidity-contracts" "1.2.1" + "@threshold-network/solidity-contracts" "1.3.0-dev.11" "@keep-network/random-beacon@development": version "2.1.0-dev.10" @@ -3409,13 +3382,6 @@ "@thesis/solidity-contracts" "github:thesis/solidity-contracts#4985bcf" "@threshold-network/solidity-contracts" "1.3.0-dev.5" -"@keep-network/sortition-pools@1.1.2": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@keep-network/sortition-pools/-/sortition-pools-1.1.2.tgz#cfeb31d574b02d1ae32649df01b87af07229010a" - integrity sha512-bBaKyxkXDc8kJHq3qeESMrJ02m+Wbh6Uz9qUpWn8Zq3aTZaKXRZfGWT+J71OiBlAdyB4WoHZymrddWHkjImHdQ== - dependencies: - "@openzeppelin/contracts" "^2.4.0" - "@keep-network/sortition-pools@1.2.0-dev.1": version "1.2.0-dev.1" resolved "https://registry.yarnpkg.com/@keep-network/sortition-pools/-/sortition-pools-1.2.0-dev.1.tgz#2ee371f1dd1ff71f6d05c9ddc2a83a4a93ff56b3" @@ -3423,7 +3389,7 @@ dependencies: "@openzeppelin/contracts" "^2.4.0" -"@keep-network/sortition-pools@2.0.0", "@keep-network/sortition-pools@^2.0.0-pre.16": +"@keep-network/sortition-pools@^2.0.0-pre.16": version "2.0.0" resolved "https://registry.yarnpkg.com/@keep-network/sortition-pools/-/sortition-pools-2.0.0.tgz#04e29ec756d74e00d13505a3e2a7763b06d7a08d" integrity sha512-82pDOKcDBvHBFblCt0ALVr6qC6mxk339ZqnCfYx1zIPaPhzkw1RKOv28AqPoqzhzcdqLIoPh8g9RS/M2Lplh1A== @@ -3431,15 +3397,14 @@ "@openzeppelin/contracts" "^4.3.2" "@thesis/solidity-contracts" "github:thesis/solidity-contracts#4985bcf" -"@keep-network/tbtc-v2.ts@^2.4.1": - version "2.4.1" - resolved "https://registry.yarnpkg.com/@keep-network/tbtc-v2.ts/-/tbtc-v2.ts-2.4.1.tgz#177046b32859fe5ad429f52c081e3cac994d3700" - integrity sha512-8MPrL4dr0HPDVphhxzfT+ApLqmWNTHJWCd16NFMYjT95Xu1nWuK3v3L6AU7mDb98X1XFT2Qc2OKh4JrtVmVVQw== +"@keep-network/tbtc-v2.ts@^2.5.0-dev.8": + version "2.5.0-dev.8" + resolved "https://registry.yarnpkg.com/@keep-network/tbtc-v2.ts/-/tbtc-v2.ts-2.5.0-dev.8.tgz#6ff1f222652891beb125087412df12d05b74eecd" + integrity sha512-P/a1TlljPhJUYXuaV75Ck0EINpT96N1cyOMUQc3Bu8mGnUy6CKzRtvDTmYJFRV1W6bHBVgBaI0O09mZADulm8A== dependencies: "@bitcoinerlab/secp256k1" "^1.0.5" - "@keep-network/ecdsa" "2.0.1" - "@keep-network/tbtc-v2" "1.6.0" - "@ledgerhq/wallet-api-client" "^1.2.1" + "@keep-network/ecdsa" "2.1.0-dev.19" + "@keep-network/tbtc-v2" "1.7.0-dev.4" bignumber.js "^9.1.2" bitcoinjs-lib "^6.1.5" bufio "^1.0.6" @@ -3450,30 +3415,20 @@ url-parse "^1.5.10" wif "2.0.6" -"@keep-network/tbtc-v2@1.6.0": - version "1.6.0" - resolved "https://registry.yarnpkg.com/@keep-network/tbtc-v2/-/tbtc-v2-1.6.0.tgz#06ed337d87bfd6d2d027aca461dbdd985207cc41" - integrity sha512-g+bZ1AHQTbNf3Mfze+PpexN7BO2WHHP8emZYo6VKOZi2amqqDjlY3yRKePa42cbNJXIdHcCwLgyLG+2G6WrZiA== +"@keep-network/tbtc-v2@1.7.0-dev.4": + version "1.7.0-dev.4" + resolved "https://registry.yarnpkg.com/@keep-network/tbtc-v2/-/tbtc-v2-1.7.0-dev.4.tgz#fafbd3c7ccc8c68dbdb3e9c684b7f106b42a5a78" + integrity sha512-+DxR5XebK0DB5WIrQyCQG2osixBYpJhOuwQtLu3EDMsi4tFAPEh5MFjWG5LYeuEtX65p19mSC4Vj69/Z3jMgrA== dependencies: "@keep-network/bitcoin-spv-sol" "3.4.0-solc-0.8" - "@keep-network/ecdsa" "2.0.1" - "@keep-network/random-beacon" "2.0.0" - "@keep-network/tbtc" "1.1.0" + "@keep-network/ecdsa" "2.1.0-dev.19" + "@keep-network/random-beacon" "2.1.0-dev.18" + "@keep-network/tbtc" "1.1.2-dev.1" "@openzeppelin/contracts" "^4.8.1" "@openzeppelin/contracts-upgradeable" "^4.8.1" "@thesis/solidity-contracts" "github:thesis/solidity-contracts#4985bcf" -"@keep-network/tbtc@1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@keep-network/tbtc/-/tbtc-1.1.0.tgz#9574ff355af04e77fb73a7bbe3e74cfd8764cf3c" - integrity sha512-V4sGR/t61PgkEF11GDZL5QNijVSdDhL7A7larcOSSCmKJOugxd5s+d+NdhYcHZhX9IS58ebtepvZan8TydHUHw== - dependencies: - "@keep-network/keep-ecdsa" "1.2.1" - "@summa-tx/bitcoin-spv-sol" "^3.1.0" - "@summa-tx/relay-sol" "^2.0.2" - openzeppelin-solidity "2.3.0" - -"@keep-network/tbtc@development": +"@keep-network/tbtc@1.1.2-dev.1", "@keep-network/tbtc@development": version "1.1.2-dev.1" resolved "https://registry.yarnpkg.com/@keep-network/tbtc/-/tbtc-1.1.2-dev.1.tgz#dd1e734c0fed50474c74d7170c8749127231d1f9" integrity sha512-IRa0j1D7JBG8UpduaFxkaq2Ii6F61HhNMUBmxr7kAIZwj/yx8sYXWi921mn0L2Z+hAYNcwEUVhCM91VKQH29pQ== @@ -3574,7 +3529,7 @@ dependencies: "@ledgerhq/wallet-api-client" "1.2.1" -"@ledgerhq/wallet-api-client@1.2.1", "@ledgerhq/wallet-api-client@^1.2.0", "@ledgerhq/wallet-api-client@^1.2.1": +"@ledgerhq/wallet-api-client@1.2.1", "@ledgerhq/wallet-api-client@^1.2.0": version "1.2.1" resolved "https://registry.yarnpkg.com/@ledgerhq/wallet-api-client/-/wallet-api-client-1.2.1.tgz#b47fe5b4f431282f50ddb64c8abb911545593eba" integrity sha512-uTBTZCpbLTM5y5Cd7ioQB0lcq0b3cbrU2bGzCiKuY1IEd0NUyFhr2dKliRrcLoMPDRtQRmRnSxeX0BFKinoo8Q== @@ -3726,15 +3681,10 @@ mkdirp "^1.0.4" rimraf "^3.0.2" -"@nucypher/nucypher-contracts@0.13.0": - version "0.13.0" - resolved "https://registry.yarnpkg.com/@nucypher/nucypher-contracts/-/nucypher-contracts-0.13.0.tgz#43ead85d4cdf7eb6b459ba77a6ff90a8bb796300" - integrity sha512-QB9vCVq2mLR2SeA/gSX8Px2QW3wcc9keQuTwgtDOA5J7PLoxDHEAko4ow6ZlsfjsbK572Xz6YReH09MBr71ujA== - -"@openzeppelin/contracts-ethereum-package@^2.4.0": - version "2.5.0" - resolved "https://registry.yarnpkg.com/@openzeppelin/contracts-ethereum-package/-/contracts-ethereum-package-2.5.0.tgz#cfb4b91f8132edde7e04bcd032575d4c6b544f4a" - integrity sha512-14CijdTyy4Y/3D3UUeFC2oW12nt1Yq1M8gFOtkuODEvSYPe3YSAKnKyhUeGf0UDNCZzwfGr15KdiFK6AoJjoSQ== +"@nucypher/nucypher-contracts@0.23.0": + version "0.23.0" + resolved "https://registry.yarnpkg.com/@nucypher/nucypher-contracts/-/nucypher-contracts-0.23.0.tgz#beebaea7665e822949238fff4e712d29bbf64493" + integrity sha512-vilcgICbFzSP2x5otEJHzmaKsbX4t6DIU8aj4U33taTeCdR62LDFS6tCG1r+XzgSmIJZO8ksO5bGzaEHF+r1Ww== "@openzeppelin/contracts-upgradeable@^4.6.0", "@openzeppelin/contracts-upgradeable@^4.8.1": version "4.9.1" @@ -3746,6 +3696,11 @@ resolved "https://registry.yarnpkg.com/@openzeppelin/contracts-upgradeable/-/contracts-upgradeable-4.5.2.tgz#90d9e47bacfd8693bfad0ac8a394645575528d05" integrity sha512-xgWZYaPlrEOQo3cBj97Ufiuv79SPd8Brh4GcFYhPgb6WvAq4ppz8dWKL6h+jLAK01rUqMRp/TS9AdXgAeNvCLA== +"@openzeppelin/contracts@4.7.3": + version "4.7.3" + resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-4.7.3.tgz#939534757a81f8d69cc854c7692805684ff3111e" + integrity sha512-dGRS0agJzu8ybo44pCIf3xBaPQN/65AIXNgK8+4gzKd5kbvlqyxryUYVLJv7fK98Seyd2hDZzVEHSWAh0Bt1Yw== + "@openzeppelin/contracts@^2.4.0": version "2.5.1" resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-2.5.1.tgz#c76e3fc57aa224da3718ec351812a4251289db31" @@ -4396,12 +4351,22 @@ resolved "https://registry.npmjs.org/@threshold-network/components/-/components-1.0.0-dev.31.tgz#7767a9f136156f8d4f3044d90e87a1014eb07a67" integrity sha512-ftzJV6p2He3Co0wLYky+sX0NAFVGrJCRvBDI0n3KF4POBO425Qy3yodS7HOkT1TgGRNU8AGO0KebS2X7gfgAEA== -"@threshold-network/solidity-contracts@1.2.1": - version "1.2.1" - resolved "https://registry.yarnpkg.com/@threshold-network/solidity-contracts/-/solidity-contracts-1.2.1.tgz#8f9d8fe52f24b51acc52fdff765fdef3b8546587" - integrity sha512-v19gnQzdU52DLB6ZpkCW4YHTvApmwA1EG/YRxh+FRrzeDOC6rv+EqUhLgKpMtSpgBZT1ryqqLXm1QmjkW6CIGw== +"@threshold-network/solidity-contracts@1.3.0-dev.11": + version "1.3.0-dev.11" + resolved "https://registry.yarnpkg.com/@threshold-network/solidity-contracts/-/solidity-contracts-1.3.0-dev.11.tgz#849f20a5094c93359bbdea0c42780c318f985ee0" + integrity sha512-QQJB17BvuU/7UaitneoD7zFmIA3fZQ3FAvOAP2q+FkWEBZPYtAMf3+vB7y+Y+QlrcUl1kcA9wXD5auirsdxCBQ== dependencies: - "@keep-network/keep-core" "1.7.0" + "@keep-network/keep-core" ">1.8.1-dev <1.8.1-goerli" + "@openzeppelin/contracts" "~4.5.0" + "@openzeppelin/contracts-upgradeable" "~4.5.2" + "@thesis/solidity-contracts" "github:thesis/solidity-contracts#4985bcf" + +"@threshold-network/solidity-contracts@1.3.0-dev.12": + version "1.3.0-dev.12" + resolved "https://registry.yarnpkg.com/@threshold-network/solidity-contracts/-/solidity-contracts-1.3.0-dev.12.tgz#55e2d789ac6cd2180f8f55cd876a5bdd0a9b45e6" + integrity sha512-06EF583uEwko3ik7qjnMOg+sJ+Vb7YWkqag4a9xZq8Mmy8rifpmLjnfDKCVGeKbUis3uI++pTGC9U/EfvVOrlQ== + dependencies: + "@keep-network/keep-core" ">1.8.1-dev <1.8.1-goerli" "@openzeppelin/contracts" "~4.5.0" "@openzeppelin/contracts-upgradeable" "~4.5.2" "@thesis/solidity-contracts" "github:thesis/solidity-contracts#4985bcf"