From 252156932835bea2ecc80484725829763816b020 Mon Sep 17 00:00:00 2001
From: Owen
Date: Fri, 12 Sep 2025 00:20:03 -0400
Subject: [PATCH 01/12] feat: staking manager rough draft
---
.../[step]/client-page.tsx | 15 +
.../staking-manager-setup/[step]/page.tsx | 8 +
.../staking-manager-setup/page.tsx | 7 +
.../staking-manager-setup/steps.ts | 34 +
components/console/console-sidebar.tsx | 3 +-
.../setup/DeployExampleRewardCalculator.tsx | 114 +
.../setup/erc20/DeployERC20StakingManager.tsx | 155 +
.../erc20/InitializeERC20StakingManager.tsx | 370 ++
.../native/DeployNativeStakingManager.tsx | 156 +
.../native/EnableStakingManagerMinting.tsx | 79 +
.../native/InitializeNativeStakingManager.tsx | 339 ++
components/toolbox/stores/toolboxStore.ts | 6 +-
.../compiled/ERC20TokenStakingManager.json | 3069 +++++++++++++++++
contracts/icm-contracts/entrypoint.sh | 1 +
14 files changed, 4352 insertions(+), 4 deletions(-)
create mode 100644 app/console/permissionless-l1s/staking-manager-setup/[step]/client-page.tsx
create mode 100644 app/console/permissionless-l1s/staking-manager-setup/[step]/page.tsx
create mode 100644 app/console/permissionless-l1s/staking-manager-setup/page.tsx
create mode 100644 app/console/permissionless-l1s/staking-manager-setup/steps.ts
create mode 100644 components/toolbox/console/permissionless-l1s/setup/DeployExampleRewardCalculator.tsx
create mode 100644 components/toolbox/console/permissionless-l1s/setup/erc20/DeployERC20StakingManager.tsx
create mode 100644 components/toolbox/console/permissionless-l1s/setup/erc20/InitializeERC20StakingManager.tsx
create mode 100644 components/toolbox/console/permissionless-l1s/setup/native/DeployNativeStakingManager.tsx
create mode 100644 components/toolbox/console/permissionless-l1s/setup/native/EnableStakingManagerMinting.tsx
create mode 100644 components/toolbox/console/permissionless-l1s/setup/native/InitializeNativeStakingManager.tsx
create mode 100644 contracts/icm-contracts/compiled/ERC20TokenStakingManager.json
diff --git a/app/console/permissionless-l1s/staking-manager-setup/[step]/client-page.tsx b/app/console/permissionless-l1s/staking-manager-setup/[step]/client-page.tsx
new file mode 100644
index 00000000000..4dcb8ccec3f
--- /dev/null
+++ b/app/console/permissionless-l1s/staking-manager-setup/[step]/client-page.tsx
@@ -0,0 +1,15 @@
+"use client";
+
+import StepFlow from "@/components/console/step-flow";
+import { steps } from "../steps";
+
+export default function StakingManagerSetupClientPage({ currentStepKey }: { currentStepKey: string }) {
+ const basePath = "/console/permissionless-l1s/staking-manager-setup";
+ return (
+
+ );
+}
diff --git a/app/console/permissionless-l1s/staking-manager-setup/[step]/page.tsx b/app/console/permissionless-l1s/staking-manager-setup/[step]/page.tsx
new file mode 100644
index 00000000000..fe2a1590cea
--- /dev/null
+++ b/app/console/permissionless-l1s/staking-manager-setup/[step]/page.tsx
@@ -0,0 +1,8 @@
+import StakingManagerSetupClientPage from "./client-page";
+
+export default async function Page({ params }: { params: Promise<{ step: string }> }) {
+ const { step } = await params;
+ return (
+
+ );
+}
diff --git a/app/console/permissionless-l1s/staking-manager-setup/page.tsx b/app/console/permissionless-l1s/staking-manager-setup/page.tsx
new file mode 100644
index 00000000000..574f8cd168d
--- /dev/null
+++ b/app/console/permissionless-l1s/staking-manager-setup/page.tsx
@@ -0,0 +1,7 @@
+import { redirect } from "next/navigation";
+
+export default function Page() {
+ redirect("/console/permissionless-l1s/staking-manager-setup/deploy-native-token-staking-manager");
+}
+
+
diff --git a/app/console/permissionless-l1s/staking-manager-setup/steps.ts b/app/console/permissionless-l1s/staking-manager-setup/steps.ts
new file mode 100644
index 00000000000..4cc3279d57c
--- /dev/null
+++ b/app/console/permissionless-l1s/staking-manager-setup/steps.ts
@@ -0,0 +1,34 @@
+import { type StepDefinition } from "@/components/console/step-flow";
+import ReadContract from "@/components/toolbox/console/permissioned-l1s/validator-manager-setup/ReadContract";
+import DeployNativeTokenStakingManager from "@/components/toolbox/console/permissionless-l1s/setup/native/DeployNativeStakingManager";
+import InitializeNativeTokenStakingManager from "@/components/toolbox/console/permissionless-l1s/setup/native/InitializeNativeStakingManager";
+import DeployERC20StakingManager from "@/components/toolbox/console/permissionless-l1s/setup/erc20/DeployERC20StakingManager";
+import InitializeERC20StakingManager from "@/components/toolbox/console/permissionless-l1s/setup/erc20/InitializeERC20StakingManager";
+import DeployExampleRewardCalculator from "@/components/toolbox/console/permissionless-l1s/setup/DeployExampleRewardCalculator";
+import TransferOwnership from "@/components/toolbox/console/permissioned-l1s/multisig-setup/TransferOwnership";
+import EnableStakingManagerMinting from "@/components/toolbox/console/permissionless-l1s/setup/native/EnableStakingManagerMinting";
+
+export const steps: StepDefinition[] = [
+ {
+ type: "branch",
+ key: "deploy-staking-manager",
+ title: "Deploy Staking Manager",
+ options: [
+ { key: "deploy-native-token-staking-manager", label: "Deploy Native Token Staking Manager", component: DeployNativeTokenStakingManager },
+ { key: "deploy-erc20-staking-manager", label: "Deploy ERC20 Token Staking Manager", component: DeployERC20StakingManager },
+ ],
+ },
+ { type: "single", key: "deploy-example-reward-calculator", title: "Deploy Example Reward Calculator", component: DeployExampleRewardCalculator },
+ {
+ type: "branch",
+ key: "initialize-staking-manager",
+ title: "Initialize Staking Manager",
+ options: [
+ { key: "initialize-native-staking-manager", label: "Initialize Native Token Staking Manager", component: InitializeNativeTokenStakingManager },
+ { key: "initialize-erc20-staking-manager", label: "Initialize ERC20 Token Staking Manager", component: InitializeERC20StakingManager },
+ ],
+ },
+ { type: "single", key: "enable-staking-minting", title: "Enable Staking Manager Minting", component: EnableStakingManagerMinting, optional: true },
+ { type: "single", key: "transfer-ownership", title: "Transfer Ownership", component: TransferOwnership },
+ { type: "single", key: "read-contract", title: "Read Contract", component: ReadContract },
+];
diff --git a/components/console/console-sidebar.tsx b/components/console/console-sidebar.tsx
index 358632caffd..21284746990 100644
--- a/components/console/console-sidebar.tsx
+++ b/components/console/console-sidebar.tsx
@@ -222,9 +222,8 @@ const data = {
items: [
{
title: "Migrate from Permissioned L1",
- url: "/console/permissionless-l1s/deploy-reward-manager",
+ url: "/console/permissionless-l1s/staking-manager-setup",
icon: GitMerge,
- comingSoon: true,
},
{
title: "Stake & Unstake",
diff --git a/components/toolbox/console/permissionless-l1s/setup/DeployExampleRewardCalculator.tsx b/components/toolbox/console/permissionless-l1s/setup/DeployExampleRewardCalculator.tsx
new file mode 100644
index 00000000000..119c1a23251
--- /dev/null
+++ b/components/toolbox/console/permissionless-l1s/setup/DeployExampleRewardCalculator.tsx
@@ -0,0 +1,114 @@
+"use client";
+
+import { useState } from "react";
+import { useWalletStore } from "@/components/toolbox/stores/walletStore";
+import { useToolboxStore, useViemChainStore } from "@/components/toolbox/stores/toolboxStore";
+import { Button } from "@/components/toolbox/components/Button";
+import { Container } from "@/components/toolbox/components/Container";
+import { Success } from "@/components/toolbox/components/Success";
+import { Input } from "@/components/toolbox/components/Input";
+import { CheckWalletRequirements } from "@/components/toolbox/components/CheckWalletRequirements";
+import { WalletRequirementsConfigKey } from "@/components/toolbox/hooks/useWalletRequirements";
+import ExampleRewardCalculator from "@/contracts/icm-contracts/compiled/ExampleRewardCalculator.json";
+import versions from '@/scripts/versions.json';
+
+const ICM_COMMIT = versions["ava-labs/icm-contracts"];
+const EXAMPLE_REWARD_CALCULATOR_SOURCE_URL = `https://github.com/ava-labs/icm-contracts/blob/${ICM_COMMIT}/contracts/validator-manager/ExampleRewardCalculator.sol`;
+
+export default function DeployExampleRewardCalculator() {
+ const [criticalError, setCriticalError] = useState(null);
+ const [isDeploying, setIsDeploying] = useState(false);
+ const [rewardBasisPoints, setRewardBasisPoints] = useState("500"); // Default 5% APR (500 basis points)
+
+ const { coreWalletClient, publicClient } = useWalletStore();
+ const viemChain = useViemChainStore();
+ const { rewardCalculatorAddress, setRewardCalculatorAddress } = useToolboxStore();
+
+ // Throw critical errors during render
+ if (criticalError) {
+ throw criticalError;
+ }
+
+ async function deployExampleRewardCalculator() {
+ setIsDeploying(true);
+ setRewardCalculatorAddress("");
+ try {
+ await coreWalletClient.addChain({ chain: viemChain });
+ await coreWalletClient.switchChain({ id: viemChain!.id });
+
+ // Let viem handle gas estimation automatically
+ // ExampleRewardCalculator is a simple contract, so auto-estimation should work
+ const hash = await coreWalletClient.deployContract({
+ abi: ExampleRewardCalculator.abi,
+ bytecode: ExampleRewardCalculator.bytecode.object as `0x${string}`,
+ args: [BigInt(rewardBasisPoints)], // Constructor takes uint64 rewardBasisPoints
+ chain: viemChain,
+ });
+
+ const receipt = await publicClient.waitForTransactionReceipt({ hash });
+
+ if (!receipt.contractAddress) {
+ throw new Error('No contract address in receipt');
+ }
+
+ setRewardCalculatorAddress(receipt.contractAddress);
+ } catch (error) {
+ setCriticalError(error instanceof Error ? error : new Error(String(error)));
+ } finally {
+ setIsDeploying(false);
+ }
+ }
+
+ return (
+
+
+
+
+ This will deploy the ExampleRewardCalculator contract to the EVM network {viemChain?.id}.
+ The Example Reward Calculator implements a linear, non-compounding reward calculation that rewards a set percentage of tokens per year.
+
+
+ Contract source: ExampleRewardCalculator.sol @ {ICM_COMMIT.slice(0, 7)}
+
+
+
+
+
+
+
+ Deploy Example Reward Calculator
+
+
+
Deployment Status: {rewardCalculatorAddress || "Not deployed"}
+
+ {rewardCalculatorAddress && (
+
+ )}
+
+
+
+ );
+}
diff --git a/components/toolbox/console/permissionless-l1s/setup/erc20/DeployERC20StakingManager.tsx b/components/toolbox/console/permissionless-l1s/setup/erc20/DeployERC20StakingManager.tsx
new file mode 100644
index 00000000000..627a050d273
--- /dev/null
+++ b/components/toolbox/console/permissionless-l1s/setup/erc20/DeployERC20StakingManager.tsx
@@ -0,0 +1,155 @@
+"use client";
+
+import { useState } from "react";
+import { useWalletStore } from "@/components/toolbox/stores/walletStore";
+import { useToolboxStore, useViemChainStore } from "@/components/toolbox/stores/toolboxStore";
+import { Button } from "@/components/toolbox/components/Button";
+import { Container } from "@/components/toolbox/components/Container";
+import { Success } from "@/components/toolbox/components/Success";
+import { CheckWalletRequirements } from "@/components/toolbox/components/CheckWalletRequirements";
+import { WalletRequirementsConfigKey } from "@/components/toolbox/hooks/useWalletRequirements";
+import ERC20TokenStakingManager from "@/contracts/icm-contracts/compiled/ERC20TokenStakingManager.json";
+import versions from '@/scripts/versions.json';
+import { keccak256 } from 'viem';
+
+const ICM_COMMIT = versions["ava-labs/icm-contracts"];
+const ERC20_TOKEN_STAKING_MANAGER_SOURCE_URL = `https://github.com/ava-labs/icm-contracts/blob/main/contracts/validator-manager/ERC20TokenStakingManager.sol`;
+
+// this should be pulled into a shared utils file with other contract deployments
+function calculateLibraryHash(libraryPath: string) {
+ const hash = keccak256(
+ new TextEncoder().encode(libraryPath)
+ ).slice(2);
+ return hash.slice(0, 34);
+}
+
+export default function DeployERC20StakingManager() {
+ const [criticalError, setCriticalError] = useState(null);
+ const [isDeploying, setIsDeploying] = useState(false);
+
+ const { coreWalletClient, publicClient, walletEVMAddress } = useWalletStore();
+ const viemChain = useViemChainStore();
+ const { erc20StakingManagerAddress, setErc20StakingManagerAddress, validatorMessagesLibAddress } = useToolboxStore();
+
+ // Throw critical errors during render
+ if (criticalError) {
+ throw criticalError;
+ }
+
+ const getLinkedBytecode = () => {
+ if (!validatorMessagesLibAddress) {
+ throw new Error('ValidatorMessages library must be deployed first. Please deploy it in the Validator Manager setup.');
+ }
+
+ const libraryPath = `${Object.keys(ERC20TokenStakingManager.bytecode.linkReferences)[0]}:${Object.keys(Object.values(ERC20TokenStakingManager.bytecode.linkReferences)[0])[0]}`;
+ const libraryHash = calculateLibraryHash(libraryPath);
+ const libraryPlaceholder = `__$${libraryHash}$__`;
+
+ const linkedBytecode = ERC20TokenStakingManager.bytecode.object
+ .split(libraryPlaceholder)
+ .join(validatorMessagesLibAddress.slice(2).padStart(40, '0'));
+
+ if (linkedBytecode.includes("$__")) {
+ throw new Error("Failed to replace library placeholder with actual address");
+ }
+
+ return linkedBytecode as `0x${string}`;
+ };
+
+ async function deployERC20StakingManager() {
+ setIsDeploying(true);
+ setErc20StakingManagerAddress("");
+ try {
+ if (!viemChain) throw new Error("Viem chain not found");
+
+ // Check for library first
+ if (!validatorMessagesLibAddress) {
+ throw new Error('ValidatorMessages library must be deployed first. Please go to Validator Manager Setup and deploy the library.');
+ }
+
+ // Follow exact pattern from ValidatorManager deployment
+ await coreWalletClient.addChain({ chain: viemChain });
+ await coreWalletClient.switchChain({ id: viemChain!.id });
+
+ const hash = await coreWalletClient.deployContract({
+ abi: ERC20TokenStakingManager.abi,
+ bytecode: getLinkedBytecode(), // Use linked bytecode with library
+ args: [0], // ICMInitializable.Allowed
+ chain: viemChain,
+ });
+
+ const receipt = await publicClient.waitForTransactionReceipt({ hash });
+
+ if (!receipt.contractAddress) {
+ throw new Error('No contract address in receipt');
+ }
+
+ setErc20StakingManagerAddress(receipt.contractAddress);
+ } catch (error) {
+ setCriticalError(error instanceof Error ? error : new Error(String(error)));
+ } finally {
+ setIsDeploying(false);
+ }
+ }
+
+ return (
+
+
+
+
+ This will deploy the ERC20TokenStakingManager contract to the EVM network {viemChain?.id}.
+ The ERC20 Token Staking Manager enables permissionless staking on your L1 using a custom ERC20 token.
+
+
+ Contract source: ERC20TokenStakingManager.sol @ {ICM_COMMIT.slice(0, 7)}
+
+ {walletEVMAddress && (
+
+ Connected wallet: {walletEVMAddress}
+
+ )}
+
+ {!validatorMessagesLibAddress ? (
+
+
+ Required: ValidatorMessages library must be deployed first.
+ Please go to the Validator Manager Setup section and deploy the ValidatorMessages library.
+
+
+ ) : (
+
+
+ Ready: ValidatorMessages library found at: {validatorMessagesLibAddress}
+
+
+ )}
+
+
+ {!validatorMessagesLibAddress
+ ? "Deploy ValidatorMessages Library First"
+ : "Deploy ERC20 Token Staking Manager"}
+
+
+
Deployment Status: {erc20StakingManagerAddress || "Not deployed"}
+
+ {erc20StakingManagerAddress && (
+
+ )}
+
+
+
+ );
+}
diff --git a/components/toolbox/console/permissionless-l1s/setup/erc20/InitializeERC20StakingManager.tsx b/components/toolbox/console/permissionless-l1s/setup/erc20/InitializeERC20StakingManager.tsx
new file mode 100644
index 00000000000..19de8cdd423
--- /dev/null
+++ b/components/toolbox/console/permissionless-l1s/setup/erc20/InitializeERC20StakingManager.tsx
@@ -0,0 +1,370 @@
+"use client";
+
+import { useState, useEffect } from "react";
+import { useWalletStore } from "@/components/toolbox/stores/walletStore";
+import { useToolboxStore, useViemChainStore } from "@/components/toolbox/stores/toolboxStore";
+import { Button } from "@/components/toolbox/components/Button";
+import { Container } from "@/components/toolbox/components/Container";
+import { Input } from "@/components/toolbox/components/Input";
+import { EVMAddressInput } from "@/components/toolbox/components/EVMAddressInput";
+import { CheckWalletRequirements } from "@/components/toolbox/components/CheckWalletRequirements";
+import { WalletRequirementsConfigKey } from "@/components/toolbox/hooks/useWalletRequirements";
+import { ResultField } from "@/components/toolbox/components/ResultField";
+import { Step, Steps } from "fumadocs-ui/components/steps";
+import SelectSubnet, { SubnetSelection } from '@/components/toolbox/components/SelectSubnet';
+import { useValidatorManagerDetails } from '@/components/toolbox/hooks/useValidatorManagerDetails';
+import { Callout } from "fumadocs-ui/components/callout";
+import ERC20TokenStakingManager from "@/contracts/icm-contracts/compiled/ERC20TokenStakingManager.json";
+import { parseEther } from "viem";
+import versions from '@/scripts/versions.json';
+
+const ICM_COMMIT = versions["ava-labs/icm-contracts"];
+const INITIALIZE_FUNCTION_SOURCE_URL = `https://github.com/ava-labs/icm-contracts/blob/main/contracts/validator-manager/ERC20TokenStakingManager.sol#L53`;
+
+export default function InitializeERC20StakingManager() {
+ const [criticalError, setCriticalError] = useState(null);
+ const [stakingManagerAddressInput, setStakingManagerAddressInput] = useState("");
+ const [isChecking, setIsChecking] = useState(false);
+ const [isInitializing, setIsInitializing] = useState(false);
+ const [isInitialized, setIsInitialized] = useState(null);
+ const [initEvent, setInitEvent] = useState(null);
+ const [subnetSelection, setSubnetSelection] = useState({
+ subnetId: "",
+ subnet: null
+ });
+
+ // Initialization parameters
+ const [minimumStakeAmount, setMinimumStakeAmount] = useState("1");
+ const [maximumStakeAmount, setMaximumStakeAmount] = useState("1000000");
+ const [minimumStakeDuration, setMinimumStakeDuration] = useState("86400"); // 1 day default
+ const [minimumDelegationFeeBips, setMinimumDelegationFeeBips] = useState("100"); // 1% default
+ const [maximumStakeMultiplier, setMaximumStakeMultiplier] = useState("10");
+ const [weightToValueFactor, setWeightToValueFactor] = useState("1");
+ const [rewardCalculatorAddress, setRewardCalculatorAddress] = useState("");
+ const [stakingTokenAddress, setStakingTokenAddress] = useState("");
+
+ const { coreWalletClient, publicClient } = useWalletStore();
+ const viemChain = useViemChainStore();
+ const { erc20StakingManagerAddress: storedStakingManagerAddress, rewardCalculatorAddress: storedRewardCalculatorAddress } = useToolboxStore();
+
+ // Get validator manager details from subnet ID
+ const {
+ validatorManagerAddress,
+ error: validatorManagerError,
+ isLoading: isLoadingVMCDetails,
+ } = useValidatorManagerDetails({ subnetId: subnetSelection.subnetId });
+
+ // Extract blockchain ID from subnet data
+ const blockchainId = subnetSelection.subnet?.blockchains?.[0]?.blockchainId || null;
+
+ // Throw critical errors during render
+ if (criticalError) {
+ throw criticalError;
+ }
+
+ // Auto-fill addresses from store if available
+ useEffect(() => {
+ if (storedStakingManagerAddress && !stakingManagerAddressInput) {
+ setStakingManagerAddressInput(storedStakingManagerAddress);
+ }
+ }, [storedStakingManagerAddress, stakingManagerAddressInput]);
+
+ useEffect(() => {
+ if (storedRewardCalculatorAddress && !rewardCalculatorAddress) {
+ setRewardCalculatorAddress(storedRewardCalculatorAddress);
+ }
+ }, [storedRewardCalculatorAddress, rewardCalculatorAddress]);
+
+ async function checkIfInitialized() {
+ if (!stakingManagerAddressInput) return;
+
+ setIsChecking(true);
+ try {
+ // Try to check initialization by reading a setting that would be 0 if not initialized
+ const data = await publicClient.readContract({
+ address: stakingManagerAddressInput as `0x${string}`,
+ abi: ERC20TokenStakingManager.abi,
+ functionName: 'minimumStakeAmount',
+ });
+
+ const initialized = BigInt(data as string) > 0n;
+ setIsInitialized(initialized);
+
+ if (initialized) {
+ // If initialized, get more details
+ const [settings, token] = await Promise.all([
+ publicClient.readContract({
+ address: stakingManagerAddressInput as `0x${string}`,
+ abi: ERC20TokenStakingManager.abi,
+ functionName: 'minimumStakeAmount',
+ }),
+ publicClient.readContract({
+ address: stakingManagerAddressInput as `0x${string}`,
+ abi: ERC20TokenStakingManager.abi,
+ functionName: 'erc20',
+ })
+ ]);
+ setInitEvent({ minimumStakeAmount: settings, stakingToken: token });
+ }
+ } catch (error) {
+ setIsInitialized(false);
+ } finally {
+ setIsChecking(false);
+ }
+ }
+
+ async function handleInitialize() {
+ if (!stakingManagerAddressInput) return;
+
+ setIsInitializing(true);
+ try {
+ if (!validatorManagerAddress) throw new Error("Validator Manager address required");
+ if (!rewardCalculatorAddress) throw new Error("Reward Calculator address required");
+ if (!stakingTokenAddress) throw new Error("Staking Token address required");
+ if (!blockchainId) throw new Error("Blockchain ID not found. Please select a valid subnet.");
+
+ // Create settings object
+ const settings = {
+ manager: validatorManagerAddress as `0x${string}`,
+ minimumStakeAmount: parseEther(minimumStakeAmount),
+ maximumStakeAmount: parseEther(maximumStakeAmount),
+ minimumStakeDuration: BigInt(minimumStakeDuration),
+ minimumDelegationFeeBips: parseInt(minimumDelegationFeeBips),
+ maximumStakeMultiplier: parseInt(maximumStakeMultiplier),
+ weightToValueFactor: parseEther(weightToValueFactor),
+ rewardCalculator: rewardCalculatorAddress as `0x${string}`,
+ uptimeBlockchainID: blockchainId as `0x${string}`
+ };
+
+ // Estimate gas for initialization
+ const gasEstimate = await publicClient.estimateContractGas({
+ address: stakingManagerAddressInput as `0x${string}`,
+ abi: ERC20TokenStakingManager.abi,
+ functionName: 'initialize',
+ args: [settings, stakingTokenAddress as `0x${string}`],
+ account: coreWalletClient.account.address,
+ });
+
+ // Add 20% buffer to gas estimate for safety
+ const gasWithBuffer = gasEstimate + (gasEstimate * 20n / 100n);
+
+ const hash = await coreWalletClient.writeContract({
+ address: stakingManagerAddressInput as `0x${string}`,
+ abi: ERC20TokenStakingManager.abi,
+ functionName: 'initialize',
+ args: [settings, stakingTokenAddress as `0x${string}`],
+ chain: viemChain,
+ gas: gasWithBuffer,
+ });
+
+ await publicClient.waitForTransactionReceipt({ hash });
+ await checkIfInitialized();
+ } catch (error) {
+ setCriticalError(error instanceof Error ? error : new Error(String(error)));
+ } finally {
+ setIsInitializing(false);
+ }
+ }
+
+ return (
+
+
+
+
+ Select L1 Subnet
+
+ Choose the L1 subnet where the ERC20 Token Staking Manager will be initialized. The Validator Manager address and blockchain ID will be automatically derived from your selection.
+
+
+
+ {subnetSelection.subnet && !subnetSelection.subnet.isL1 && (
+
+
+ Note: This subnet has not been converted to an L1 yet. ERC20 Token Staking Manager can only be initialized for L1s.
+
+
+ )}
+
+ {validatorManagerAddress && (
+
+
+ Validator Manager Address: {validatorManagerAddress}
+
+
+ )}
+
+
+
+ Select ERC20 Token Staking Manager
+
+ Select the ERC20 Token Staking Manager contract you want to initialize.
+
+
+ Initialize function source: initialize() @ {ICM_COMMIT.slice(0, 7)}
+
+
+
+
+
+ Check Status
+
+
+
+
+ Configure Staking Token & Rewards
+
+ Set the ERC20 token that will be used for staking and the Reward Calculator contract address. The Validator Manager address and Uptime Blockchain ID are automatically derived from your subnet selection.
+
+
+
+ {validatorManagerAddress && (
+
+
+ Validator Manager Address: {validatorManagerAddress}
+
+
+ Uptime Blockchain ID: {blockchainId || 'Loading...'}
+
+
+ )}
+
+
+
+
+ Important: Token Requirements
+ The ERC20 token must implement the IERC20Mintable interface.
+ This allows the staking manager to mint rewards. Care should be taken to enforce that only
+ authorized users (i.e., the staking manager contract) are able to mint the ERC20 staking token.
+
+
+
+
+
+
+
+ Set Staking Parameters
+
+ Configure the staking parameters that define how validators and delegators can participate in securing the network.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Initialize Contract
+
+
+
+
+ {isInitialized === true && (
+
+ )}
+
+
+ );
+}
+
+function jsonStringifyWithBigint(value: unknown) {
+ return JSON.stringify(value, (_, v) =>
+ typeof v === 'bigint' ? v.toString() : v
+ , 2);
+}
diff --git a/components/toolbox/console/permissionless-l1s/setup/native/DeployNativeStakingManager.tsx b/components/toolbox/console/permissionless-l1s/setup/native/DeployNativeStakingManager.tsx
new file mode 100644
index 00000000000..1dfbd822d3b
--- /dev/null
+++ b/components/toolbox/console/permissionless-l1s/setup/native/DeployNativeStakingManager.tsx
@@ -0,0 +1,156 @@
+"use client";
+
+import { useState } from "react";
+import { useWalletStore } from "@/components/toolbox/stores/walletStore";
+import { useToolboxStore, useViemChainStore } from "@/components/toolbox/stores/toolboxStore";
+import { Button } from "@/components/toolbox/components/Button";
+import { Container } from "@/components/toolbox/components/Container";
+import { Success } from "@/components/toolbox/components/Success";
+import { CheckWalletRequirements } from "@/components/toolbox/components/CheckWalletRequirements";
+import { WalletRequirementsConfigKey } from "@/components/toolbox/hooks/useWalletRequirements";
+import NativeTokenStakingManager from "@/contracts/icm-contracts/compiled/NativeTokenStakingManager.json";
+import versions from '@/scripts/versions.json';
+import { keccak256 } from 'viem';
+
+const ICM_COMMIT = versions["ava-labs/icm-contracts"];
+const NATIVE_TOKEN_STAKING_MANAGER_SOURCE_URL = `https://github.com/ava-labs/icm-contracts/blob/main/contracts/validator-manager/NativeTokenStakingManager.sol`;
+
+// this should be pulled into a shared utils file with other contract deployments
+function calculateLibraryHash(libraryPath: string) {
+ const hash = keccak256(
+ new TextEncoder().encode(libraryPath)
+ ).slice(2);
+ return hash.slice(0, 34);
+}
+
+export default function DeployNativeStakingManager() {
+ const [criticalError, setCriticalError] = useState(null);
+ const [isDeploying, setIsDeploying] = useState(false);
+
+ const { coreWalletClient, publicClient, walletEVMAddress } = useWalletStore();
+ const viemChain = useViemChainStore();
+ const { nativeStakingManagerAddress, setNativeStakingManagerAddress, validatorMessagesLibAddress } = useToolboxStore();
+
+ // Throw critical errors during render
+ if (criticalError) {
+ throw criticalError;
+ }
+
+ const getLinkedBytecode = () => {
+ if (!validatorMessagesLibAddress) {
+ throw new Error('ValidatorMessages library must be deployed first. Please deploy it in the Validator Manager setup.');
+ }
+
+ const libraryPath = `${Object.keys(NativeTokenStakingManager.bytecode.linkReferences)[0]}:${Object.keys(Object.values(NativeTokenStakingManager.bytecode.linkReferences)[0])[0]}`;
+ const libraryHash = calculateLibraryHash(libraryPath);
+ const libraryPlaceholder = `__$${libraryHash}$__`;
+
+ const linkedBytecode = NativeTokenStakingManager.bytecode.object
+ .split(libraryPlaceholder)
+ .join(validatorMessagesLibAddress.slice(2).padStart(40, '0'));
+
+ if (linkedBytecode.includes("$__")) {
+ throw new Error("Failed to replace library placeholder with actual address");
+ }
+
+ return linkedBytecode as `0x${string}`;
+ };
+
+ async function deployNativeTokenStakingManager() {
+ setIsDeploying(true);
+ setNativeStakingManagerAddress("");
+ try {
+ if (!viemChain) throw new Error("Viem chain not found");
+
+ // Check for library first
+ if (!validatorMessagesLibAddress) {
+ throw new Error('ValidatorMessages library must be deployed first. Please go to Validator Manager Setup and deploy the library.');
+ }
+
+ // Follow exact pattern from ValidatorManager deployment
+ await coreWalletClient.addChain({ chain: viemChain });
+ await coreWalletClient.switchChain({ id: viemChain!.id });
+
+ const hash = await coreWalletClient.deployContract({
+ abi: NativeTokenStakingManager.abi,
+ bytecode: getLinkedBytecode(), // Use linked bytecode with library
+ args: [0], // ICMInitializable.Allowed
+ chain: viemChain,
+ });
+
+ const receipt = await publicClient.waitForTransactionReceipt({ hash });
+
+ if (!receipt.contractAddress) {
+ throw new Error('No contract address in receipt');
+ }
+
+ setNativeStakingManagerAddress(receipt.contractAddress);
+ } catch (error) {
+ setCriticalError(error instanceof Error ? error : new Error(String(error)));
+ } finally {
+ setIsDeploying(false);
+ }
+ }
+
+ return (
+
+
+
+
+ This will deploy the NativeTokenStakingManager contract to the EVM network {viemChain?.id}.
+ The Native Token Staking Manager enables permissionless staking on your L1 using the native token.
+
+
+ Contract source: NativeTokenStakingManager.sol @ {ICM_COMMIT.slice(0, 7)}
+
+ {walletEVMAddress && (
+
+ Connected wallet: {walletEVMAddress}
+
+ )}
+
+ {/* Library requirement notice */}
+ {!validatorMessagesLibAddress ? (
+
+
+ Required: ValidatorMessages library must be deployed first.
+ Please go to the Validator Manager Setup section and deploy the ValidatorMessages library.
+
+
+ ) : (
+
+
+ Ready: ValidatorMessages library found at: {validatorMessagesLibAddress}
+
+
+ )}
+
+
+ {!validatorMessagesLibAddress
+ ? "Deploy ValidatorMessages Library First"
+ : "Deploy Native Token Staking Manager"}
+
+
+
Deployment Status: {nativeStakingManagerAddress || "Not deployed"}
+
+ {nativeStakingManagerAddress && (
+
+ )}
+
+
+
+ );
+}
\ No newline at end of file
diff --git a/components/toolbox/console/permissionless-l1s/setup/native/EnableStakingManagerMinting.tsx b/components/toolbox/console/permissionless-l1s/setup/native/EnableStakingManagerMinting.tsx
new file mode 100644
index 00000000000..b2d470e0563
--- /dev/null
+++ b/components/toolbox/console/permissionless-l1s/setup/native/EnableStakingManagerMinting.tsx
@@ -0,0 +1,79 @@
+"use client";
+
+import { useState, useEffect } from "react";
+import { useToolboxStore } from "@/components/toolbox/stores/toolboxStore";
+import { Container } from "@/components/toolbox/components/Container";
+import { AllowlistComponent } from "@/components/toolbox/components/AllowListComponents";
+import { CheckPrecompile } from "@/components/toolbox/components/CheckPrecompile";
+import { CheckWalletRequirements } from "@/components/toolbox/components/CheckWalletRequirements";
+import { WalletRequirementsConfigKey } from "@/components/toolbox/hooks/useWalletRequirements";
+import { Callout } from "fumadocs-ui/components/callout";
+
+// Default Native Minter address
+const DEFAULT_NATIVE_MINTER_ADDRESS = "0x0200000000000000000000000000000000000001";
+
+export default function EnableStakingManagerMinting() {
+ const { nativeStakingManagerAddress } = useToolboxStore();
+ const [isNativeStaking, setIsNativeStaking] = useState(null);
+
+ useEffect(() => {
+ // Check if we have a native staking manager address stored
+ if (nativeStakingManagerAddress) {
+ setIsNativeStaking(true);
+ }
+ }, [nativeStakingManagerAddress]);
+
+ return (
+
+
+
+
+
+ Why is this needed?
+ The Native Token Staking Manager needs permission to mint native tokens as rewards for validators and delegators.
+ You must add the staking manager address to the Native Minter allowlist.
+ {nativeStakingManagerAddress && (
+
+ Your Native Token Staking Manager Address: {nativeStakingManagerAddress}
+
+ )}
+
+
+
+ Skip this step if using ERC20 Token Staking
+ This step is only required for Native Token Staking Manager. If you deployed an ERC20 Token Staking Manager,
+ you can skip this step as the ERC20 token should handle its own minting permissions.
+
+
+ {!nativeStakingManagerAddress && (
+
+ No native staking manager address found. Please deploy and initialize a Native Token Staking Manager first.
+
+ )}
+
+ {nativeStakingManagerAddress && (
+
+
+ Add your Native Token Staking Manager to the allowlist below:
+
+
+ )}
+
+
+
+
+
+
+ );
+}
diff --git a/components/toolbox/console/permissionless-l1s/setup/native/InitializeNativeStakingManager.tsx b/components/toolbox/console/permissionless-l1s/setup/native/InitializeNativeStakingManager.tsx
new file mode 100644
index 00000000000..e5524068f2e
--- /dev/null
+++ b/components/toolbox/console/permissionless-l1s/setup/native/InitializeNativeStakingManager.tsx
@@ -0,0 +1,339 @@
+"use client";
+
+import { useState, useEffect } from "react";
+import { useWalletStore } from "@/components/toolbox/stores/walletStore";
+import { useToolboxStore, useViemChainStore } from "@/components/toolbox/stores/toolboxStore";
+import { Button } from "@/components/toolbox/components/Button";
+import { Container } from "@/components/toolbox/components/Container";
+import { Input } from "@/components/toolbox/components/Input";
+import { EVMAddressInput } from "@/components/toolbox/components/EVMAddressInput";
+import { CheckWalletRequirements } from "@/components/toolbox/components/CheckWalletRequirements";
+import { WalletRequirementsConfigKey } from "@/components/toolbox/hooks/useWalletRequirements";
+import { ResultField } from "@/components/toolbox/components/ResultField";
+import { Step, Steps } from "fumadocs-ui/components/steps";
+import SelectSubnet, { SubnetSelection } from '@/components/toolbox/components/SelectSubnet';
+import { useValidatorManagerDetails } from '@/components/toolbox/hooks/useValidatorManagerDetails';
+import NativeTokenStakingManager from "@/contracts/icm-contracts/compiled/NativeTokenStakingManager.json";
+import { parseEther } from "viem";
+import versions from '@/scripts/versions.json';
+
+const ICM_COMMIT = versions["ava-labs/icm-contracts"];
+const INITIALIZE_FUNCTION_SOURCE_URL = `https://github.com/ava-labs/icm-contracts/blob/main/contracts/validator-manager/NativeTokenStakingManager.sol#L43`;
+
+export default function InitializeNativeStakingManager() {
+ const [criticalError, setCriticalError] = useState(null);
+ const [stakingManagerAddressInput, setStakingManagerAddressInput] = useState("");
+ const [isChecking, setIsChecking] = useState(false);
+ const [isInitializing, setIsInitializing] = useState(false);
+ const [isInitialized, setIsInitialized] = useState(null);
+ const [initEvent, setInitEvent] = useState(null);
+ const [subnetSelection, setSubnetSelection] = useState({
+ subnetId: "",
+ subnet: null
+ });
+
+ // Initialization parameters
+ const [minimumStakeAmount, setMinimumStakeAmount] = useState("1");
+ const [maximumStakeAmount, setMaximumStakeAmount] = useState("1000000");
+ const [minimumStakeDuration, setMinimumStakeDuration] = useState("86400"); // 1 day default
+ const [minimumDelegationFeeBips, setMinimumDelegationFeeBips] = useState("100"); // 1% default
+ const [maximumStakeMultiplier, setMaximumStakeMultiplier] = useState("10");
+ const [weightToValueFactor, setWeightToValueFactor] = useState("1");
+ const [rewardCalculatorAddress, setRewardCalculatorAddress] = useState("");
+
+ const { coreWalletClient, publicClient } = useWalletStore();
+ const viemChain = useViemChainStore();
+ const { nativeStakingManagerAddress: storedStakingManagerAddress, rewardCalculatorAddress: storedRewardCalculatorAddress } = useToolboxStore();
+
+ // Get validator manager details from subnet ID
+ const {
+ validatorManagerAddress,
+ error: validatorManagerError,
+ isLoading: isLoadingVMCDetails,
+ } = useValidatorManagerDetails({ subnetId: subnetSelection.subnetId });
+
+ // Extract blockchain ID from subnet data
+ const blockchainId = subnetSelection.subnet?.blockchains?.[0]?.blockchainId || null;
+
+ // Throw critical errors during render
+ if (criticalError) {
+ throw criticalError;
+ }
+
+ // Auto-fill addresses from store if available
+ useEffect(() => {
+ if (storedStakingManagerAddress && !stakingManagerAddressInput) {
+ setStakingManagerAddressInput(storedStakingManagerAddress);
+ }
+ }, [storedStakingManagerAddress, stakingManagerAddressInput]);
+
+ useEffect(() => {
+ if (storedRewardCalculatorAddress && !rewardCalculatorAddress) {
+ setRewardCalculatorAddress(storedRewardCalculatorAddress);
+ }
+ }, [storedRewardCalculatorAddress, rewardCalculatorAddress]);
+
+ async function checkIfInitialized() {
+ if (!stakingManagerAddressInput) return;
+
+ setIsChecking(true);
+ try {
+ // Try to check initialization by reading a setting that would be 0 if not initialized
+ const data = await publicClient.readContract({
+ address: stakingManagerAddressInput as `0x${string}`,
+ abi: NativeTokenStakingManager.abi,
+ functionName: 'minimumStakeAmount',
+ });
+
+ const initialized = BigInt(data as string) > 0n;
+ setIsInitialized(initialized);
+
+ if (initialized) {
+ // If initialized, get more details
+ const [settings] = await Promise.all([
+ publicClient.readContract({
+ address: stakingManagerAddressInput as `0x${string}`,
+ abi: NativeTokenStakingManager.abi,
+ functionName: 'minimumStakeAmount',
+ })
+ ]);
+ setInitEvent({ minimumStakeAmount: settings });
+ }
+ } catch (error) {
+ setIsInitialized(false);
+ } finally {
+ setIsChecking(false);
+ }
+ }
+
+ async function handleInitialize() {
+ if (!stakingManagerAddressInput) return;
+
+ setIsInitializing(true);
+ try {
+ if (!validatorManagerAddress) throw new Error("Validator Manager address required");
+ if (!rewardCalculatorAddress) throw new Error("Reward Calculator address required");
+ if (!blockchainId) throw new Error("Blockchain ID not found. Please select a valid subnet.");
+
+ // Create settings object
+ const settings = {
+ manager: validatorManagerAddress as `0x${string}`,
+ minimumStakeAmount: parseEther(minimumStakeAmount),
+ maximumStakeAmount: parseEther(maximumStakeAmount),
+ minimumStakeDuration: BigInt(minimumStakeDuration),
+ minimumDelegationFeeBips: parseInt(minimumDelegationFeeBips),
+ maximumStakeMultiplier: parseInt(maximumStakeMultiplier),
+ weightToValueFactor: parseEther(weightToValueFactor),
+ rewardCalculator: rewardCalculatorAddress as `0x${string}`,
+ uptimeBlockchainID: blockchainId as `0x${string}`
+ };
+
+ // Estimate gas for initialization
+ const gasEstimate = await publicClient.estimateContractGas({
+ address: stakingManagerAddressInput as `0x${string}`,
+ abi: NativeTokenStakingManager.abi,
+ functionName: 'initialize',
+ args: [settings],
+ account: coreWalletClient.account.address,
+ });
+
+ // Add 20% buffer to gas estimate for safety
+ const gasWithBuffer = gasEstimate + (gasEstimate * 20n / 100n);
+
+ const hash = await coreWalletClient.writeContract({
+ address: stakingManagerAddressInput as `0x${string}`,
+ abi: NativeTokenStakingManager.abi,
+ functionName: 'initialize',
+ args: [settings],
+ chain: viemChain,
+ gas: gasWithBuffer,
+ });
+
+ await publicClient.waitForTransactionReceipt({ hash });
+ await checkIfInitialized();
+ } catch (error) {
+ setCriticalError(error instanceof Error ? error : new Error(String(error)));
+ } finally {
+ setIsInitializing(false);
+ }
+ }
+
+ return (
+
+
+
+
+ Select L1 Subnet
+
+ Choose the L1 subnet where the Native Token Staking Manager will be initialized. The Validator Manager address and blockchain ID will be automatically derived from your selection.
+
+
+
+ {subnetSelection.subnet && !subnetSelection.subnet.isL1 && (
+
+
+ Note: This subnet has not been converted to an L1 yet. Native Token Staking Manager can only be initialized for L1s.
+
+
+ )}
+
+
+
+ Select Native Token Staking Manager
+
+ Select the Native Token Staking Manager contract you want to initialize.
+
+
+ Initialize function source: initialize() @ {ICM_COMMIT.slice(0, 7)}
+
+
+
+
+
+ Check Status
+
+
+
+
+ Configure Reward Calculator
+
+ Set the Reward Calculator contract address that determines how rewards are distributed to validators. The Validator Manager address and Uptime Blockchain ID are automatically derived from your subnet selection.
+
+
+
+ {validatorManagerAddress && (
+
+
+ Validator Manager Address: {validatorManagerAddress}
+
+
+ Uptime Blockchain ID: {blockchainId || 'Loading...'}
+
+
+ )}
+
+
+
+
+
+
+ Set Staking Parameters
+
+ Configure the staking parameters that define how validators and delegators can participate in securing the network.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Initialize Contract
+
+
+
+
+ {isInitialized === true && (
+
+ )}
+
+
+ );
+}
+
+function jsonStringifyWithBigint(value: unknown) {
+ return JSON.stringify(value, (_, v) =>
+ typeof v === 'bigint' ? v.toString() : v
+ , 2);
+}
diff --git a/components/toolbox/stores/toolboxStore.ts b/components/toolbox/stores/toolboxStore.ts
index d08e6f1cab3..0335da53f78 100644
--- a/components/toolbox/stores/toolboxStore.ts
+++ b/components/toolbox/stores/toolboxStore.ts
@@ -11,7 +11,8 @@ const toolboxInitialState = {
validatorMessagesLibAddress: "",
validatorManagerAddress: "",
rewardCalculatorAddress: "",
- stakingManagerAddress: "",
+ nativeStakingManagerAddress: "",
+ erc20StakingManagerAddress: "",
teleporterRegistryAddress: "",
icmReceiverAddress: "",
exampleErc20Address: "",
@@ -30,7 +31,8 @@ export const getToolboxStore = (chainId: string) => create(
setValidatorMessagesLibAddress: (validatorMessagesLibAddress: string) => set({ validatorMessagesLibAddress }),
setValidatorManagerAddress: (validatorManagerAddress: string) => set({ validatorManagerAddress }),
setRewardCalculatorAddress: (rewardCalculatorAddress: string) => set({ rewardCalculatorAddress }),
- setStakingManagerAddress: (stakingManagerAddress: string) => set({ stakingManagerAddress }),
+ setNativeStakingManagerAddress: (nativeStakingManagerAddress: string) => set({ nativeStakingManagerAddress }),
+ setErc20StakingManagerAddress: (erc20StakingManagerAddress: string) => set({ erc20StakingManagerAddress }),
setTeleporterRegistryAddress: (address: string) => set({ teleporterRegistryAddress: address }),
setIcmReceiverAddress: (address: string) => set({ icmReceiverAddress: address }),
setExampleErc20Address: (address: string) => set({ exampleErc20Address: address }),
diff --git a/contracts/icm-contracts/compiled/ERC20TokenStakingManager.json b/contracts/icm-contracts/compiled/ERC20TokenStakingManager.json
new file mode 100644
index 00000000000..359e1755aaa
--- /dev/null
+++ b/contracts/icm-contracts/compiled/ERC20TokenStakingManager.json
@@ -0,0 +1,3069 @@
+{
+ "abi": [
+ {
+ "type": "constructor",
+ "inputs": [
+ {
+ "name": "init",
+ "type": "uint8",
+ "internalType": "enum ICMInitializable"
+ }
+ ],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "BIPS_CONVERSION_FACTOR",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint16",
+ "internalType": "uint16"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "ERC20_STAKING_MANAGER_STORAGE_LOCATION",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "bytes32",
+ "internalType": "bytes32"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "MAXIMUM_DELEGATION_FEE_BIPS",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint16",
+ "internalType": "uint16"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "MAXIMUM_STAKE_MULTIPLIER_LIMIT",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint8",
+ "internalType": "uint8"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "STAKING_MANAGER_STORAGE_LOCATION",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "bytes32",
+ "internalType": "bytes32"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "WARP_MESSENGER",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "address",
+ "internalType": "contract IWarpMessenger"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "changeDelegatorRewardRecipient",
+ "inputs": [
+ {
+ "name": "delegationID",
+ "type": "bytes32",
+ "internalType": "bytes32"
+ },
+ {
+ "name": "rewardRecipient",
+ "type": "address",
+ "internalType": "address"
+ }
+ ],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "changeValidatorRewardRecipient",
+ "inputs": [
+ {
+ "name": "validationID",
+ "type": "bytes32",
+ "internalType": "bytes32"
+ },
+ {
+ "name": "rewardRecipient",
+ "type": "address",
+ "internalType": "address"
+ }
+ ],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "claimDelegationFees",
+ "inputs": [
+ {
+ "name": "validationID",
+ "type": "bytes32",
+ "internalType": "bytes32"
+ }
+ ],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "completeDelegatorRegistration",
+ "inputs": [
+ {
+ "name": "delegationID",
+ "type": "bytes32",
+ "internalType": "bytes32"
+ },
+ {
+ "name": "messageIndex",
+ "type": "uint32",
+ "internalType": "uint32"
+ }
+ ],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "completeDelegatorRemoval",
+ "inputs": [
+ {
+ "name": "delegationID",
+ "type": "bytes32",
+ "internalType": "bytes32"
+ },
+ {
+ "name": "messageIndex",
+ "type": "uint32",
+ "internalType": "uint32"
+ }
+ ],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "completeValidatorRegistration",
+ "inputs": [
+ {
+ "name": "messageIndex",
+ "type": "uint32",
+ "internalType": "uint32"
+ }
+ ],
+ "outputs": [
+ {
+ "name": "",
+ "type": "bytes32",
+ "internalType": "bytes32"
+ }
+ ],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "completeValidatorRemoval",
+ "inputs": [
+ {
+ "name": "messageIndex",
+ "type": "uint32",
+ "internalType": "uint32"
+ }
+ ],
+ "outputs": [
+ {
+ "name": "",
+ "type": "bytes32",
+ "internalType": "bytes32"
+ }
+ ],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "erc20",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "address",
+ "internalType": "contract IERC20Mintable"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "forceInitiateDelegatorRemoval",
+ "inputs": [
+ {
+ "name": "delegationID",
+ "type": "bytes32",
+ "internalType": "bytes32"
+ },
+ {
+ "name": "includeUptimeProof",
+ "type": "bool",
+ "internalType": "bool"
+ },
+ {
+ "name": "messageIndex",
+ "type": "uint32",
+ "internalType": "uint32"
+ }
+ ],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "forceInitiateValidatorRemoval",
+ "inputs": [
+ {
+ "name": "validationID",
+ "type": "bytes32",
+ "internalType": "bytes32"
+ },
+ {
+ "name": "includeUptimeProof",
+ "type": "bool",
+ "internalType": "bool"
+ },
+ {
+ "name": "messageIndex",
+ "type": "uint32",
+ "internalType": "uint32"
+ }
+ ],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "getDelegatorInfo",
+ "inputs": [
+ {
+ "name": "delegationID",
+ "type": "bytes32",
+ "internalType": "bytes32"
+ }
+ ],
+ "outputs": [
+ {
+ "name": "",
+ "type": "tuple",
+ "internalType": "struct Delegator",
+ "components": [
+ {
+ "name": "status",
+ "type": "uint8",
+ "internalType": "enum DelegatorStatus"
+ },
+ {
+ "name": "owner",
+ "type": "address",
+ "internalType": "address"
+ },
+ {
+ "name": "validationID",
+ "type": "bytes32",
+ "internalType": "bytes32"
+ },
+ {
+ "name": "weight",
+ "type": "uint64",
+ "internalType": "uint64"
+ },
+ {
+ "name": "startTime",
+ "type": "uint64",
+ "internalType": "uint64"
+ },
+ {
+ "name": "startingNonce",
+ "type": "uint64",
+ "internalType": "uint64"
+ },
+ {
+ "name": "endingNonce",
+ "type": "uint64",
+ "internalType": "uint64"
+ }
+ ]
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "getDelegatorRewardInfo",
+ "inputs": [
+ {
+ "name": "delegationID",
+ "type": "bytes32",
+ "internalType": "bytes32"
+ }
+ ],
+ "outputs": [
+ {
+ "name": "",
+ "type": "address",
+ "internalType": "address"
+ },
+ {
+ "name": "",
+ "type": "uint256",
+ "internalType": "uint256"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "getStakingManagerSettings",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "tuple",
+ "internalType": "struct StakingManagerSettings",
+ "components": [
+ {
+ "name": "manager",
+ "type": "address",
+ "internalType": "contract IValidatorManager"
+ },
+ {
+ "name": "minimumStakeAmount",
+ "type": "uint256",
+ "internalType": "uint256"
+ },
+ {
+ "name": "maximumStakeAmount",
+ "type": "uint256",
+ "internalType": "uint256"
+ },
+ {
+ "name": "minimumStakeDuration",
+ "type": "uint64",
+ "internalType": "uint64"
+ },
+ {
+ "name": "minimumDelegationFeeBips",
+ "type": "uint16",
+ "internalType": "uint16"
+ },
+ {
+ "name": "maximumStakeMultiplier",
+ "type": "uint8",
+ "internalType": "uint8"
+ },
+ {
+ "name": "weightToValueFactor",
+ "type": "uint256",
+ "internalType": "uint256"
+ },
+ {
+ "name": "rewardCalculator",
+ "type": "address",
+ "internalType": "contract IRewardCalculator"
+ },
+ {
+ "name": "uptimeBlockchainID",
+ "type": "bytes32",
+ "internalType": "bytes32"
+ }
+ ]
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "getStakingValidator",
+ "inputs": [
+ {
+ "name": "validationID",
+ "type": "bytes32",
+ "internalType": "bytes32"
+ }
+ ],
+ "outputs": [
+ {
+ "name": "",
+ "type": "tuple",
+ "internalType": "struct PoSValidatorInfo",
+ "components": [
+ {
+ "name": "owner",
+ "type": "address",
+ "internalType": "address"
+ },
+ {
+ "name": "delegationFeeBips",
+ "type": "uint16",
+ "internalType": "uint16"
+ },
+ {
+ "name": "minStakeDuration",
+ "type": "uint64",
+ "internalType": "uint64"
+ },
+ {
+ "name": "uptimeSeconds",
+ "type": "uint64",
+ "internalType": "uint64"
+ }
+ ]
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "getValidatorRewardInfo",
+ "inputs": [
+ {
+ "name": "validationID",
+ "type": "bytes32",
+ "internalType": "bytes32"
+ }
+ ],
+ "outputs": [
+ {
+ "name": "",
+ "type": "address",
+ "internalType": "address"
+ },
+ {
+ "name": "",
+ "type": "uint256",
+ "internalType": "uint256"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "initialize",
+ "inputs": [
+ {
+ "name": "settings",
+ "type": "tuple",
+ "internalType": "struct StakingManagerSettings",
+ "components": [
+ {
+ "name": "manager",
+ "type": "address",
+ "internalType": "contract IValidatorManager"
+ },
+ {
+ "name": "minimumStakeAmount",
+ "type": "uint256",
+ "internalType": "uint256"
+ },
+ {
+ "name": "maximumStakeAmount",
+ "type": "uint256",
+ "internalType": "uint256"
+ },
+ {
+ "name": "minimumStakeDuration",
+ "type": "uint64",
+ "internalType": "uint64"
+ },
+ {
+ "name": "minimumDelegationFeeBips",
+ "type": "uint16",
+ "internalType": "uint16"
+ },
+ {
+ "name": "maximumStakeMultiplier",
+ "type": "uint8",
+ "internalType": "uint8"
+ },
+ {
+ "name": "weightToValueFactor",
+ "type": "uint256",
+ "internalType": "uint256"
+ },
+ {
+ "name": "rewardCalculator",
+ "type": "address",
+ "internalType": "contract IRewardCalculator"
+ },
+ {
+ "name": "uptimeBlockchainID",
+ "type": "bytes32",
+ "internalType": "bytes32"
+ }
+ ]
+ },
+ {
+ "name": "token",
+ "type": "address",
+ "internalType": "contract IERC20Mintable"
+ }
+ ],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "initiateDelegatorRegistration",
+ "inputs": [
+ {
+ "name": "validationID",
+ "type": "bytes32",
+ "internalType": "bytes32"
+ },
+ {
+ "name": "delegationAmount",
+ "type": "uint256",
+ "internalType": "uint256"
+ },
+ {
+ "name": "rewardRecipient",
+ "type": "address",
+ "internalType": "address"
+ }
+ ],
+ "outputs": [
+ {
+ "name": "",
+ "type": "bytes32",
+ "internalType": "bytes32"
+ }
+ ],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "initiateDelegatorRemoval",
+ "inputs": [
+ {
+ "name": "delegationID",
+ "type": "bytes32",
+ "internalType": "bytes32"
+ },
+ {
+ "name": "includeUptimeProof",
+ "type": "bool",
+ "internalType": "bool"
+ },
+ {
+ "name": "messageIndex",
+ "type": "uint32",
+ "internalType": "uint32"
+ }
+ ],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "initiateValidatorRegistration",
+ "inputs": [
+ {
+ "name": "nodeID",
+ "type": "bytes",
+ "internalType": "bytes"
+ },
+ {
+ "name": "blsPublicKey",
+ "type": "bytes",
+ "internalType": "bytes"
+ },
+ {
+ "name": "remainingBalanceOwner",
+ "type": "tuple",
+ "internalType": "struct PChainOwner",
+ "components": [
+ {
+ "name": "threshold",
+ "type": "uint32",
+ "internalType": "uint32"
+ },
+ {
+ "name": "addresses",
+ "type": "address[]",
+ "internalType": "address[]"
+ }
+ ]
+ },
+ {
+ "name": "disableOwner",
+ "type": "tuple",
+ "internalType": "struct PChainOwner",
+ "components": [
+ {
+ "name": "threshold",
+ "type": "uint32",
+ "internalType": "uint32"
+ },
+ {
+ "name": "addresses",
+ "type": "address[]",
+ "internalType": "address[]"
+ }
+ ]
+ },
+ {
+ "name": "delegationFeeBips",
+ "type": "uint16",
+ "internalType": "uint16"
+ },
+ {
+ "name": "minStakeDuration",
+ "type": "uint64",
+ "internalType": "uint64"
+ },
+ {
+ "name": "stakeAmount",
+ "type": "uint256",
+ "internalType": "uint256"
+ },
+ {
+ "name": "rewardRecipient",
+ "type": "address",
+ "internalType": "address"
+ }
+ ],
+ "outputs": [
+ {
+ "name": "",
+ "type": "bytes32",
+ "internalType": "bytes32"
+ }
+ ],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "initiateValidatorRemoval",
+ "inputs": [
+ {
+ "name": "validationID",
+ "type": "bytes32",
+ "internalType": "bytes32"
+ },
+ {
+ "name": "includeUptimeProof",
+ "type": "bool",
+ "internalType": "bool"
+ },
+ {
+ "name": "messageIndex",
+ "type": "uint32",
+ "internalType": "uint32"
+ }
+ ],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "resendUpdateDelegator",
+ "inputs": [
+ {
+ "name": "delegationID",
+ "type": "bytes32",
+ "internalType": "bytes32"
+ }
+ ],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "submitUptimeProof",
+ "inputs": [
+ {
+ "name": "validationID",
+ "type": "bytes32",
+ "internalType": "bytes32"
+ },
+ {
+ "name": "messageIndex",
+ "type": "uint32",
+ "internalType": "uint32"
+ }
+ ],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "valueToWeight",
+ "inputs": [
+ {
+ "name": "value",
+ "type": "uint256",
+ "internalType": "uint256"
+ }
+ ],
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint64",
+ "internalType": "uint64"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "weightToValue",
+ "inputs": [
+ {
+ "name": "weight",
+ "type": "uint64",
+ "internalType": "uint64"
+ }
+ ],
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256",
+ "internalType": "uint256"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "event",
+ "name": "CompletedDelegatorRegistration",
+ "inputs": [
+ {
+ "name": "delegationID",
+ "type": "bytes32",
+ "indexed": true,
+ "internalType": "bytes32"
+ },
+ {
+ "name": "validationID",
+ "type": "bytes32",
+ "indexed": true,
+ "internalType": "bytes32"
+ },
+ {
+ "name": "startTime",
+ "type": "uint256",
+ "indexed": false,
+ "internalType": "uint256"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "CompletedDelegatorRemoval",
+ "inputs": [
+ {
+ "name": "delegationID",
+ "type": "bytes32",
+ "indexed": true,
+ "internalType": "bytes32"
+ },
+ {
+ "name": "validationID",
+ "type": "bytes32",
+ "indexed": true,
+ "internalType": "bytes32"
+ },
+ {
+ "name": "rewards",
+ "type": "uint256",
+ "indexed": false,
+ "internalType": "uint256"
+ },
+ {
+ "name": "fees",
+ "type": "uint256",
+ "indexed": false,
+ "internalType": "uint256"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "DelegatorRewardClaimed",
+ "inputs": [
+ {
+ "name": "delegationID",
+ "type": "bytes32",
+ "indexed": true,
+ "internalType": "bytes32"
+ },
+ {
+ "name": "recipient",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ },
+ {
+ "name": "amount",
+ "type": "uint256",
+ "indexed": false,
+ "internalType": "uint256"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "DelegatorRewardRecipientChanged",
+ "inputs": [
+ {
+ "name": "delegationID",
+ "type": "bytes32",
+ "indexed": true,
+ "internalType": "bytes32"
+ },
+ {
+ "name": "recipient",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ },
+ {
+ "name": "oldRecipient",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "Initialized",
+ "inputs": [
+ {
+ "name": "version",
+ "type": "uint64",
+ "indexed": false,
+ "internalType": "uint64"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "InitiatedDelegatorRegistration",
+ "inputs": [
+ {
+ "name": "delegationID",
+ "type": "bytes32",
+ "indexed": true,
+ "internalType": "bytes32"
+ },
+ {
+ "name": "validationID",
+ "type": "bytes32",
+ "indexed": true,
+ "internalType": "bytes32"
+ },
+ {
+ "name": "delegatorAddress",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ },
+ {
+ "name": "nonce",
+ "type": "uint64",
+ "indexed": false,
+ "internalType": "uint64"
+ },
+ {
+ "name": "validatorWeight",
+ "type": "uint64",
+ "indexed": false,
+ "internalType": "uint64"
+ },
+ {
+ "name": "delegatorWeight",
+ "type": "uint64",
+ "indexed": false,
+ "internalType": "uint64"
+ },
+ {
+ "name": "setWeightMessageID",
+ "type": "bytes32",
+ "indexed": false,
+ "internalType": "bytes32"
+ },
+ {
+ "name": "rewardRecipient",
+ "type": "address",
+ "indexed": false,
+ "internalType": "address"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "InitiatedDelegatorRemoval",
+ "inputs": [
+ {
+ "name": "delegationID",
+ "type": "bytes32",
+ "indexed": true,
+ "internalType": "bytes32"
+ },
+ {
+ "name": "validationID",
+ "type": "bytes32",
+ "indexed": true,
+ "internalType": "bytes32"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "InitiatedStakingValidatorRegistration",
+ "inputs": [
+ {
+ "name": "validationID",
+ "type": "bytes32",
+ "indexed": true,
+ "internalType": "bytes32"
+ },
+ {
+ "name": "owner",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ },
+ {
+ "name": "delegationFeeBips",
+ "type": "uint16",
+ "indexed": false,
+ "internalType": "uint16"
+ },
+ {
+ "name": "minStakeDuration",
+ "type": "uint64",
+ "indexed": false,
+ "internalType": "uint64"
+ },
+ {
+ "name": "rewardRecipient",
+ "type": "address",
+ "indexed": false,
+ "internalType": "address"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "UptimeUpdated",
+ "inputs": [
+ {
+ "name": "validationID",
+ "type": "bytes32",
+ "indexed": true,
+ "internalType": "bytes32"
+ },
+ {
+ "name": "uptime",
+ "type": "uint64",
+ "indexed": false,
+ "internalType": "uint64"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "ValidatorRewardClaimed",
+ "inputs": [
+ {
+ "name": "validationID",
+ "type": "bytes32",
+ "indexed": true,
+ "internalType": "bytes32"
+ },
+ {
+ "name": "recipient",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ },
+ {
+ "name": "amount",
+ "type": "uint256",
+ "indexed": false,
+ "internalType": "uint256"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "ValidatorRewardRecipientChanged",
+ "inputs": [
+ {
+ "name": "validationID",
+ "type": "bytes32",
+ "indexed": true,
+ "internalType": "bytes32"
+ },
+ {
+ "name": "recipient",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ },
+ {
+ "name": "oldRecipient",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "error",
+ "name": "AddressEmptyCode",
+ "inputs": [
+ {
+ "name": "target",
+ "type": "address",
+ "internalType": "address"
+ }
+ ]
+ },
+ {
+ "type": "error",
+ "name": "AddressInsufficientBalance",
+ "inputs": [
+ {
+ "name": "account",
+ "type": "address",
+ "internalType": "address"
+ }
+ ]
+ },
+ {
+ "type": "error",
+ "name": "DelegatorIneligibleForRewards",
+ "inputs": [
+ {
+ "name": "delegationID",
+ "type": "bytes32",
+ "internalType": "bytes32"
+ }
+ ]
+ },
+ {
+ "type": "error",
+ "name": "FailedInnerCall",
+ "inputs": []
+ },
+ {
+ "type": "error",
+ "name": "InvalidDelegationFee",
+ "inputs": [
+ {
+ "name": "delegationFeeBips",
+ "type": "uint16",
+ "internalType": "uint16"
+ }
+ ]
+ },
+ {
+ "type": "error",
+ "name": "InvalidDelegationID",
+ "inputs": [
+ {
+ "name": "delegationID",
+ "type": "bytes32",
+ "internalType": "bytes32"
+ }
+ ]
+ },
+ {
+ "type": "error",
+ "name": "InvalidDelegatorStatus",
+ "inputs": [
+ {
+ "name": "status",
+ "type": "uint8",
+ "internalType": "enum DelegatorStatus"
+ }
+ ]
+ },
+ {
+ "type": "error",
+ "name": "InvalidInitialization",
+ "inputs": []
+ },
+ {
+ "type": "error",
+ "name": "InvalidMinStakeDuration",
+ "inputs": [
+ {
+ "name": "minStakeDuration",
+ "type": "uint64",
+ "internalType": "uint64"
+ }
+ ]
+ },
+ {
+ "type": "error",
+ "name": "InvalidNonce",
+ "inputs": [
+ {
+ "name": "nonce",
+ "type": "uint64",
+ "internalType": "uint64"
+ }
+ ]
+ },
+ {
+ "type": "error",
+ "name": "InvalidRewardRecipient",
+ "inputs": [
+ {
+ "name": "rewardRecipient",
+ "type": "address",
+ "internalType": "address"
+ }
+ ]
+ },
+ {
+ "type": "error",
+ "name": "InvalidStakeAmount",
+ "inputs": [
+ {
+ "name": "stakeAmount",
+ "type": "uint256",
+ "internalType": "uint256"
+ }
+ ]
+ },
+ {
+ "type": "error",
+ "name": "InvalidStakeMultiplier",
+ "inputs": [
+ {
+ "name": "maximumStakeMultiplier",
+ "type": "uint8",
+ "internalType": "uint8"
+ }
+ ]
+ },
+ {
+ "type": "error",
+ "name": "InvalidUptimeBlockchainID",
+ "inputs": [
+ {
+ "name": "uptimeBlockchainID",
+ "type": "bytes32",
+ "internalType": "bytes32"
+ }
+ ]
+ },
+ {
+ "type": "error",
+ "name": "InvalidValidatorStatus",
+ "inputs": [
+ {
+ "name": "status",
+ "type": "uint8",
+ "internalType": "enum ValidatorStatus"
+ }
+ ]
+ },
+ {
+ "type": "error",
+ "name": "InvalidWarpMessage",
+ "inputs": []
+ },
+ {
+ "type": "error",
+ "name": "InvalidWarpOriginSenderAddress",
+ "inputs": [
+ {
+ "name": "senderAddress",
+ "type": "address",
+ "internalType": "address"
+ }
+ ]
+ },
+ {
+ "type": "error",
+ "name": "InvalidWarpSourceChainID",
+ "inputs": [
+ {
+ "name": "sourceChainID",
+ "type": "bytes32",
+ "internalType": "bytes32"
+ }
+ ]
+ },
+ {
+ "type": "error",
+ "name": "MaxWeightExceeded",
+ "inputs": [
+ {
+ "name": "newValidatorWeight",
+ "type": "uint64",
+ "internalType": "uint64"
+ }
+ ]
+ },
+ {
+ "type": "error",
+ "name": "MinStakeDurationNotPassed",
+ "inputs": [
+ {
+ "name": "endTime",
+ "type": "uint64",
+ "internalType": "uint64"
+ }
+ ]
+ },
+ {
+ "type": "error",
+ "name": "NotInitializing",
+ "inputs": []
+ },
+ {
+ "type": "error",
+ "name": "ReentrancyGuardReentrantCall",
+ "inputs": []
+ },
+ {
+ "type": "error",
+ "name": "SafeERC20FailedOperation",
+ "inputs": [
+ {
+ "name": "token",
+ "type": "address",
+ "internalType": "address"
+ }
+ ]
+ },
+ {
+ "type": "error",
+ "name": "UnauthorizedOwner",
+ "inputs": [
+ {
+ "name": "sender",
+ "type": "address",
+ "internalType": "address"
+ }
+ ]
+ },
+ {
+ "type": "error",
+ "name": "UnexpectedValidationID",
+ "inputs": [
+ {
+ "name": "validationID",
+ "type": "bytes32",
+ "internalType": "bytes32"
+ },
+ {
+ "name": "expectedValidationID",
+ "type": "bytes32",
+ "internalType": "bytes32"
+ }
+ ]
+ },
+ {
+ "type": "error",
+ "name": "ValidatorIneligibleForRewards",
+ "inputs": [
+ {
+ "name": "validationID",
+ "type": "bytes32",
+ "internalType": "bytes32"
+ }
+ ]
+ },
+ {
+ "type": "error",
+ "name": "ValidatorNotPoS",
+ "inputs": [
+ {
+ "name": "validationID",
+ "type": "bytes32",
+ "internalType": "bytes32"
+ }
+ ]
+ },
+ {
+ "type": "error",
+ "name": "ZeroAddress",
+ "inputs": []
+ },
+ {
+ "type": "error",
+ "name": "ZeroWeightToValueFactor",
+ "inputs": []
+ }
+ ],
+ "bytecode": {
+ "object": "0x608060405234801561000f575f80fd5b506040516144cd3803806144cd83398101604081905261002e91610107565b60018160018111156100425761004261012c565b0361004f5761004f610055565b50610140565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000900460ff16156100a55760405163f92ee8a960e01b815260040160405180910390fd5b80546001600160401b03908116146101045780546001600160401b0319166001600160401b0390811782556040519081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50565b5f60208284031215610117575f80fd5b815160028110610125575f80fd5b9392505050565b634e487b7160e01b5f52602160045260245ffd5b6143808061014d5f395ff3fe608060405234801561000f575f80fd5b50600436106101d1575f3560e01c80637e65f4da116100fe578063b2c1712e1161009e578063cd236e7f1161006e578063cd236e7f14610495578063e24b2680146104a8578063e4a63c40146104bb578063fb8b11dd146104cf575f80fd5b8063b2c1712e1461044c578063b5c934981461045f578063b771b3bc14610472578063caa7187414610480575f80fd5b80639681d940116100d95780639681d940146103f4578063a3a65e4814610407578063a9778a7a146102f3578063af1dd66c1461041a575f80fd5b80637e65f4da146103bb5780638ef34c98146103ce57806393e24598146103e1575f80fd5b80632aa566381161017457806360ad77841161014457806360ad77841461032f5780636206585614610342578063785e9e86146103635780637a63ad8514610394575f80fd5b80632aa56638146102b55780632e2194d8146102c857806335455ded146102f357806353a133381461030f575f80fd5b8063245dafcb116101af578063245dafcb1461021c57806325e1c7761461022f5780632674874b1461024257806327bf60cd146102a2575f80fd5b806313409645146101d5578063151d30d1146101ea5780631667956414610209575b5f80fd5b6101e86101e336600461384e565b6104e2565b005b6101f2600a81565b60405160ff90911681526020015b60405180910390f35b6101e8610217366004613885565b610822565b6101e861022a3660046138c0565b610833565b6101e861023d36600461384e565b610af7565b6102556102503660046138c0565b610bd5565b6040805182516001600160a01b0316815260208084015161ffff1690820152828201516001600160401b039081169282019290925260609283015190911691810191909152608001610200565b6101e86102b0366004613885565b610c61565b6101e86102c3366004613885565b610c6c565b6102db6102d63660046138c0565b610c7c565b6040516001600160401b039091168152602001610200565b6102fc61271081565b60405161ffff9091168152602001610200565b61032261031d3660046138c0565b610cd0565b60405161020091906138ff565b6101e861033d36600461384e565b610dbd565b61035561035036600461398d565b6110df565b604051908152602001610200565b5f80516020614334833981519152546001600160a01b03165b6040516001600160a01b039091168152602001610200565b6103557fafe6c4731b852fc2be89a0896ae43d22d8b24989064d841b2a1586b4d39ab60081565b6103556103c9366004613ba8565b6110ff565b6101e86103dc366004613c87565b61113c565b6101e86103ef3660046138c0565b61121e565b610355610402366004613cb5565b611337565b610355610415366004613cb5565b6114d8565b61042d6104283660046138c0565b611550565b604080516001600160a01b039093168352602083019190915201610200565b6101e861045a366004613885565b61158c565b6101e861046d366004613cce565b611597565b61037c6005600160991b0181565b6104886116a5565b6040516102009190613d01565b6103556104a3366004613da2565b611781565b61042d6104b63660046138c0565b6117b5565b6103555f8051602061433483398151915281565b6101e86104dd366004613c87565b6117f1565b6104ea6118b9565b5f6104f36118f0565b5f848152600882016020526040808220815160e0810190925280549394509192909190829060ff16600381111561052c5761052c6138d7565b600381111561053d5761053d6138d7565b8152815461010090046001600160a01b03166020820152600182015460408201526002909101546001600160401b038082166060840152600160401b820481166080840152600160801b8204811660a0840152600160c01b9091041660c09091015290506003815160038111156105b6576105b66138d7565b146105e0578051604051633b0d540d60e21b81526105d79190600401613dd8565b60405180910390fd5b81546040828101519051636af907fb60e11b815260048101919091525f916001600160a01b03169063d5f20ff6906024015f60405180830381865afa15801561062b573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526106529190810190613e6b565b9050600483546040808501519051636af907fb60e11b81526001600160a01b039092169163d5f20ff69161068c9160040190815260200190565b5f60405180830381865afa1580156106a6573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526106cd9190810190613e6b565b5160058111156106df576106df6138d7565b1415801561070657508160c001516001600160401b031681608001516001600160401b0316105b156107fc57825460405163338587c560e21b815263ffffffff861660048201525f9182916001600160a01b039091169063ce161f149060240160408051808303815f875af115801561075a573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061077e9190613f4a565b91509150818460400151146107b75781846040015160405163fee3144560e01b81526004016105d7929190918252602082015260400190565b806001600160401b03168460c001516001600160401b031611156107f957604051632e19bc2d60e11b81526001600160401b03821660048201526024016105d7565b50505b61080585611914565b50505061081e60015f8051602061435483398151915255565b5050565b61082d838383611b58565b50505050565b5f61083c6118f0565b5f838152600882016020526040808220815160e0810190925280549394509192909190829060ff166003811115610875576108756138d7565b6003811115610886576108866138d7565b8152815461010090046001600160a01b0316602082015260018083015460408301526002909201546001600160401b038082166060840152600160401b820481166080840152600160801b8204811660a0840152600160c01b9091041660c090910152909150815160038111156108ff576108ff6138d7565b14158015610920575060038151600381111561091d5761091d6138d7565b14155b15610941578051604051633b0d540d60e21b81526105d79190600401613dd8565b81546040828101519051636af907fb60e11b815260048101919091525f916001600160a01b03169063d5f20ff6906024015f60405180830381865afa15801561098c573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526109b39190810190613e6b565b905080606001516001600160401b03165f036109e5576040516339b894f960e21b8152600481018590526024016105d7565b604080830151606083015160a0840151925163854a893f60e01b81526005600160991b019363ee5b48eb9373__$fd0c147b4031eef6079b0498cbafa865f0$__9363854a893f93610a5393906004019283526001600160401b03918216602084015216604082015260600190565b5f60405180830381865af4158015610a6d573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052610a949190810190613f6d565b6040518263ffffffff1660e01b8152600401610ab09190613fc9565b6020604051808303815f875af1158015610acc573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610af09190613fdb565b5050505050565b610b0082611dfd565b610b20576040516330efa98b60e01b8152600481018390526024016105d7565b5f610b296118f0565b54604051636af907fb60e11b8152600481018590526001600160a01b039091169063d5f20ff6906024015f60405180830381865afa158015610b6d573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052610b949190810190613e6b565b5190506002816005811115610bab57610bab6138d7565b14610bcb578060405163170cc93360e21b81526004016105d79190613ff2565b61082d8383611e26565b604080516080810182525f808252602082018190529181018290526060810191909152610c006118f0565b5f9283526007016020908152604092839020835160808101855281546001600160a01b038116825261ffff600160a01b820416938201939093526001600160401b03600160b01b909304831694810194909452600101541660608301525090565b61082d838383612090565b610c778383836124b1565b505050565b5f80610c866118f0565b60040154610c949084614020565b9050801580610ca957506001600160401b0381115b15610cca5760405163222d164360e21b8152600481018490526024016105d7565b92915050565b6040805160e0810182525f80825260208201819052918101829052606081018290526080810182905260a0810182905260c0810191909152610d106118f0565b5f838152600891909101602052604090819020815160e081019092528054829060ff166003811115610d4457610d446138d7565b6003811115610d5557610d556138d7565b8152815461010090046001600160a01b03166020820152600182015460408201526002909101546001600160401b038082166060840152600160401b820481166080840152600160801b8204811660a0840152600160c01b9091041660c09091015292915050565b5f610dc66118f0565b5f848152600882016020526040808220815160e0810190925280549394509192909190829060ff166003811115610dff57610dff6138d7565b6003811115610e1057610e106138d7565b8152815461010090046001600160a01b03908116602083015260018301546040808401919091526002909301546001600160401b038082166060850152600160401b820481166080850152600160801b8204811660a0850152600160c01b9091041660c0909201919091528282015185549251636af907fb60e11b815260048101829052939450925f929091169063d5f20ff6906024015f60405180830381865afa158015610ec1573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052610ee89190810190613e6b565b9050600183516003811115610eff57610eff6138d7565b14610f20578251604051633b0d540d60e21b81526105d79190600401613dd8565b600481516005811115610f3557610f356138d7565b03610f4b57610f4386611914565b505050505050565b8260a001516001600160401b031681608001516001600160401b0316101561105357835460405163338587c560e21b815263ffffffff871660048201525f9182916001600160a01b039091169063ce161f149060240160408051808303815f875af1158015610fbc573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610fe09190613f4a565b9150915081841461100e5760405163fee3144560e01b815260048101839052602481018590526044016105d7565b8460a001516001600160401b0316816001600160401b0316101561105057604051632e19bc2d60e11b81526001600160401b03821660048201526024016105d7565b50505b5f868152600885016020908152604091829020805460ff1916600290811782550180546001600160401b034216600160401b81026fffffffffffffffff000000000000000019909216919091179091559151918252839188917f3886b7389bccb22cac62838dee3f400cf8b22289295283e01a2c7093f93dd5aa910160405180910390a3505050505050565b5f6110e86118f0565b60040154610cca906001600160401b03841661403f565b5f6111086118b9565b61111889898989898989896124dc565b905061113060015f8051602061435483398151915255565b98975050505050505050565b5f6111456118f0565b90506001600160a01b0382166111795760405163caa903f960e01b81526001600160a01b03831660048201526024016105d7565b5f8381526007820160205260409020546001600160a01b031633146111bf57335b604051636e2ccd7560e11b81526001600160a01b0390911660048201526024016105d7565b5f838152600c8201602052604080822080546001600160a01b038681166001600160a01b0319831681179093559251921692839287917f28c6fc4db51556a07b41aa23b91cedb22c02a7560c431a31255c03ca6ad61c3391a450505050565b5f6112276118f0565b8054604051636af907fb60e11b8152600481018590529192505f916001600160a01b039091169063d5f20ff6906024015f60405180830381865afa158015611271573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526112989190810190613e6b565b51905060048160058111156112af576112af6138d7565b146112cf578060405163170cc93360e21b81526004016105d79190613ff2565b5f8381526007830160205260409020546001600160a01b031633146112f4573361119a565b5f838152600c830160205260409020546001600160a01b03168061132d57505f8381526007830160205260409020546001600160a01b03165b61082d8185612813565b5f6113406118b9565b5f6113496118f0565b805460405163025a076560e61b815263ffffffff861660048201529192505f916001600160a01b0390911690639681d940906024016020604051808303815f875af115801561139a573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906113be9190613fdb565b8254604051636af907fb60e11b8152600481018390529192505f916001600160a01b039091169063d5f20ff6906024015f60405180830381865afa158015611408573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f1916820160405261142f9190810190613e6b565b905061143a82611dfd565b611448575091506114bd9050565b5f828152600784016020908152604080832054600c8701909252909120546001600160a01b0391821691168061147b5750805b600483516005811115611490576114906138d7565b0361149f5761149f8185612813565b6114b5826114b085604001516110df565b612887565b509193505050505b6114d360015f8051602061435483398151915255565b919050565b5f6114e16118f0565b54604051631474cbc960e31b815263ffffffff841660048201526001600160a01b039091169063a3a65e48906024016020604051808303815f875af115801561152c573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610cca9190613fdb565b5f805f61155b6118f0565b5f948552600a810160209081526040808720546009909301909152909420546001600160a01b039094169492505050565b610c778383836128aa565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a008054600160401b810460ff1615906001600160401b03165f811580156115db5750825b90505f826001600160401b031660011480156115f65750303b155b905081158015611604575080155b156116225760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff19166001178555831561164c57845460ff60401b1916600160401b1785555b61165687876128d5565b831561169c57845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50505050505050565b60408051610120810182525f80825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e081018290526101008101829052906116f56118f0565b604080516101208101825282546001600160a01b0390811682526001840154602083015260028401549282019290925260038301546001600160401b0381166060830152600160401b810461ffff166080830152600160501b900460ff1660a0820152600483015460c0820152600583015490911660e082015260069091015461010082015292915050565b5f61178a6118b9565b611796843385856128ef565b90506117ae60015f8051602061435483398151915255565b9392505050565b5f805f6117c06118f0565b5f948552600c81016020908152604080872054600b909301909152909420546001600160a01b039094169492505050565b6001600160a01b0381166118235760405163caa903f960e01b81526001600160a01b03821660048201526024016105d7565b5f61182c6118f0565b5f8481526008820160205260409020549091506001600160a01b0361010090910416331461185a573361119a565b5f838152600a8201602052604080822080546001600160a01b038681166001600160a01b0319831681179093559251921692839287917f6b30f219ab3cc1c43b394679707f3856ff2f3c6f1f6c97f383c6b16687a1e00591a450505050565b5f805160206143548339815191528054600119016118ea57604051633ee5aeb560e01b815260040160405180910390fd5b60029055565b7fafe6c4731b852fc2be89a0896ae43d22d8b24989064d841b2a1586b4d39ab60090565b5f61191d6118f0565b5f838152600882016020526040808220815160e0810190925280549394509192909190829060ff166003811115611956576119566138d7565b6003811115611967576119676138d7565b815281546001600160a01b03610100909104811660208084019190915260018401546040808501919091526002909401546001600160401b038082166060860152600160401b820481166080860152600160801b8204811660a0860152600160c01b9091041660c09093019290925283830151865484516304e0efb360e11b8152945195965090949116926309c1df669260048083019391928290030181865afa158015611a17573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611a3b9190614056565b8260800151611a4a9190614071565b6001600160401b0316421015611a7e5760405163fb6ce63f60e01b81526001600160401b03421660048201526024016105d7565b5f848152600884016020908152604080832080546001600160a81b031916815560018101849055600201839055600a8601909152902080546001600160a01b031981169091556001600160a01b031680611ad9575060208201515b5f80611ae6838886612d39565b91509150611aff85602001516114b087606001516110df565b6040805183815260208101839052859189917f5ecc5b26a9265302cf871229b3d983e5ca57dbb1448966c6c58b2d3c68bc7f7e910160405180910390a350505050505050565b60015f8051602061435483398151915255565b5f80611b626118f0565b8054604051635b73516560e11b8152600481018890529192506001600160a01b03169063b6e6a2ca906024015f604051808303815f87803b158015611ba5575f80fd5b505af1158015611bb7573d5f803e3d5ffd5b50508254604051636af907fb60e11b8152600481018990525f93506001600160a01b03909116915063d5f20ff6906024015f60405180830381865afa158015611c02573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052611c299190810190613e6b565b9050611c3486611dfd565b611c43576001925050506117ae565b5f8681526007830160205260409020546001600160a01b03163314611c68573361119a565b5f86815260078301602052604090205460c0820151611c9791600160b01b90046001600160401b031690614071565b6001600160401b03168160e001516001600160401b03161015611cde5760e081015160405163fb6ce63f60e01b81526001600160401b0390911660048201526024016105d7565b5f8515611cf657611cef8786611e26565b9050611d14565b505f8681526007830160205260409020600101546001600160401b03165b600583015460408301515f916001600160a01b031690634f22429f90611d39906110df565b60c086015160e0808801516040519185901b6001600160e01b031916825260048201939093526001600160401b0391821660248201819052604482015291811660648301528516608482015260a401602060405180830381865afa158015611da3573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611dc79190613fdb565b90508084600b015f8a81526020019081526020015f205f828254611deb9190614098565b90915550501515979650505050505050565b5f80611e076118f0565b5f938452600701602052505060409020546001600160a01b0316151590565b6040516306f8253560e41b815263ffffffff821660048201525f90819081906005600160991b0190636f825350906024015f60405180830381865afa158015611e71573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052611e9891908101906140ab565b9150915080611eba57604051636b2f19e960e01b815260040160405180910390fd5b5f611ec36118f0565b6006810154845191925014611ef1578251604051636ba589a560e01b815260048101919091526024016105d7565b60208301516001600160a01b031615611f2d576020830151604051624de75d60e31b81526001600160a01b0390911660048201526024016105d7565b5f8073__$fd0c147b4031eef6079b0498cbafa865f0$__63088c246386604001516040518263ffffffff1660e01b8152600401611f6a9190613fc9565b6040805180830381865af4158015611f84573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611fa89190613f4a565b91509150818814611fd65760405163fee3144560e01b815260048101839052602481018990526044016105d7565b5f8881526007840160205260409020600101546001600160401b039081169082161115612067575f888152600784016020908152604091829020600101805467ffffffffffffffff19166001600160401b038516908117909155915191825289917fec44148e8ff271f2d0bacef1142154abacb0abb3a29eb3eb50e2ca97e86d0435910160405180910390a2612085565b505f8781526007830160205260409020600101546001600160401b03165b979650505050505050565b5f8061209a6118f0565b5f868152600882016020526040808220815160e0810190925280549394509192909190829060ff1660038111156120d3576120d36138d7565b60038111156120e4576120e46138d7565b8152815461010090046001600160a01b03908116602083015260018301546040808401919091526002909301546001600160401b038082166060850152600160401b820481166080850152600160801b8204811660a0850152600160c01b9091041660c0909201919091528282015185549251636af907fb60e11b815260048101829052939450925f929091169063d5f20ff6906024015f60405180830381865afa158015612195573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526121bc9190810190613e6b565b90506002835160038111156121d3576121d36138d7565b146121f4578251604051633b0d540d60e21b81526105d79190600401613dd8565b60208301516001600160a01b03163314612290575f8281526007850160205260409020546001600160a01b0316331461222d573361119a565b5f82815260078501602052604090205460c082015161225c91600160b01b90046001600160401b031690614071565b6001600160401b03164210156122905760405163fb6ce63f60e01b81526001600160401b03421660048201526024016105d7565b5f888152600a850160205260409020546001600160a01b03166002825160058111156122be576122be6138d7565b0361245857600385015460808501516122e0916001600160401b031690614071565b6001600160401b03164210156123145760405163fb6ce63f60e01b81526001600160401b03421660048201526024016105d7565b8715612326576123248388611e26565b505b5f8981526008860160205260409020805460ff191660031790558454606085015160a08401516001600160a01b0390921691636610966991869161236a9190614151565b6040516001600160e01b031960e085901b16815260048101929092526001600160401b0316602482015260440160408051808303815f875af11580156123b2573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906123d69190614171565b505f8a8152600887016020526040812060020180546001600160401b03909316600160c01b026001600160c01b039093169290921790915561241985838c612e38565b9050838a7f5abe543af12bb7f76f6fa9daaa9d95d181c5e90566df58d3c012216b6245eeaf60405160405180910390a3151595506117ae945050505050565b60048251600581111561246d5761246d6138d7565b036124955761247d84828b612e38565b5061248789611914565b6001955050505050506117ae565b815160405163170cc93360e21b81526105d79190600401613ff2565b6124bc838383612090565b610c7757604051631036cf9160e11b8152600481018490526024016105d7565b5f806124e66118f0565b600381015490915061ffff600160401b9091048116908716108061250f575061271061ffff8716115b1561253357604051635f12e6c360e11b815261ffff871660048201526024016105d7565b60038101546001600160401b03908116908616101561256f576040516202a06d60e11b81526001600160401b03861660048201526024016105d7565b80600101548410806125845750806002015484115b156125a55760405163222d164360e21b8152600481018590526024016105d7565b6001600160a01b0383166125d75760405163caa903f960e01b81526001600160a01b03841660048201526024016105d7565b5f6125e185613072565b90505f6125ed82610c7c565b90505f835f015f9054906101000a90046001600160a01b03166001600160a01b0316639cb7624e8e8e8e8e876040518663ffffffff1660e01b8152600401612639959493929190614203565b6020604051808303815f875af1158015612655573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906126799190613fdb565b90505f33905080856007015f8481526020019081526020015f205f015f6101000a8154816001600160a01b0302191690836001600160a01b0316021790555089856007015f8481526020019081526020015f205f0160146101000a81548161ffff021916908361ffff16021790555088856007015f8481526020019081526020015f205f0160166101000a8154816001600160401b0302191690836001600160401b031602179055505f856007015f8481526020019081526020015f206001015f6101000a8154816001600160401b0302191690836001600160401b031602179055508685600c015f8481526020019081526020015f205f6101000a8154816001600160a01b0302191690836001600160a01b03160217905550806001600160a01b0316827ff51ab9b5253693af2f675b23c4042ccac671873d5f188e405b30019f4c159b7f8c8c8b6040516127fa9392919061ffff9390931683526001600160401b039190911660208301526001600160a01b0316604082015260600190565b60405180910390a3509c9b505050505050505050505050565b5f61281c6118f0565b5f838152600b820160205260408120805491905590915061283d8482613095565b836001600160a01b0316837f875feb58aa30eeee040d55b00249c5c8c5af4f27c95cd29d64180ad67400c6e48360405161287991815260200190565b60405180910390a350505050565b5f805160206143348339815191525461081e906001600160a01b03168383613102565b6128b5838383611b58565b610c7757604051635bff683f60e11b8152600481018490526024016105d7565b6128dd613161565b6128e6826131ac565b61081e8161322a565b5f806128f96118f0565b90505f6129086102d686613072565b905061291387611dfd565b612933576040516330efa98b60e01b8152600481018890526024016105d7565b6001600160a01b0384166129655760405163caa903f960e01b81526001600160a01b03851660048201526024016105d7565b8154604051636af907fb60e11b8152600481018990525f9182916001600160a01b039091169063d5f20ff6906024015f60405180830381865afa1580156129ae573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526129d59190810190613e6b565b9050828160a001516129e79190614071565b915083600301600a9054906101000a90046001600160401b03168160400151612a10919061426b565b6001600160401b0316826001600160401b03161115612a4d57604051636d51fe0560e11b81526001600160401b03831660048201526024016105d7565b508254604051636610966960e01b8152600481018a90526001600160401b03831660248201525f9182916001600160a01b039091169063661096699060440160408051808303815f875af1158015612aa7573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612acb9190614171565b915091505f8a83604051602001612af992919091825260c01b6001600160c01b031916602082015260280190565b60408051601f1981840301815291815281516020928301205f81815260088a019093529120805491925060019160ff19168280021790555089866008015f8381526020019081526020015f205f0160016101000a8154816001600160a01b0302191690836001600160a01b031602179055508a866008015f8381526020019081526020015f206001018190555084866008015f8381526020019081526020015f206002015f6101000a8154816001600160401b0302191690836001600160401b031602179055505f866008015f8381526020019081526020015f2060020160086101000a8154816001600160401b0302191690836001600160401b0316021790555082866008015f8381526020019081526020015f2060020160106101000a8154816001600160401b0302191690836001600160401b031602179055505f866008015f8381526020019081526020015f2060020160186101000a8154816001600160401b0302191690836001600160401b031602179055508786600a015f8381526020019081526020015f205f6101000a8154816001600160a01b0302191690836001600160a01b03160217905550896001600160a01b03168b827f77499a5603260ef2b34698d88b31f7b1acf28c7b134ad4e3fa636501e6064d7786888a888f604051612d239594939291906001600160401b039586168152938516602085015291909316604083015260608201929092526001600160a01b0391909116608082015260a00190565b60405180910390a49a9950505050505050505050565b5f805f612d446118f0565b5f8681526009820160205260408120549192509081908015612e2a575f88815260098501602090815260408083208390558983526007870190915290205461271090612d9b90600160a01b900461ffff168361403f565b612da59190614020565b91508184600b015f8981526020019081526020015f205f828254612dc99190614098565b90915550612dd990508282614296565b9250612de58984613095565b886001600160a01b0316887f3ffc31181aadb250503101bd718e5fce8c27650af8d3525b9f60996756efaf6385604051612e2191815260200190565b60405180910390a35b509097909650945050505050565b5f80612e426118f0565b80546040808801519051636af907fb60e11b81529293505f926001600160a01b039092169163d5f20ff691612e7d9160040190815260200190565b5f60405180830381865afa158015612e97573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052612ebe9190810190613e6b565b90505f600382516005811115612ed657612ed66138d7565b1480612ef45750600482516005811115612ef257612ef26138d7565b145b15612f04575060e0810151612f21565b600282516005811115612f1957612f196138d7565b036124955750425b86608001516001600160401b0316816001600160401b031611612f49575f93505050506117ae565b600583015460608801515f916001600160a01b031690634f22429f90612f6e906110df565b60c086015160808c01516040808e01515f90815260078b0160205281902060010154905160e086901b6001600160e01b031916815260048101949094526001600160401b0392831660248501529082166044840152818716606484015216608482015260a401602060405180830381865afa158015612fef573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906130139190613fdb565b90506001600160a01b03871661302b57876020015196505b5f8681526009850160209081526040808320849055600a90960190529390932080546001600160a01b0388166001600160a01b031990911617905550909150509392505050565b5f610cca825f80516020614334833981519152546001600160a01b031690613287565b5f5f8051602061433483398151915280546040516340c10f1960e01b81526001600160a01b038681166004830152602482018690529293509116906340c10f19906044015f604051808303815f87803b1580156130f0575f80fd5b505af115801561169c573d5f803e3d5ffd5b6040516001600160a01b03838116602483015260448201839052610c7791859182169063a9059cbb906064015b604051602081830303815290604052915060e01b6020820180516001600160e01b038381831617835250505050613293565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054600160401b900460ff166131aa57604051631afcd79f60e31b815260040160405180910390fd5b565b6131b4613161565b6131bc6132f4565b6132276131cc60208301836142a9565b602083013560408401356131e6608086016060870161398d565b6131f660a08701608088016142c4565b61320660c0880160a089016142dd565b60c088013561321c6101008a0160e08b016142a9565b896101000135613304565b50565b613232613161565b5f805160206143348339815191526001600160a01b0382166132675760405163d92e233d60e01b815260040160405180910390fd5b80546001600160a01b0319166001600160a01b0392909216919091179055565b5f6117ae83338461357b565b5f6132a76001600160a01b038416836136de565b905080515f141580156132cb5750808060200190518101906132c991906142fd565b155b15610c7757604051635274afe760e01b81526001600160a01b03841660048201526024016105d7565b6132fc613161565b6131aa6136eb565b61330c613161565b5f6133156118f0565b905061ffff8616158061332d575061271061ffff8716115b1561335157604051635f12e6c360e11b815261ffff871660048201526024016105d7565b878911156133755760405163222d164360e21b8152600481018a90526024016105d7565b60ff851615806133885750600a60ff8616115b156133ab5760405163170db35960e31b815260ff861660048201526024016105d7565b6001600160a01b038a166133d25760405163d92e233d60e01b815260040160405180910390fd5b6001600160a01b0383166133f95760405163d92e233d60e01b815260040160405180910390fd5b896001600160a01b03166309c1df666040518163ffffffff1660e01b8152600401602060405180830381865afa158015613435573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906134599190614056565b6001600160401b0316876001600160401b03161015613495576040516202a06d60e11b81526001600160401b03881660048201526024016105d7565b835f036134b55760405163a733007160e01b815260040160405180910390fd5b816134d657604051632f6bd1db60e01b8152600481018390526024016105d7565b80546001600160a01b039a8b166001600160a01b031991821617825560018201999099556002810197909755600387018054600160501b60ff9096169590950267ffffffffffffffff60501b1961ffff909716600160401b0269ffffffffffffffffffff199096166001600160401b03909816979097179490941794909416949094179091556004840155600583018054929095169190931617909255600690910155565b6040516370a0823160e01b81523060048201525f9081906001600160a01b038616906370a0823190602401602060405180830381865afa1580156135c1573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906135e59190613fdb565b90506135fc6001600160a01b0386168530866136f3565b6040516370a0823160e01b81523060048201525f906001600160a01b038716906370a0823190602401602060405180830381865afa158015613640573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906136649190613fdb565b90508181116136ca5760405162461bcd60e51b815260206004820152602c60248201527f5361666545524332305472616e7366657246726f6d3a2062616c616e6365206e60448201526b1bdd081a5b98dc99585cd95960a21b60648201526084016105d7565b6136d48282614296565b9695505050505050565b60606117ae83835f61372c565b611b45613161565b6040516001600160a01b03848116602483015283811660448301526064820183905261082d9186918216906323b872dd9060840161312f565b6060814710156137515760405163cd78605960e01b81523060048201526024016105d7565b5f80856001600160a01b0316848660405161376c9190614318565b5f6040518083038185875af1925050503d805f81146137a6576040519150601f19603f3d011682016040523d82523d5f602084013e6137ab565b606091505b50915091506136d48683836060826137cb576137c682613812565b6117ae565b81511580156137e257506001600160a01b0384163b155b1561380b57604051639996b31560e01b81526001600160a01b03851660048201526024016105d7565b50806117ae565b8051156138225780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b803563ffffffff811681146114d3575f80fd5b5f806040838503121561385f575f80fd5b8235915061386f6020840161383b565b90509250929050565b8015158114613227575f80fd5b5f805f60608486031215613897575f80fd5b8335925060208401356138a981613878565b91506138b76040850161383b565b90509250925092565b5f602082840312156138d0575f80fd5b5035919050565b634e487b7160e01b5f52602160045260245ffd5b600481106138fb576138fb6138d7565b9052565b5f60e0820190506139118284516138eb565b60018060a01b0360208401511660208301526040830151604083015260608301516001600160401b0380821660608501528060808601511660808501528060a08601511660a08501528060c08601511660c0850152505092915050565b6001600160401b0381168114613227575f80fd5b80356114d38161396e565b5f6020828403121561399d575f80fd5b81356117ae8161396e565b634e487b7160e01b5f52604160045260245ffd5b604080519081016001600160401b03811182821017156139de576139de6139a8565b60405290565b60405161010081016001600160401b03811182821017156139de576139de6139a8565b604051601f8201601f191681016001600160401b0381118282101715613a2f57613a2f6139a8565b604052919050565b5f6001600160401b03821115613a4f57613a4f6139a8565b50601f01601f191660200190565b5f82601f830112613a6c575f80fd5b8135613a7f613a7a82613a37565b613a07565b818152846020838601011115613a93575f80fd5b816020850160208301375f918101602001919091529392505050565b6001600160a01b0381168114613227575f80fd5b80356114d381613aaf565b5f60408284031215613ade575f80fd5b613ae66139bc565b9050613af18261383b565b81526020808301356001600160401b0380821115613b0d575f80fd5b818501915085601f830112613b20575f80fd5b813581811115613b3257613b326139a8565b8060051b9150613b43848301613a07565b8181529183018401918481019088841115613b5c575f80fd5b938501935b83851015613b865784359250613b7683613aaf565b8282529385019390850190613b61565b808688015250505050505092915050565b803561ffff811681146114d3575f80fd5b5f805f805f805f80610100898b031215613bc0575f80fd5b88356001600160401b0380821115613bd6575f80fd5b613be28c838d01613a5d565b995060208b0135915080821115613bf7575f80fd5b613c038c838d01613a5d565b985060408b0135915080821115613c18575f80fd5b613c248c838d01613ace565b975060608b0135915080821115613c39575f80fd5b50613c468b828c01613ace565b955050613c5560808a01613b97565b9350613c6360a08a01613982565b925060c08901359150613c7860e08a01613ac3565b90509295985092959890939650565b5f8060408385031215613c98575f80fd5b823591506020830135613caa81613aaf565b809150509250929050565b5f60208284031215613cc5575f80fd5b6117ae8261383b565b5f80828403610140811215613ce1575f80fd5b61012080821215613cf0575f80fd5b8493508301359050613caa81613aaf565b81516001600160a01b031681526020808301519082015260408083015190820152606080830151610120830191613d42908401826001600160401b03169052565b506080830151613d58608084018261ffff169052565b5060a0830151613d6d60a084018260ff169052565b5060c083015160c083015260e0830151613d9260e08401826001600160a01b03169052565b5061010092830151919092015290565b5f805f60608486031215613db4575f80fd5b83359250602084013591506040840135613dcd81613aaf565b809150509250925092565b60208101610cca82846138eb565b8051600681106114d3575f80fd5b5f5b83811015613e0e578181015183820152602001613df6565b50505f910152565b5f82601f830112613e25575f80fd5b8151613e33613a7a82613a37565b818152846020838601011115613e47575f80fd5b613e58826020830160208701613df4565b949350505050565b80516114d38161396e565b5f60208284031215613e7b575f80fd5b81516001600160401b0380821115613e91575f80fd5b908301906101008286031215613ea5575f80fd5b613ead6139e4565b613eb683613de6565b8152602083015182811115613ec9575f80fd5b613ed587828601613e16565b602083015250613ee760408401613e60565b6040820152613ef860608401613e60565b6060820152613f0960808401613e60565b6080820152613f1a60a08401613e60565b60a0820152613f2b60c08401613e60565b60c0820152613f3c60e08401613e60565b60e082015295945050505050565b5f8060408385031215613f5b575f80fd5b825191506020830151613caa8161396e565b5f60208284031215613f7d575f80fd5b81516001600160401b03811115613f92575f80fd5b613e5884828501613e16565b5f8151808452613fb5816020860160208601613df4565b601f01601f19169290920160200192915050565b602081525f6117ae6020830184613f9e565b5f60208284031215613feb575f80fd5b5051919050565b6020810160068310614006576140066138d7565b91905290565b634e487b7160e01b5f52601160045260245ffd5b5f8261403a57634e487b7160e01b5f52601260045260245ffd5b500490565b8082028115828204841417610cca57610cca61400c565b5f60208284031215614066575f80fd5b81516117ae8161396e565b6001600160401b038181168382160190808211156140915761409161400c565b5092915050565b80820180821115610cca57610cca61400c565b5f80604083850312156140bc575f80fd5b82516001600160401b03808211156140d2575f80fd5b90840190606082870312156140e5575f80fd5b604051606081018181108382111715614100576141006139a8565b60405282518152602083015161411581613aaf565b602082015260408301518281111561412b575f80fd5b61413788828601613e16565b6040830152508094505050506020830151613caa81613878565b6001600160401b038281168282160390808211156140915761409161400c565b5f8060408385031215614182575f80fd5b825161418d8161396e565b6020939093015192949293505050565b5f6040830163ffffffff8351168452602080840151604060208701528281518085526060880191506020830194505f92505b808310156141f85784516001600160a01b031682529383019360019290920191908301906141cf565b509695505050505050565b60a081525f61421560a0830188613f9e565b82810360208401526142278188613f9e565b9050828103604084015261423b818761419d565b9050828103606084015261424f818661419d565b9150506001600160401b03831660808301529695505050505050565b6001600160401b0381811683821602808216919082811461428e5761428e61400c565b505092915050565b81810381811115610cca57610cca61400c565b5f602082840312156142b9575f80fd5b81356117ae81613aaf565b5f602082840312156142d4575f80fd5b6117ae82613b97565b5f602082840312156142ed575f80fd5b813560ff811681146117ae575f80fd5b5f6020828403121561430d575f80fd5b81516117ae81613878565b5f8251614329818460208701613df4565b919091019291505056fe6e5bdfcce15e53c3406ea67bfce37dcd26f5152d5492824e43fd5e3c8ac5ab009b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00a164736f6c6343000819000a",
+ "sourceMap": "1005:4688:92:-:0;;;2080:153;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;2151:27;2143:4;:35;;;;;;;;:::i;:::-;;2139:88;;2194:22;:20;:22::i;:::-;2080:153;1005:4688;;7711:422:140;8870:21;7900:15;;;;;;;7896:76;;;7938:23;;-1:-1:-1;;;7938:23:140;;;;;;;;;;;7896:76;7985:14;;-1:-1:-1;;;;;7985:14:140;;;:34;7981:146;;8035:33;;-1:-1:-1;;;;;;8035:33:140;-1:-1:-1;;;;;8035:33:140;;;;;8087:29;;577:50:160;;;8087:29:140;;565:2:160;550:18;8087:29:140;;;;;;;7981:146;7760:373;7711:422::o;14:282:160:-;106:6;159:2;147:9;138:7;134:23;130:32;127:52;;;175:1;172;165:12;127:52;207:9;201:16;246:1;239:5;236:12;226:40;;262:1;259;252:12;226:40;285:5;14:282;-1:-1:-1;;;14:282:160:o;301:127::-;362:10;357:3;353:20;350:1;343:31;393:4;390:1;383:15;417:4;414:1;407:15;433:200;1005:4688:92;;;;;;",
+ "linkReferences": {
+ "contracts/validator-manager/ValidatorMessages.sol": {
+ "ValidatorMessages": [
+ {
+ "start": 2911,
+ "length": 20
+ },
+ {
+ "start": 8318,
+ "length": 20
+ }
+ ]
+ }
+ }
+ },
+ "deployedBytecode": {
+ "object": "0x608060405234801561000f575f80fd5b50600436106101d1575f3560e01c80637e65f4da116100fe578063b2c1712e1161009e578063cd236e7f1161006e578063cd236e7f14610495578063e24b2680146104a8578063e4a63c40146104bb578063fb8b11dd146104cf575f80fd5b8063b2c1712e1461044c578063b5c934981461045f578063b771b3bc14610472578063caa7187414610480575f80fd5b80639681d940116100d95780639681d940146103f4578063a3a65e4814610407578063a9778a7a146102f3578063af1dd66c1461041a575f80fd5b80637e65f4da146103bb5780638ef34c98146103ce57806393e24598146103e1575f80fd5b80632aa566381161017457806360ad77841161014457806360ad77841461032f5780636206585614610342578063785e9e86146103635780637a63ad8514610394575f80fd5b80632aa56638146102b55780632e2194d8146102c857806335455ded146102f357806353a133381461030f575f80fd5b8063245dafcb116101af578063245dafcb1461021c57806325e1c7761461022f5780632674874b1461024257806327bf60cd146102a2575f80fd5b806313409645146101d5578063151d30d1146101ea5780631667956414610209575b5f80fd5b6101e86101e336600461384e565b6104e2565b005b6101f2600a81565b60405160ff90911681526020015b60405180910390f35b6101e8610217366004613885565b610822565b6101e861022a3660046138c0565b610833565b6101e861023d36600461384e565b610af7565b6102556102503660046138c0565b610bd5565b6040805182516001600160a01b0316815260208084015161ffff1690820152828201516001600160401b039081169282019290925260609283015190911691810191909152608001610200565b6101e86102b0366004613885565b610c61565b6101e86102c3366004613885565b610c6c565b6102db6102d63660046138c0565b610c7c565b6040516001600160401b039091168152602001610200565b6102fc61271081565b60405161ffff9091168152602001610200565b61032261031d3660046138c0565b610cd0565b60405161020091906138ff565b6101e861033d36600461384e565b610dbd565b61035561035036600461398d565b6110df565b604051908152602001610200565b5f80516020614334833981519152546001600160a01b03165b6040516001600160a01b039091168152602001610200565b6103557fafe6c4731b852fc2be89a0896ae43d22d8b24989064d841b2a1586b4d39ab60081565b6103556103c9366004613ba8565b6110ff565b6101e86103dc366004613c87565b61113c565b6101e86103ef3660046138c0565b61121e565b610355610402366004613cb5565b611337565b610355610415366004613cb5565b6114d8565b61042d6104283660046138c0565b611550565b604080516001600160a01b039093168352602083019190915201610200565b6101e861045a366004613885565b61158c565b6101e861046d366004613cce565b611597565b61037c6005600160991b0181565b6104886116a5565b6040516102009190613d01565b6103556104a3366004613da2565b611781565b61042d6104b63660046138c0565b6117b5565b6103555f8051602061433483398151915281565b6101e86104dd366004613c87565b6117f1565b6104ea6118b9565b5f6104f36118f0565b5f848152600882016020526040808220815160e0810190925280549394509192909190829060ff16600381111561052c5761052c6138d7565b600381111561053d5761053d6138d7565b8152815461010090046001600160a01b03166020820152600182015460408201526002909101546001600160401b038082166060840152600160401b820481166080840152600160801b8204811660a0840152600160c01b9091041660c09091015290506003815160038111156105b6576105b66138d7565b146105e0578051604051633b0d540d60e21b81526105d79190600401613dd8565b60405180910390fd5b81546040828101519051636af907fb60e11b815260048101919091525f916001600160a01b03169063d5f20ff6906024015f60405180830381865afa15801561062b573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526106529190810190613e6b565b9050600483546040808501519051636af907fb60e11b81526001600160a01b039092169163d5f20ff69161068c9160040190815260200190565b5f60405180830381865afa1580156106a6573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526106cd9190810190613e6b565b5160058111156106df576106df6138d7565b1415801561070657508160c001516001600160401b031681608001516001600160401b0316105b156107fc57825460405163338587c560e21b815263ffffffff861660048201525f9182916001600160a01b039091169063ce161f149060240160408051808303815f875af115801561075a573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061077e9190613f4a565b91509150818460400151146107b75781846040015160405163fee3144560e01b81526004016105d7929190918252602082015260400190565b806001600160401b03168460c001516001600160401b031611156107f957604051632e19bc2d60e11b81526001600160401b03821660048201526024016105d7565b50505b61080585611914565b50505061081e60015f8051602061435483398151915255565b5050565b61082d838383611b58565b50505050565b5f61083c6118f0565b5f838152600882016020526040808220815160e0810190925280549394509192909190829060ff166003811115610875576108756138d7565b6003811115610886576108866138d7565b8152815461010090046001600160a01b0316602082015260018083015460408301526002909201546001600160401b038082166060840152600160401b820481166080840152600160801b8204811660a0840152600160c01b9091041660c090910152909150815160038111156108ff576108ff6138d7565b14158015610920575060038151600381111561091d5761091d6138d7565b14155b15610941578051604051633b0d540d60e21b81526105d79190600401613dd8565b81546040828101519051636af907fb60e11b815260048101919091525f916001600160a01b03169063d5f20ff6906024015f60405180830381865afa15801561098c573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526109b39190810190613e6b565b905080606001516001600160401b03165f036109e5576040516339b894f960e21b8152600481018590526024016105d7565b604080830151606083015160a0840151925163854a893f60e01b81526005600160991b019363ee5b48eb9373__$fd0c147b4031eef6079b0498cbafa865f0$__9363854a893f93610a5393906004019283526001600160401b03918216602084015216604082015260600190565b5f60405180830381865af4158015610a6d573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052610a949190810190613f6d565b6040518263ffffffff1660e01b8152600401610ab09190613fc9565b6020604051808303815f875af1158015610acc573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610af09190613fdb565b5050505050565b610b0082611dfd565b610b20576040516330efa98b60e01b8152600481018390526024016105d7565b5f610b296118f0565b54604051636af907fb60e11b8152600481018590526001600160a01b039091169063d5f20ff6906024015f60405180830381865afa158015610b6d573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052610b949190810190613e6b565b5190506002816005811115610bab57610bab6138d7565b14610bcb578060405163170cc93360e21b81526004016105d79190613ff2565b61082d8383611e26565b604080516080810182525f808252602082018190529181018290526060810191909152610c006118f0565b5f9283526007016020908152604092839020835160808101855281546001600160a01b038116825261ffff600160a01b820416938201939093526001600160401b03600160b01b909304831694810194909452600101541660608301525090565b61082d838383612090565b610c778383836124b1565b505050565b5f80610c866118f0565b60040154610c949084614020565b9050801580610ca957506001600160401b0381115b15610cca5760405163222d164360e21b8152600481018490526024016105d7565b92915050565b6040805160e0810182525f80825260208201819052918101829052606081018290526080810182905260a0810182905260c0810191909152610d106118f0565b5f838152600891909101602052604090819020815160e081019092528054829060ff166003811115610d4457610d446138d7565b6003811115610d5557610d556138d7565b8152815461010090046001600160a01b03166020820152600182015460408201526002909101546001600160401b038082166060840152600160401b820481166080840152600160801b8204811660a0840152600160c01b9091041660c09091015292915050565b5f610dc66118f0565b5f848152600882016020526040808220815160e0810190925280549394509192909190829060ff166003811115610dff57610dff6138d7565b6003811115610e1057610e106138d7565b8152815461010090046001600160a01b03908116602083015260018301546040808401919091526002909301546001600160401b038082166060850152600160401b820481166080850152600160801b8204811660a0850152600160c01b9091041660c0909201919091528282015185549251636af907fb60e11b815260048101829052939450925f929091169063d5f20ff6906024015f60405180830381865afa158015610ec1573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052610ee89190810190613e6b565b9050600183516003811115610eff57610eff6138d7565b14610f20578251604051633b0d540d60e21b81526105d79190600401613dd8565b600481516005811115610f3557610f356138d7565b03610f4b57610f4386611914565b505050505050565b8260a001516001600160401b031681608001516001600160401b0316101561105357835460405163338587c560e21b815263ffffffff871660048201525f9182916001600160a01b039091169063ce161f149060240160408051808303815f875af1158015610fbc573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610fe09190613f4a565b9150915081841461100e5760405163fee3144560e01b815260048101839052602481018590526044016105d7565b8460a001516001600160401b0316816001600160401b0316101561105057604051632e19bc2d60e11b81526001600160401b03821660048201526024016105d7565b50505b5f868152600885016020908152604091829020805460ff1916600290811782550180546001600160401b034216600160401b81026fffffffffffffffff000000000000000019909216919091179091559151918252839188917f3886b7389bccb22cac62838dee3f400cf8b22289295283e01a2c7093f93dd5aa910160405180910390a3505050505050565b5f6110e86118f0565b60040154610cca906001600160401b03841661403f565b5f6111086118b9565b61111889898989898989896124dc565b905061113060015f8051602061435483398151915255565b98975050505050505050565b5f6111456118f0565b90506001600160a01b0382166111795760405163caa903f960e01b81526001600160a01b03831660048201526024016105d7565b5f8381526007820160205260409020546001600160a01b031633146111bf57335b604051636e2ccd7560e11b81526001600160a01b0390911660048201526024016105d7565b5f838152600c8201602052604080822080546001600160a01b038681166001600160a01b0319831681179093559251921692839287917f28c6fc4db51556a07b41aa23b91cedb22c02a7560c431a31255c03ca6ad61c3391a450505050565b5f6112276118f0565b8054604051636af907fb60e11b8152600481018590529192505f916001600160a01b039091169063d5f20ff6906024015f60405180830381865afa158015611271573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526112989190810190613e6b565b51905060048160058111156112af576112af6138d7565b146112cf578060405163170cc93360e21b81526004016105d79190613ff2565b5f8381526007830160205260409020546001600160a01b031633146112f4573361119a565b5f838152600c830160205260409020546001600160a01b03168061132d57505f8381526007830160205260409020546001600160a01b03165b61082d8185612813565b5f6113406118b9565b5f6113496118f0565b805460405163025a076560e61b815263ffffffff861660048201529192505f916001600160a01b0390911690639681d940906024016020604051808303815f875af115801561139a573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906113be9190613fdb565b8254604051636af907fb60e11b8152600481018390529192505f916001600160a01b039091169063d5f20ff6906024015f60405180830381865afa158015611408573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f1916820160405261142f9190810190613e6b565b905061143a82611dfd565b611448575091506114bd9050565b5f828152600784016020908152604080832054600c8701909252909120546001600160a01b0391821691168061147b5750805b600483516005811115611490576114906138d7565b0361149f5761149f8185612813565b6114b5826114b085604001516110df565b612887565b509193505050505b6114d360015f8051602061435483398151915255565b919050565b5f6114e16118f0565b54604051631474cbc960e31b815263ffffffff841660048201526001600160a01b039091169063a3a65e48906024016020604051808303815f875af115801561152c573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610cca9190613fdb565b5f805f61155b6118f0565b5f948552600a810160209081526040808720546009909301909152909420546001600160a01b039094169492505050565b610c778383836128aa565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a008054600160401b810460ff1615906001600160401b03165f811580156115db5750825b90505f826001600160401b031660011480156115f65750303b155b905081158015611604575080155b156116225760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff19166001178555831561164c57845460ff60401b1916600160401b1785555b61165687876128d5565b831561169c57845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50505050505050565b60408051610120810182525f80825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e081018290526101008101829052906116f56118f0565b604080516101208101825282546001600160a01b0390811682526001840154602083015260028401549282019290925260038301546001600160401b0381166060830152600160401b810461ffff166080830152600160501b900460ff1660a0820152600483015460c0820152600583015490911660e082015260069091015461010082015292915050565b5f61178a6118b9565b611796843385856128ef565b90506117ae60015f8051602061435483398151915255565b9392505050565b5f805f6117c06118f0565b5f948552600c81016020908152604080872054600b909301909152909420546001600160a01b039094169492505050565b6001600160a01b0381166118235760405163caa903f960e01b81526001600160a01b03821660048201526024016105d7565b5f61182c6118f0565b5f8481526008820160205260409020549091506001600160a01b0361010090910416331461185a573361119a565b5f838152600a8201602052604080822080546001600160a01b038681166001600160a01b0319831681179093559251921692839287917f6b30f219ab3cc1c43b394679707f3856ff2f3c6f1f6c97f383c6b16687a1e00591a450505050565b5f805160206143548339815191528054600119016118ea57604051633ee5aeb560e01b815260040160405180910390fd5b60029055565b7fafe6c4731b852fc2be89a0896ae43d22d8b24989064d841b2a1586b4d39ab60090565b5f61191d6118f0565b5f838152600882016020526040808220815160e0810190925280549394509192909190829060ff166003811115611956576119566138d7565b6003811115611967576119676138d7565b815281546001600160a01b03610100909104811660208084019190915260018401546040808501919091526002909401546001600160401b038082166060860152600160401b820481166080860152600160801b8204811660a0860152600160c01b9091041660c09093019290925283830151865484516304e0efb360e11b8152945195965090949116926309c1df669260048083019391928290030181865afa158015611a17573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611a3b9190614056565b8260800151611a4a9190614071565b6001600160401b0316421015611a7e5760405163fb6ce63f60e01b81526001600160401b03421660048201526024016105d7565b5f848152600884016020908152604080832080546001600160a81b031916815560018101849055600201839055600a8601909152902080546001600160a01b031981169091556001600160a01b031680611ad9575060208201515b5f80611ae6838886612d39565b91509150611aff85602001516114b087606001516110df565b6040805183815260208101839052859189917f5ecc5b26a9265302cf871229b3d983e5ca57dbb1448966c6c58b2d3c68bc7f7e910160405180910390a350505050505050565b60015f8051602061435483398151915255565b5f80611b626118f0565b8054604051635b73516560e11b8152600481018890529192506001600160a01b03169063b6e6a2ca906024015f604051808303815f87803b158015611ba5575f80fd5b505af1158015611bb7573d5f803e3d5ffd5b50508254604051636af907fb60e11b8152600481018990525f93506001600160a01b03909116915063d5f20ff6906024015f60405180830381865afa158015611c02573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052611c299190810190613e6b565b9050611c3486611dfd565b611c43576001925050506117ae565b5f8681526007830160205260409020546001600160a01b03163314611c68573361119a565b5f86815260078301602052604090205460c0820151611c9791600160b01b90046001600160401b031690614071565b6001600160401b03168160e001516001600160401b03161015611cde5760e081015160405163fb6ce63f60e01b81526001600160401b0390911660048201526024016105d7565b5f8515611cf657611cef8786611e26565b9050611d14565b505f8681526007830160205260409020600101546001600160401b03165b600583015460408301515f916001600160a01b031690634f22429f90611d39906110df565b60c086015160e0808801516040519185901b6001600160e01b031916825260048201939093526001600160401b0391821660248201819052604482015291811660648301528516608482015260a401602060405180830381865afa158015611da3573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611dc79190613fdb565b90508084600b015f8a81526020019081526020015f205f828254611deb9190614098565b90915550501515979650505050505050565b5f80611e076118f0565b5f938452600701602052505060409020546001600160a01b0316151590565b6040516306f8253560e41b815263ffffffff821660048201525f90819081906005600160991b0190636f825350906024015f60405180830381865afa158015611e71573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052611e9891908101906140ab565b9150915080611eba57604051636b2f19e960e01b815260040160405180910390fd5b5f611ec36118f0565b6006810154845191925014611ef1578251604051636ba589a560e01b815260048101919091526024016105d7565b60208301516001600160a01b031615611f2d576020830151604051624de75d60e31b81526001600160a01b0390911660048201526024016105d7565b5f8073__$fd0c147b4031eef6079b0498cbafa865f0$__63088c246386604001516040518263ffffffff1660e01b8152600401611f6a9190613fc9565b6040805180830381865af4158015611f84573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611fa89190613f4a565b91509150818814611fd65760405163fee3144560e01b815260048101839052602481018990526044016105d7565b5f8881526007840160205260409020600101546001600160401b039081169082161115612067575f888152600784016020908152604091829020600101805467ffffffffffffffff19166001600160401b038516908117909155915191825289917fec44148e8ff271f2d0bacef1142154abacb0abb3a29eb3eb50e2ca97e86d0435910160405180910390a2612085565b505f8781526007830160205260409020600101546001600160401b03165b979650505050505050565b5f8061209a6118f0565b5f868152600882016020526040808220815160e0810190925280549394509192909190829060ff1660038111156120d3576120d36138d7565b60038111156120e4576120e46138d7565b8152815461010090046001600160a01b03908116602083015260018301546040808401919091526002909301546001600160401b038082166060850152600160401b820481166080850152600160801b8204811660a0850152600160c01b9091041660c0909201919091528282015185549251636af907fb60e11b815260048101829052939450925f929091169063d5f20ff6906024015f60405180830381865afa158015612195573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526121bc9190810190613e6b565b90506002835160038111156121d3576121d36138d7565b146121f4578251604051633b0d540d60e21b81526105d79190600401613dd8565b60208301516001600160a01b03163314612290575f8281526007850160205260409020546001600160a01b0316331461222d573361119a565b5f82815260078501602052604090205460c082015161225c91600160b01b90046001600160401b031690614071565b6001600160401b03164210156122905760405163fb6ce63f60e01b81526001600160401b03421660048201526024016105d7565b5f888152600a850160205260409020546001600160a01b03166002825160058111156122be576122be6138d7565b0361245857600385015460808501516122e0916001600160401b031690614071565b6001600160401b03164210156123145760405163fb6ce63f60e01b81526001600160401b03421660048201526024016105d7565b8715612326576123248388611e26565b505b5f8981526008860160205260409020805460ff191660031790558454606085015160a08401516001600160a01b0390921691636610966991869161236a9190614151565b6040516001600160e01b031960e085901b16815260048101929092526001600160401b0316602482015260440160408051808303815f875af11580156123b2573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906123d69190614171565b505f8a8152600887016020526040812060020180546001600160401b03909316600160c01b026001600160c01b039093169290921790915561241985838c612e38565b9050838a7f5abe543af12bb7f76f6fa9daaa9d95d181c5e90566df58d3c012216b6245eeaf60405160405180910390a3151595506117ae945050505050565b60048251600581111561246d5761246d6138d7565b036124955761247d84828b612e38565b5061248789611914565b6001955050505050506117ae565b815160405163170cc93360e21b81526105d79190600401613ff2565b6124bc838383612090565b610c7757604051631036cf9160e11b8152600481018490526024016105d7565b5f806124e66118f0565b600381015490915061ffff600160401b9091048116908716108061250f575061271061ffff8716115b1561253357604051635f12e6c360e11b815261ffff871660048201526024016105d7565b60038101546001600160401b03908116908616101561256f576040516202a06d60e11b81526001600160401b03861660048201526024016105d7565b80600101548410806125845750806002015484115b156125a55760405163222d164360e21b8152600481018590526024016105d7565b6001600160a01b0383166125d75760405163caa903f960e01b81526001600160a01b03841660048201526024016105d7565b5f6125e185613072565b90505f6125ed82610c7c565b90505f835f015f9054906101000a90046001600160a01b03166001600160a01b0316639cb7624e8e8e8e8e876040518663ffffffff1660e01b8152600401612639959493929190614203565b6020604051808303815f875af1158015612655573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906126799190613fdb565b90505f33905080856007015f8481526020019081526020015f205f015f6101000a8154816001600160a01b0302191690836001600160a01b0316021790555089856007015f8481526020019081526020015f205f0160146101000a81548161ffff021916908361ffff16021790555088856007015f8481526020019081526020015f205f0160166101000a8154816001600160401b0302191690836001600160401b031602179055505f856007015f8481526020019081526020015f206001015f6101000a8154816001600160401b0302191690836001600160401b031602179055508685600c015f8481526020019081526020015f205f6101000a8154816001600160a01b0302191690836001600160a01b03160217905550806001600160a01b0316827ff51ab9b5253693af2f675b23c4042ccac671873d5f188e405b30019f4c159b7f8c8c8b6040516127fa9392919061ffff9390931683526001600160401b039190911660208301526001600160a01b0316604082015260600190565b60405180910390a3509c9b505050505050505050505050565b5f61281c6118f0565b5f838152600b820160205260408120805491905590915061283d8482613095565b836001600160a01b0316837f875feb58aa30eeee040d55b00249c5c8c5af4f27c95cd29d64180ad67400c6e48360405161287991815260200190565b60405180910390a350505050565b5f805160206143348339815191525461081e906001600160a01b03168383613102565b6128b5838383611b58565b610c7757604051635bff683f60e11b8152600481018490526024016105d7565b6128dd613161565b6128e6826131ac565b61081e8161322a565b5f806128f96118f0565b90505f6129086102d686613072565b905061291387611dfd565b612933576040516330efa98b60e01b8152600481018890526024016105d7565b6001600160a01b0384166129655760405163caa903f960e01b81526001600160a01b03851660048201526024016105d7565b8154604051636af907fb60e11b8152600481018990525f9182916001600160a01b039091169063d5f20ff6906024015f60405180830381865afa1580156129ae573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526129d59190810190613e6b565b9050828160a001516129e79190614071565b915083600301600a9054906101000a90046001600160401b03168160400151612a10919061426b565b6001600160401b0316826001600160401b03161115612a4d57604051636d51fe0560e11b81526001600160401b03831660048201526024016105d7565b508254604051636610966960e01b8152600481018a90526001600160401b03831660248201525f9182916001600160a01b039091169063661096699060440160408051808303815f875af1158015612aa7573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612acb9190614171565b915091505f8a83604051602001612af992919091825260c01b6001600160c01b031916602082015260280190565b60408051601f1981840301815291815281516020928301205f81815260088a019093529120805491925060019160ff19168280021790555089866008015f8381526020019081526020015f205f0160016101000a8154816001600160a01b0302191690836001600160a01b031602179055508a866008015f8381526020019081526020015f206001018190555084866008015f8381526020019081526020015f206002015f6101000a8154816001600160401b0302191690836001600160401b031602179055505f866008015f8381526020019081526020015f2060020160086101000a8154816001600160401b0302191690836001600160401b0316021790555082866008015f8381526020019081526020015f2060020160106101000a8154816001600160401b0302191690836001600160401b031602179055505f866008015f8381526020019081526020015f2060020160186101000a8154816001600160401b0302191690836001600160401b031602179055508786600a015f8381526020019081526020015f205f6101000a8154816001600160a01b0302191690836001600160a01b03160217905550896001600160a01b03168b827f77499a5603260ef2b34698d88b31f7b1acf28c7b134ad4e3fa636501e6064d7786888a888f604051612d239594939291906001600160401b039586168152938516602085015291909316604083015260608201929092526001600160a01b0391909116608082015260a00190565b60405180910390a49a9950505050505050505050565b5f805f612d446118f0565b5f8681526009820160205260408120549192509081908015612e2a575f88815260098501602090815260408083208390558983526007870190915290205461271090612d9b90600160a01b900461ffff168361403f565b612da59190614020565b91508184600b015f8981526020019081526020015f205f828254612dc99190614098565b90915550612dd990508282614296565b9250612de58984613095565b886001600160a01b0316887f3ffc31181aadb250503101bd718e5fce8c27650af8d3525b9f60996756efaf6385604051612e2191815260200190565b60405180910390a35b509097909650945050505050565b5f80612e426118f0565b80546040808801519051636af907fb60e11b81529293505f926001600160a01b039092169163d5f20ff691612e7d9160040190815260200190565b5f60405180830381865afa158015612e97573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052612ebe9190810190613e6b565b90505f600382516005811115612ed657612ed66138d7565b1480612ef45750600482516005811115612ef257612ef26138d7565b145b15612f04575060e0810151612f21565b600282516005811115612f1957612f196138d7565b036124955750425b86608001516001600160401b0316816001600160401b031611612f49575f93505050506117ae565b600583015460608801515f916001600160a01b031690634f22429f90612f6e906110df565b60c086015160808c01516040808e01515f90815260078b0160205281902060010154905160e086901b6001600160e01b031916815260048101949094526001600160401b0392831660248501529082166044840152818716606484015216608482015260a401602060405180830381865afa158015612fef573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906130139190613fdb565b90506001600160a01b03871661302b57876020015196505b5f8681526009850160209081526040808320849055600a90960190529390932080546001600160a01b0388166001600160a01b031990911617905550909150509392505050565b5f610cca825f80516020614334833981519152546001600160a01b031690613287565b5f5f8051602061433483398151915280546040516340c10f1960e01b81526001600160a01b038681166004830152602482018690529293509116906340c10f19906044015f604051808303815f87803b1580156130f0575f80fd5b505af115801561169c573d5f803e3d5ffd5b6040516001600160a01b03838116602483015260448201839052610c7791859182169063a9059cbb906064015b604051602081830303815290604052915060e01b6020820180516001600160e01b038381831617835250505050613293565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054600160401b900460ff166131aa57604051631afcd79f60e31b815260040160405180910390fd5b565b6131b4613161565b6131bc6132f4565b6132276131cc60208301836142a9565b602083013560408401356131e6608086016060870161398d565b6131f660a08701608088016142c4565b61320660c0880160a089016142dd565b60c088013561321c6101008a0160e08b016142a9565b896101000135613304565b50565b613232613161565b5f805160206143348339815191526001600160a01b0382166132675760405163d92e233d60e01b815260040160405180910390fd5b80546001600160a01b0319166001600160a01b0392909216919091179055565b5f6117ae83338461357b565b5f6132a76001600160a01b038416836136de565b905080515f141580156132cb5750808060200190518101906132c991906142fd565b155b15610c7757604051635274afe760e01b81526001600160a01b03841660048201526024016105d7565b6132fc613161565b6131aa6136eb565b61330c613161565b5f6133156118f0565b905061ffff8616158061332d575061271061ffff8716115b1561335157604051635f12e6c360e11b815261ffff871660048201526024016105d7565b878911156133755760405163222d164360e21b8152600481018a90526024016105d7565b60ff851615806133885750600a60ff8616115b156133ab5760405163170db35960e31b815260ff861660048201526024016105d7565b6001600160a01b038a166133d25760405163d92e233d60e01b815260040160405180910390fd5b6001600160a01b0383166133f95760405163d92e233d60e01b815260040160405180910390fd5b896001600160a01b03166309c1df666040518163ffffffff1660e01b8152600401602060405180830381865afa158015613435573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906134599190614056565b6001600160401b0316876001600160401b03161015613495576040516202a06d60e11b81526001600160401b03881660048201526024016105d7565b835f036134b55760405163a733007160e01b815260040160405180910390fd5b816134d657604051632f6bd1db60e01b8152600481018390526024016105d7565b80546001600160a01b039a8b166001600160a01b031991821617825560018201999099556002810197909755600387018054600160501b60ff9096169590950267ffffffffffffffff60501b1961ffff909716600160401b0269ffffffffffffffffffff199096166001600160401b03909816979097179490941794909416949094179091556004840155600583018054929095169190931617909255600690910155565b6040516370a0823160e01b81523060048201525f9081906001600160a01b038616906370a0823190602401602060405180830381865afa1580156135c1573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906135e59190613fdb565b90506135fc6001600160a01b0386168530866136f3565b6040516370a0823160e01b81523060048201525f906001600160a01b038716906370a0823190602401602060405180830381865afa158015613640573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906136649190613fdb565b90508181116136ca5760405162461bcd60e51b815260206004820152602c60248201527f5361666545524332305472616e7366657246726f6d3a2062616c616e6365206e60448201526b1bdd081a5b98dc99585cd95960a21b60648201526084016105d7565b6136d48282614296565b9695505050505050565b60606117ae83835f61372c565b611b45613161565b6040516001600160a01b03848116602483015283811660448301526064820183905261082d9186918216906323b872dd9060840161312f565b6060814710156137515760405163cd78605960e01b81523060048201526024016105d7565b5f80856001600160a01b0316848660405161376c9190614318565b5f6040518083038185875af1925050503d805f81146137a6576040519150601f19603f3d011682016040523d82523d5f602084013e6137ab565b606091505b50915091506136d48683836060826137cb576137c682613812565b6117ae565b81511580156137e257506001600160a01b0384163b155b1561380b57604051639996b31560e01b81526001600160a01b03851660048201526024016105d7565b50806117ae565b8051156138225780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b803563ffffffff811681146114d3575f80fd5b5f806040838503121561385f575f80fd5b8235915061386f6020840161383b565b90509250929050565b8015158114613227575f80fd5b5f805f60608486031215613897575f80fd5b8335925060208401356138a981613878565b91506138b76040850161383b565b90509250925092565b5f602082840312156138d0575f80fd5b5035919050565b634e487b7160e01b5f52602160045260245ffd5b600481106138fb576138fb6138d7565b9052565b5f60e0820190506139118284516138eb565b60018060a01b0360208401511660208301526040830151604083015260608301516001600160401b0380821660608501528060808601511660808501528060a08601511660a08501528060c08601511660c0850152505092915050565b6001600160401b0381168114613227575f80fd5b80356114d38161396e565b5f6020828403121561399d575f80fd5b81356117ae8161396e565b634e487b7160e01b5f52604160045260245ffd5b604080519081016001600160401b03811182821017156139de576139de6139a8565b60405290565b60405161010081016001600160401b03811182821017156139de576139de6139a8565b604051601f8201601f191681016001600160401b0381118282101715613a2f57613a2f6139a8565b604052919050565b5f6001600160401b03821115613a4f57613a4f6139a8565b50601f01601f191660200190565b5f82601f830112613a6c575f80fd5b8135613a7f613a7a82613a37565b613a07565b818152846020838601011115613a93575f80fd5b816020850160208301375f918101602001919091529392505050565b6001600160a01b0381168114613227575f80fd5b80356114d381613aaf565b5f60408284031215613ade575f80fd5b613ae66139bc565b9050613af18261383b565b81526020808301356001600160401b0380821115613b0d575f80fd5b818501915085601f830112613b20575f80fd5b813581811115613b3257613b326139a8565b8060051b9150613b43848301613a07565b8181529183018401918481019088841115613b5c575f80fd5b938501935b83851015613b865784359250613b7683613aaf565b8282529385019390850190613b61565b808688015250505050505092915050565b803561ffff811681146114d3575f80fd5b5f805f805f805f80610100898b031215613bc0575f80fd5b88356001600160401b0380821115613bd6575f80fd5b613be28c838d01613a5d565b995060208b0135915080821115613bf7575f80fd5b613c038c838d01613a5d565b985060408b0135915080821115613c18575f80fd5b613c248c838d01613ace565b975060608b0135915080821115613c39575f80fd5b50613c468b828c01613ace565b955050613c5560808a01613b97565b9350613c6360a08a01613982565b925060c08901359150613c7860e08a01613ac3565b90509295985092959890939650565b5f8060408385031215613c98575f80fd5b823591506020830135613caa81613aaf565b809150509250929050565b5f60208284031215613cc5575f80fd5b6117ae8261383b565b5f80828403610140811215613ce1575f80fd5b61012080821215613cf0575f80fd5b8493508301359050613caa81613aaf565b81516001600160a01b031681526020808301519082015260408083015190820152606080830151610120830191613d42908401826001600160401b03169052565b506080830151613d58608084018261ffff169052565b5060a0830151613d6d60a084018260ff169052565b5060c083015160c083015260e0830151613d9260e08401826001600160a01b03169052565b5061010092830151919092015290565b5f805f60608486031215613db4575f80fd5b83359250602084013591506040840135613dcd81613aaf565b809150509250925092565b60208101610cca82846138eb565b8051600681106114d3575f80fd5b5f5b83811015613e0e578181015183820152602001613df6565b50505f910152565b5f82601f830112613e25575f80fd5b8151613e33613a7a82613a37565b818152846020838601011115613e47575f80fd5b613e58826020830160208701613df4565b949350505050565b80516114d38161396e565b5f60208284031215613e7b575f80fd5b81516001600160401b0380821115613e91575f80fd5b908301906101008286031215613ea5575f80fd5b613ead6139e4565b613eb683613de6565b8152602083015182811115613ec9575f80fd5b613ed587828601613e16565b602083015250613ee760408401613e60565b6040820152613ef860608401613e60565b6060820152613f0960808401613e60565b6080820152613f1a60a08401613e60565b60a0820152613f2b60c08401613e60565b60c0820152613f3c60e08401613e60565b60e082015295945050505050565b5f8060408385031215613f5b575f80fd5b825191506020830151613caa8161396e565b5f60208284031215613f7d575f80fd5b81516001600160401b03811115613f92575f80fd5b613e5884828501613e16565b5f8151808452613fb5816020860160208601613df4565b601f01601f19169290920160200192915050565b602081525f6117ae6020830184613f9e565b5f60208284031215613feb575f80fd5b5051919050565b6020810160068310614006576140066138d7565b91905290565b634e487b7160e01b5f52601160045260245ffd5b5f8261403a57634e487b7160e01b5f52601260045260245ffd5b500490565b8082028115828204841417610cca57610cca61400c565b5f60208284031215614066575f80fd5b81516117ae8161396e565b6001600160401b038181168382160190808211156140915761409161400c565b5092915050565b80820180821115610cca57610cca61400c565b5f80604083850312156140bc575f80fd5b82516001600160401b03808211156140d2575f80fd5b90840190606082870312156140e5575f80fd5b604051606081018181108382111715614100576141006139a8565b60405282518152602083015161411581613aaf565b602082015260408301518281111561412b575f80fd5b61413788828601613e16565b6040830152508094505050506020830151613caa81613878565b6001600160401b038281168282160390808211156140915761409161400c565b5f8060408385031215614182575f80fd5b825161418d8161396e565b6020939093015192949293505050565b5f6040830163ffffffff8351168452602080840151604060208701528281518085526060880191506020830194505f92505b808310156141f85784516001600160a01b031682529383019360019290920191908301906141cf565b509695505050505050565b60a081525f61421560a0830188613f9e565b82810360208401526142278188613f9e565b9050828103604084015261423b818761419d565b9050828103606084015261424f818661419d565b9150506001600160401b03831660808301529695505050505050565b6001600160401b0381811683821602808216919082811461428e5761428e61400c565b505092915050565b81810381811115610cca57610cca61400c565b5f602082840312156142b9575f80fd5b81356117ae81613aaf565b5f602082840312156142d4575f80fd5b6117ae82613b97565b5f602082840312156142ed575f80fd5b813560ff811681146117ae575f80fd5b5f6020828403121561430d575f80fd5b81516117ae81613878565b5f8251614329818460208701613df4565b919091019291505056fe6e5bdfcce15e53c3406ea67bfce37dcd26f5152d5492824e43fd5e3c8ac5ab009b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00a164736f6c6343000819000a",
+ "sourceMap": "1005:4688:92:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;38165:1897:96;;;;;;:::i;:::-;;:::i;:::-;;3941:57;;3996:2;3941:57;;;;;691:4:160;679:17;;;661:36;;649:2;634:18;3941:57:96;;;;;;;;11197:342;;;;;;:::i;:::-;;:::i;36992:939::-;;;;;;:::i;:::-;;:::i;9063:565::-;;;;;;:::i;:::-;;:::i;23237:194::-;;;;;;:::i;:::-;;:::i;:::-;;;;1843:13:160;;-1:-1:-1;;;;;1839:39:160;1821:58;;1939:4;1927:17;;;1921:24;1947:6;1917:37;1895:20;;;1888:67;1990:17;;;1984:24;-1:-1:-1;;;;;2083:21:160;;;2061:20;;;2054:51;;;;2165:4;2153:17;;;2147:24;2143:33;;;2121:20;;;2114:63;;;;1808:3;1793:19;23237:194:96;1604:579:160;31212:339:96;;;;;;:::i;:::-;;:::i;30554:240::-;;;;;;:::i;:::-;;:::i;21613:314::-;;;;;;:::i;:::-;;:::i;:::-;;;-1:-1:-1;;;;;2535:31:160;;;2517:50;;2505:2;2490:18;21613:314:96;2373:200:160;4005:58:96;;4058:5;4005:58;;;;;2752:6:160;2740:19;;;2722:38;;2710:2;2695:18;4005:58:96;2578:188:160;24049:183:96;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;28358:2111::-;;;;;;:::i;:::-;;:::i;22040:172::-;;;;;;:::i;:::-;;:::i;:::-;;;4510:25:160;;;4498:2;4483:18;22040:172:96;4364:177:160;4697:119:92;-1:-1:-1;;;;;;;;;;;4770:39:92;-1:-1:-1;;;;;4770:39:92;4697:119;;;-1:-1:-1;;;;;4859:32:160;;;4841:51;;4829:2;4814:18;4697:119:92;4671:227:160;3801:133:96;;3868:66;3801:133;;3420:783:92;;;;;;:::i;:::-;;:::i;11630:674:96:-;;;;;;:::i;:::-;;:::i;9708:743::-;;;;;;:::i;:::-;;:::i;15448:1473::-;;;;;;:::i;:::-;;:::i;21291:205::-;;;;;;:::i;:::-;;:::i;24470:313::-;;;;;;:::i;:::-;;:::i;:::-;;;;-1:-1:-1;;;;;10226:32:160;;;10208:51;;10290:2;10275:18;;10268:34;;;;10181:18;24470:313:96;10034:274:160;10536:240:96;;;;;;:::i;:::-;;:::i;2432:192:92:-;;;;;;:::i;:::-;;:::i;4130:114:96:-;;-1:-1:-1;;;;;4130:114:96;;22308:720;;;:::i;:::-;;;;;;;:::i;4302:321:92:-;;;;;;:::i;:::-;;:::i;23669:282:96:-;;;;;;:::i;:::-;;:::i;1608:139:92:-;;-1:-1:-1;;;;;;;;;;;1608:139:92;;12395:691:96;;;;;;:::i;:::-;;:::i;38165:1897::-;3251:21:143;:19;:21::i;:::-;38296:31:96::1;38330:27;:25;:27::i;:::-;38367:26;38396:32:::0;;;:18:::1;::::0;::::1;:32;::::0;;;;;38367:61;;::::1;::::0;::::1;::::0;;;;;38296;;-1:-1:-1;38367:26:96;;:61;;38396:32;38367:61;;::::1;;;::::0;::::1;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;::::0;;;;::::1;::::0;::::1;-1:-1:-1::0;;;;;38367:61:96::1;;::::0;::::1;::::0;::::1;::::0;::::1;::::0;;;;;::::1;::::0;;::::1;::::0;-1:-1:-1;;;;;38367:61:96;;::::1;::::0;;;;-1:-1:-1;;;38367:61:96;::::1;::::0;::::1;::::0;;;;-1:-1:-1;;;38367:61:96;::::1;::::0;::::1;::::0;;;;-1:-1:-1;;;38367:61:96;;::::1;;::::0;;;;;;-1:-1:-1;38697:30:96::1;38677:16:::0;;:50:::1;::::0;::::1;;;;;;:::i;:::-;;38673:128;;38773:16:::0;;38750:40:::1;::::0;-1:-1:-1;;;38750:40:96;;::::1;::::0;38773:16;38750:40:::1;;;:::i;:::-;;;;;;;;38673:128;38839:10:::0;;38863:22:::1;::::0;;::::1;::::0;38839:47;;-1:-1:-1;;;38839:47:96;;::::1;::::0;::::1;4510:25:160::0;;;;38810:26:96::1;::::0;-1:-1:-1;;;;;38839:10:96::1;::::0;:23:::1;::::0;4483:18:160;;38839:47:96::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;::::0;;::::1;-1:-1:-1::0;;38839:47:96::1;::::0;::::1;;::::0;::::1;::::0;;;::::1;::::0;::::1;:::i;:::-;38810:76:::0;-1:-1:-1;39108:25:96::1;39050:10:::0;;39074:22:::1;::::0;;::::1;::::0;39050:47;;-1:-1:-1;;;39050:47:96;;-1:-1:-1;;;;;39050:10:96;;::::1;::::0;:23:::1;::::0;:47:::1;::::0;::::1;;4510:25:160::0;;;4498:2;4483:18;;4364:177;39050:47:96::1;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;::::0;;::::1;-1:-1:-1::0;;39050:47:96::1;::::0;::::1;;::::0;::::1;::::0;;;::::1;::::0;::::1;:::i;:::-;:54:::0;:83:::1;::::0;::::1;;;;;;:::i;:::-;;;:150;;;;;39179:9;:21;;;-1:-1:-1::0;;;;;39153:47:96::1;:9;:23;;;-1:-1:-1::0;;;;;39153:47:96::1;;39050:150;39033:973;;;39280:10:::0;;:54:::1;::::0;-1:-1:-1;;;39280:54:96;;15023:10:160;15011:23;;39280:54:96::1;::::0;::::1;14993:42:160::0;39226:20:96::1;::::0;;;-1:-1:-1;;;;;39280:10:96;;::::1;::::0;:40:::1;::::0;14966:18:160;;39280:54:96::1;::::0;::::1;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;39225:109;;;;39378:12;39352:9;:22;;;:38;39348:144;;39440:12;39454:9;:22;;;39417:60;;-1:-1:-1::0;;;39417:60:96::1;;;;;;;;15535:25:160::0;;;15591:2;15576:18;;15569:34;15523:2;15508:18;;15361:248;39348:144:96::1;39930:5;-1:-1:-1::0;;;;;39906:29:96::1;:9;:21;;;-1:-1:-1::0;;;;;39906:29:96::1;;39902:94;;;39962:19;::::0;-1:-1:-1;;;39962:19:96;;-1:-1:-1;;;;;2535:31:160;;39962:19:96::1;::::0;::::1;2517:50:160::0;2490:18;;39962:19:96::1;2373:200:160::0;39902:94:96::1;39211:795;;39033:973;40016:39;40042:12;40016:25;:39::i;:::-;38286:1776;;;3293:20:143::0;1805:1;-1:-1:-1;;;;;;;;;;;3969:23:143;3716:283;3293:20;38165:1897:96;;:::o;11197:342::-;11456:76;11485:12;11499:18;11519:12;11456:28;:76::i;:::-;;11197:342;;;:::o;36992:939::-;37078:31;37112:27;:25;:27::i;:::-;37149:26;37178:32;;;:18;;;:32;;;;;;37149:61;;;;;;;;;;37078;;-1:-1:-1;37149:26:96;;:61;;37178:32;37149:61;;;;;;;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;;;;;;;-1:-1:-1;;;;;37149:61:96;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;37149:61:96;;;;;;;-1:-1:-1;;;37149:61:96;;;;;;;;-1:-1:-1;;;37149:61:96;;;;;;;;-1:-1:-1;;;37149:61:96;;;;;;;;;;;-1:-1:-1;37237:16:96;;:48;;;;;;;;:::i;:::-;;;:118;;;;-1:-1:-1;37325:30:96;37305:16;;:50;;;;;;;;:::i;:::-;;;37237:118;37220:218;;;37410:16;;37387:40;;-1:-1:-1;;;37387:40:96;;;;37410:16;37387:40;;;:::i;37220:218::-;37477:10;;37501:22;;;;;37477:47;;-1:-1:-1;;;37477:47:96;;;;;4510:25:160;;;;37448:26:96;;-1:-1:-1;;;;;37477:10:96;;:23;;4483:18:160;;37477:47:96;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;37477:47:96;;;;;;;;;;;;:::i;:::-;37448:76;;37538:9;:19;;;-1:-1:-1;;;;;37538:24:96;37561:1;37538:24;37534:133;;37623:33;;-1:-1:-1;;;37623:33:96;;;;;4510:25:160;;;4483:18;;37623:33:96;4364:177:160;37534:133:96;37839:22;;;;;37863:19;;;;37884:16;;;;37775:139;;-1:-1:-1;;;37775:139:96;;-1:-1:-1;;;;;4201:42:96;37731:30;;37775:17;;:46;;:139;;37884:16;37775:139;;15820:25:160;;;-1:-1:-1;;;;;15918:15:160;;;15913:2;15898:18;;15891:43;15970:15;15965:2;15950:18;;15943:43;15808:2;15793:18;;15614:378;37775:139:96;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;37775:139:96;;;;;;;;;;;;:::i;:::-;37731:193;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;37068:863;;;36992:939;:::o;9063:565::-;9157:29;9173:12;9157:15;:29::i;:::-;9152:97;;9209:29;;-1:-1:-1;;;9209:29:96;;;;;4510:25:160;;;4483:18;;9209:29:96;4364:177:160;9152:97:96;9258:22;9295:27;:25;:27::i;:::-;:36;:63;;-1:-1:-1;;;9295:63:96;;;;;4510:25:160;;;-1:-1:-1;;;;;9295:36:96;;;;:49;;4483:18:160;;9295:63:96;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;9295:63:96;;;;;;;;;;;;:::i;:::-;:70;;-1:-1:-1;9389:22:96;9379:6;:32;;;;;;;;:::i;:::-;;9375:100;;9457:6;9434:30;;-1:-1:-1;;;9434:30:96;;;;;;;;:::i;9375:100::-;9580:41;9594:12;9608;9580:13;:41::i;23237:194::-;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23365:27:96;:25;:27::i;:::-;:59;;;;:45;;:59;;;;;;;;;23358:66;;;;;;;;;-1:-1:-1;;;;;23358:66:96;;;;;-1:-1:-1;;;23358:66:96;;;;;;;;;;-1:-1:-1;;;;;;;;23358:66:96;;;;;;;;;;;;;;;;;;;;-1:-1:-1;23358:66:96;23237:194::o;31212:339::-;31471:73;31497:12;31511:18;31531:12;31471:25;:73::i;30554:240::-;30705:82;30740:12;30754:18;30774:12;30705:34;:82::i;:::-;30554:240;;;:::o;21613:314::-;21686:6;21704:14;21729:27;:25;:27::i;:::-;:48;;;21721:56;;:5;:56;:::i;:::-;21704:73;-1:-1:-1;21791:11:96;;;:40;;-1:-1:-1;;;;;;21806:25:96;;21791:40;21787:103;;;21854:25;;-1:-1:-1;;;21854:25:96;;;;;4510::160;;;4483:18;;21854:25:96;4364:177:160;21787:103:96;21913:6;21613:314;-1:-1:-1;;21613:314:96:o;24049:183::-;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;24167:27:96;:25;:27::i;:::-;:58;;;;:44;;;;;:58;;;;;;;24160:65;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;;;;;;;-1:-1:-1;;;;;24160:65:96;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;24160:65:96;;;;;;;-1:-1:-1;;;24160:65:96;;;;;;;;-1:-1:-1;;;24160:65:96;;;;;;;;-1:-1:-1;;;24160:65:96;;;;;;;;;;;-1:-1:-1;;24049:183:96:o;28358:2111::-;28459:31;28493:27;:25;:27::i;:::-;28531:26;28560:32;;;:18;;;:32;;;;;;28531:61;;;;;;;;;;28459;;-1:-1:-1;28531:26:96;;:61;;28560:32;28531:61;;;;;;;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;;;;;;;-1:-1:-1;;;;;28531:61:96;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;28531:61:96;;;;;;;-1:-1:-1;;;28531:61:96;;;;;;;;-1:-1:-1;;;28531:61:96;;;;;;;;-1:-1:-1;;;28531:61:96;;;;;;;;;;;;28625:22;;;;28686:10;;:37;;-1:-1:-1;;;28686:37:96;;;;;4510:25:160;;;28625:22:96;;-1:-1:-1;28625:22:96;-1:-1:-1;;28686:10:96;;;;:23;;4483:18:160;;28686:37:96;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;28686:37:96;;;;;;;;;;;;:::i;:::-;28657:66;-1:-1:-1;28998:28:96;28978:16;;:48;;;;;;;;:::i;:::-;;28974:126;;29072:16;;29049:40;;-1:-1:-1;;;29049:40:96;;;;29072:16;29049:40;;;:::i;28974:126::-;29319:25;29299:16;;:45;;;;;;;;:::i;:::-;;29295:122;;29367:39;29393:12;29367:25;:39::i;:::-;29360:46;;;;28358:2111;;:::o;29295:122::-;29657:9;:23;;;-1:-1:-1;;;;;29631:49:96;:9;:23;;;-1:-1:-1;;;;;29631:49:96;;29627:457;;;29758:10;;:54;;-1:-1:-1;;;29758:54:96;;15023:10:160;15011:23;;29758:54:96;;;14993:42:160;29697:27:96;;;;-1:-1:-1;;;;;29758:10:96;;;;:40;;14966:18:160;;29758:54:96;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;29696:116;;;;29847:19;29831:12;:35;29827:138;;29893:57;;-1:-1:-1;;;29893:57:96;;;;;15535:25:160;;;15576:18;;;15569:34;;;15508:18;;29893:57:96;15361:248:160;29827:138:96;29990:9;:23;;;-1:-1:-1;;;;;29982:31:96;:5;-1:-1:-1;;;;;29982:31:96;;29978:96;;;30040:19;;-1:-1:-1;;;30040:19:96;;-1:-1:-1;;;;;2535:31:160;;30040:19:96;;;2517:50:160;2490:18;;30040:19:96;2373:200:160;29978:96:96;29682:402;;29627:457;30134:32;;;;:18;;;:32;;;;;;;;;:64;;-1:-1:-1;;30134:64:96;30176:22;30134:64;;;;;30208:42;:68;;-1:-1:-1;;;;;30260:15:96;30208:68;-1:-1:-1;;;30208:68:96;;-1:-1:-1;;30208:68:96;;;;;;;;;;30292:170;;2517:50:160;;;30391:12:96;;30134:32;;30292:170;;2490:18:160;30292:170:96;;;;;;;28449:2020;;;;28358:2111;;:::o;22040:172::-;22113:7;22157:27;:25;:27::i;:::-;:48;;;22139:66;;-1:-1:-1;;;;;22139:15:96;;:66;:::i;3420:783:92:-;3780:7;3251:21:143;:19;:21::i;:::-;3806:390:92::1;3859:6;3893:12;3942:21;3991:12;4036:17;4085:16;4128:11;4170:15;3806:30;:390::i;:::-;3799:397;;3293:20:143::0;1805:1;-1:-1:-1;;;;;;;;;;;3969:23:143;3716:283;3293:20;3420:783:92;;;;;;;;;;:::o;11630:674:96:-;11758:31;11792:27;:25;:27::i;:::-;11758:61;-1:-1:-1;;;;;;11834:29:96;;11830:106;;11886:39;;-1:-1:-1;;;11886:39:96;;-1:-1:-1;;;;;4859:32:160;;11886:39:96;;;4841:51:160;4814:18;;11886:39:96;4671:227:160;11830:106:96;11950:33;;;;:19;;;:33;;;;;:39;-1:-1:-1;;;;;11950:39:96;966:10:142;11950:55:96;11946:124;;966:10:142;12046:12:96;12028:31;;-1:-1:-1;;;12028:31:96;;-1:-1:-1;;;;;4859:32:160;;;12028:31:96;;;4841:51:160;4814:18;;12028:31:96;4671:227:160;11946:124:96;12080:24;12107:33;;;:19;;;:33;;;;;;;;-1:-1:-1;;;;;12150:51:96;;;-1:-1:-1;;;;;;12150:51:96;;;;;;;12217:80;;12107:33;;;;;12127:12;;12217:80;;;11748:556;;11630:674;;:::o;9708:743::-;9792:31;9826:27;:25;:27::i;:::-;9889:10;;:37;;-1:-1:-1;;;9889:37:96;;;;;4510:25:160;;;9889:10:96;;-1:-1:-1;9864:22:96;;-1:-1:-1;;;;;9889:10:96;;;;:23;;4483:18:160;;9889:37:96;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;9889:37:96;;;;;;;;;;;;:::i;:::-;:44;;-1:-1:-1;9957:25:96;9947:6;:35;;;;;;;;:::i;:::-;;9943:103;;10028:6;10005:30;;-1:-1:-1;;;10005:30:96;;;;;;;;:::i;9943:103::-;10060:33;;;;:19;;;:33;;;;;:39;-1:-1:-1;;;;;10060:39:96;966:10:142;10060:55:96;10056:124;;966:10:142;10156:12:96;887:96:142;10056:124:96;10190:23;10216:33;;;:19;;;:33;;;;;;-1:-1:-1;;;;;10216:33:96;;10260:117;;-1:-1:-1;10327:33:96;;;;:19;;;:33;;;;;:39;-1:-1:-1;;;;;10327:39:96;10260:117;10387:57;10414:15;10431:12;10387:26;:57::i;15448:1473::-;15548:7;3251:21:143;:19;:21::i;:::-;15567:31:96::1;15601:27;:25;:27::i;:::-;15754:10:::0;;:49:::1;::::0;-1:-1:-1;;;15754:49:96;;15023:10:160;15011:23;;15754:49:96::1;::::0;::::1;14993:42:160::0;15754:10:96;;-1:-1:-1;15731:20:96::1;::::0;-1:-1:-1;;;;;15754:10:96;;::::1;::::0;:35:::1;::::0;14966:18:160;;15754:49:96::1;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;15842:10:::0;;:37:::1;::::0;-1:-1:-1;;;15842:37:96;;::::1;::::0;::::1;4510:25:160::0;;;15731:72:96;;-1:-1:-1;15813:26:96::1;::::0;-1:-1:-1;;;;;15842:10:96;;::::1;::::0;:23:::1;::::0;4483:18:160;;15842:37:96::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;::::0;;::::1;-1:-1:-1::0;;15842:37:96::1;::::0;::::1;;::::0;::::1;::::0;;;::::1;::::0;::::1;:::i;:::-;15813:66;;16068:29;16084:12;16068:15;:29::i;:::-;16063:80;;-1:-1:-1::0;16120:12:96;-1:-1:-1;16113:19:96::1;::::0;-1:-1:-1;16113:19:96::1;16063:80;16153:13;16169:33:::0;;;:19:::1;::::0;::::1;:33;::::0;;;;;;;:39;16244:19:::1;::::0;::::1;:33:::0;;;;;;;-1:-1:-1;;;;;16169:39:96;;::::1;::::0;16244:33:::1;::::0;16394:83:::1;;-1:-1:-1::0;16461:5:96;16394:83:::1;16618:25;16598:16:::0;;:45:::1;::::0;::::1;;;;;;:::i;:::-;::::0;16594:133:::1;;16659:57;16686:15;16703:12;16659:26;:57::i;:::-;16829:55;16837:5;16844:39;16858:9;:24;;;16844:13;:39::i;:::-;16829:7;:55::i;:::-;-1:-1:-1::0;16902:12:96;;-1:-1:-1;;;;3282:1:143::1;3293:20:::0;1805:1;-1:-1:-1;;;;;;;;;;;3969:23:143;3716:283;3293:20;15448:1473:96;;;:::o;21291:205::-;21383:7;21409:27;:25;:27::i;:::-;:36;:80;;-1:-1:-1;;;21409:80:96;;15023:10:160;15011:23;;21409:80:96;;;14993:42:160;-1:-1:-1;;;;;21409:36:96;;;;:66;;14966:18:160;;21409:80:96;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;24470:313::-;24559:7;24568;24587:31;24621:27;:25;:27::i;:::-;24679:42;;;;:28;;;:42;;;;;;;;;24723:29;;;;:43;;;;;;;-1:-1:-1;;;;;24679:42:96;;;;24470:313;-1:-1:-1;;;24470:313:96:o;10536:240::-;10687:82;10722:12;10736:18;10756:12;10687:34;:82::i;2432:192:92:-;8870:21:140;4302:15;;-1:-1:-1;;;4302:15:140;;;;4301:16;;-1:-1:-1;;;;;4348:14:140;4158:30;4726:16;;:34;;;;;4746:14;4726:34;4706:54;;4770:17;4790:11;-1:-1:-1;;;;;4790:16:140;4805:1;4790:16;:50;;;;-1:-1:-1;4818:4:140;4810:25;:30;4790:50;4770:70;;4856:12;4855:13;:30;;;;;4873:12;4872:13;4855:30;4851:91;;;4908:23;;-1:-1:-1;;;4908:23:140;;;;;;;;;;;4851:91;4951:18;;-1:-1:-1;;4951:18:140;4968:1;4951:18;;;4979:67;;;;5013:22;;-1:-1:-1;;;;5013:22:140;-1:-1:-1;;;5013:22:140;;;4979:67;2569:48:92::1;2601:8;2611:5;2569:31;:48::i;:::-;5070:14:140::0;5066:101;;;5100:23;;-1:-1:-1;;;;5100:23:140;;;5142:14;;-1:-1:-1;2517:50:160;;5142:14:140;;2505:2:160;2490:18;5142:14:140;;;;;;;5066:101;4092:1081;;;;;2432:192:92;;:::o;22308:720:96:-;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;22441:27:96;:25;:27::i;:::-;22485:536;;;;;;;;22531:10;;-1:-1:-1;;;;;22531:10:96;;;22485:536;;22531:10;22575:21;;;22485:536;;;;22630:21;;;;22485:536;;;;;;;22687:23;;;;-1:-1:-1;;;;;22687:23:96;;22485:536;;;;-1:-1:-1;;;22750:27:96;;;;22485:536;;;;-1:-1:-1;;;22821:25:96;;22485:536;;;;;;22882:22;;;;22485:536;;;;22936:19;;;;;;;22485:536;;;;22989:21;;;;;22531:10;22485:536;;;;;-1:-1:-1;;22308:720:96:o;4302:321:92:-;4475:7;3251:21:143;:19;:21::i;:::-;4501:115:92::1;4545:12:::0;966:10:142;4573:16:92::1;4591:15;4501:30;:115::i;:::-;4494:122;;3293:20:143::0;1805:1;-1:-1:-1;;;;;;;;;;;3969:23:143;3716:283;3293:20;4302:321:92;;;;;:::o;23669:282:96:-;23758:7;23767;23786:31;23820:27;:25;:27::i;:::-;23865:33;;;;:19;;;:33;;;;;;;;;23900:29;;;;:43;;;;;;;-1:-1:-1;;;;;23865:33:96;;;;23669:282;-1:-1:-1;;;23669:282:96:o;12395:691::-;-1:-1:-1;;;;;12527:29:96;;12523:106;;12579:39;;-1:-1:-1;;;12579:39:96;;-1:-1:-1;;;;;4859:32:160;;12579:39:96;;;4841:51:160;4814:18;;12579:39:96;4671:227:160;12523:106:96;12639:31;12673:27;:25;:27::i;:::-;12715:32;;;;:18;;;:32;;;;;:38;12639:61;;-1:-1:-1;;;;;;12715:38:96;;;;;966:10:142;12715:54:96;12711:123;;966:10:142;12810:12:96;887:96:142;12711:123:96;12844:24;12871:42;;;:28;;;:42;;;;;;;;-1:-1:-1;;;;;12923:60:96;;;-1:-1:-1;;;;;;12923:60:96;;;;;;;12999:80;;12871:42;;;;;12900:12;;12999:80;;;12513:573;;12395:691;;:::o;3326:384:143:-;-1:-1:-1;;;;;;;;;;;3526:9:143;;-1:-1:-1;;3526:20:143;3522:88;;3569:30;;-1:-1:-1;;;3569:30:143;;;;;;;;;;;3522:88;1847:1;3684:19;;3326:384::o;5745:240:96:-;5937:32;;5745:240::o;40068:1371::-;40158:31;40192:27;:25;:27::i;:::-;40230:26;40259:32;;;:18;;;:32;;;;;;40230:61;;;;;;;;;;40158;;-1:-1:-1;40230:26:96;;:61;;40259:32;40230:61;;;;;;;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;;;;-1:-1:-1;;;;;40230:61:96;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;40230:61:96;;;;;;;-1:-1:-1;;;40230:61:96;;;;;;;;-1:-1:-1;;;40230:61:96;;;;;;;;-1:-1:-1;;;40230:61:96;;;;;;;;;;;;40324:22;;;;40561:10;;:34;;-1:-1:-1;;;40561:34:96;;;;40230:61;;-1:-1:-1;40324:22:96;;40561:10;;;:32;;:34;;;;;40230:61;;40561:34;;;;;:10;:34;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;40539:9;:19;;;:56;;;;:::i;:::-;-1:-1:-1;;;;;40521:74:96;:15;:74;40517:162;;;40618:50;;-1:-1:-1;;;40618:50:96;;-1:-1:-1;;;;;40651:15:96;2535:31:160;40618:50:96;;;2517::160;2490:18;;40618:50:96;2373:200:160;40517:162:96;40800:32;;;;:18;;;:32;;;;;;;;40793:39;;-1:-1:-1;;;;;;40793:39:96;;;;;;;;;;;;;;40869:28;;;:42;;;;;;;-1:-1:-1;;;;;;40921:49:96;;;;;-1:-1:-1;;;;;40869:42:96;;40981:93;;-1:-1:-1;41048:15:96;;;;40981:93;41085:25;41112:21;41149:71;41176:15;41193:12;41207;41149:26;:71::i;:::-;41084:136;;;;41272:57;41280:9;:15;;;41297:31;41311:9;:16;;;41297:13;:31::i;41272:57::-;41345:87;;;15535:25:160;;;15591:2;15576:18;;15569:34;;;41385:12:96;;41371;;41345:87;;15508:18:160;41345:87:96;;;;;;;40148:1291;;;;;;40068:1371;:::o;3716:283:143:-;1805:1;-1:-1:-1;;;;;;;;;;;3969:23:143;3716:283::o;13317:1940:96:-;13471:4;13487:31;13521:27;:25;:27::i;:::-;13559:10;;:49;;-1:-1:-1;;;13559:49:96;;;;;4510:25:160;;;13559:10:96;;-1:-1:-1;;;;;;13559:10:96;;:35;;4483:18:160;;13559:49:96;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;13791:10:96;;:37;;-1:-1:-1;;;13791:37:96;;;;;4510:25:160;;;13762:26:96;;-1:-1:-1;;;;;;13791:10:96;;;;-1:-1:-1;13791:23:96;;4483:18:160;;13791:37:96;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;13791:37:96;;;;;;;;;;;;:::i;:::-;13762:66;;13946:29;13962:12;13946:15;:29::i;:::-;13941:72;;13998:4;13991:11;;;;;;13941:72;14089:33;;;;:19;;;:33;;;;;:39;-1:-1:-1;;;;;14089:39:96;966:10:142;14089:55:96;14085:124;;966:10:142;14185:12:96;887:96:142;14085:124:96;14351:33;;;;:19;;;:33;;;;;:50;14329:19;;;;:72;;-1:-1:-1;;;14351:50:96;;-1:-1:-1;;;;;14351:50:96;;14329:72;:::i;:::-;-1:-1:-1;;;;;14293:108:96;:9;:17;;;-1:-1:-1;;;;;14293:108:96;;14276:212;;;14459:17;;;;14433:44;;-1:-1:-1;;;14433:44:96;;-1:-1:-1;;;;;2535:31:160;;;14433:44:96;;;2517:50:160;2490:18;;14433:44:96;2373:200:160;14276:212:96;14593:20;14627:18;14623:200;;;14677:41;14691:12;14705;14677:13;:41::i;:::-;14661:57;;14623:200;;;-1:-1:-1;14765:33:96;;;;:19;;;:33;;;;;:47;;;-1:-1:-1;;;;;14765:47:96;14623:200;14850:19;;;;14927:24;;;;14833:14;;-1:-1:-1;;;;;14850:19:96;;:35;;14913:39;;:13;:39::i;:::-;14986:19;;;;15086:17;;;;;14850:306;;;;;;-1:-1:-1;;;;;;14850:306:96;;;;;;19378:25:160;;;;-1:-1:-1;;;;;19476:15:160;;;19456:18;;;19449:43;;;19508:18;;;19501:43;19580:15;;;19560:18;;;19553:43;19633:15;;19612:19;;;19605:44;19350:19;;14850:306:96;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;14833:323;;15214:6;15167:1;:29;;:43;15197:12;15167:43;;;;;;;;;;;;:53;;;;;;;:::i;:::-;;;;-1:-1:-1;;15239:10:96;;;13317:1940;-1:-1:-1;;;;;;;13317:1940:96:o;41873:238::-;41957:4;41973:31;42007:27;:25;:27::i;:::-;42102:1;42051:33;;;:19;;:33;;-1:-1:-1;;42051:33:96;;;:39;-1:-1:-1;;;;;42051:39:96;:53;;;41873:238::o;17122:1507::-;17283:51;;-1:-1:-1;;;17283:51:96;;15023:10:160;15011:23;;17283:51:96;;;14993:42:160;17206:6:96;;;;;;-1:-1:-1;;;;;4201:42:96;17283:37;;14966:18:160;;17283:51:96;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;17283:51:96;;;;;;;;;;;;:::i;:::-;17224:110;;;;17349:5;17344:64;;17377:20;;-1:-1:-1;;;17377:20:96;;;;;;;;;;;17344:64;17418:31;17452:27;:25;:27::i;:::-;17594:21;;;;17565:25;;17418:61;;-1:-1:-1;17565:50:96;17561:139;;17663:25;;17638:51;;-1:-1:-1;;;17638:51:96;;;;;4510:25:160;;;;4483:18;;17638:51:96;4364:177:160;17561:139:96;17889:31;;;;-1:-1:-1;;;;;17889:45:96;;17885:146;;17988:31;;;;17957:63;;-1:-1:-1;;;17957:63:96;;-1:-1:-1;;;;;4859:32:160;;;17957:63:96;;;4841:51:160;4814:18;;17957:63:96;4671:227:160;17885:146:96;18042:26;18070:13;18099:17;:47;18147:11;:19;;;18099:68;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;18041:126;;;;18197:18;18181:12;:34;18177:128;;18238:56;;-1:-1:-1;;;18238:56:96;;;;;15535:25:160;;;15576:18;;;15569:34;;;15508:18;;18238:56:96;15361:248:160;18177:128:96;18328:33;;;;:19;;;:33;;;;;:47;;;-1:-1:-1;;;;;18328:47:96;;;18319:56;;;;18315:284;;;18391:33;;;;:19;;;:33;;;;;;;;;:47;;:56;;-1:-1:-1;;18391:56:96;-1:-1:-1;;;;;18391:56:96;;;;;;;;18466:35;;2517:50:160;;;18391:33:96;;18466:35;;2490:18:160;18466:35:96;;;;;;;18315:284;;;-1:-1:-1;18541:33:96;;;;:19;;;:33;;;;;:47;;;-1:-1:-1;;;;;18541:47:96;18315:284;18616:6;17122:1507;-1:-1:-1;;;;;;;17122:1507:96:o;31782:3053::-;31933:4;31949:31;31983:27;:25;:27::i;:::-;32021:26;32050:32;;;:18;;;:32;;;;;;32021:61;;;;;;;;;;31949;;-1:-1:-1;32021:26:96;;:61;;32050:32;32021:61;;;;;;;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;;;;;;;-1:-1:-1;;;;;32021:61:96;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;32021:61:96;;;;;;;-1:-1:-1;;;32021:61:96;;;;;;;;-1:-1:-1;;;32021:61:96;;;;;;;;-1:-1:-1;;;32021:61:96;;;;;;;;;;;;32115:22;;;;32176:10;;:37;;-1:-1:-1;;;32176:37:96;;;;;4510:25:160;;;32115:22:96;;-1:-1:-1;32115:22:96;-1:-1:-1;;32176:10:96;;;;:23;;4483:18:160;;32176:37:96;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;32176:37:96;;;;;;;;;;;;:::i;:::-;32147:66;-1:-1:-1;32290:22:96;32270:16;;:42;;;;;;;;:::i;:::-;;32266:120;;32358:16;;32335:40;;-1:-1:-1;;;32335:40:96;;;;32358:16;32335:40;;;:::i;32266:120::-;32481:15;;;;-1:-1:-1;;;;;32481:31:96;966:10:142;32481:31:96;32477:542;;32631:33;;;;:19;;;:33;;;;;:39;-1:-1:-1;;;;;32631:39:96;966:10:142;32631:55:96;32627:132;;966:10:142;32731:12:96;887:96:142;32627:132:96;32854:33;;;;:19;;;:33;;;;;:50;32832:19;;;;:72;;-1:-1:-1;;;32854:50:96;;-1:-1:-1;;;;;32854:50:96;;32832:72;:::i;:::-;-1:-1:-1;;;;;32794:110:96;:15;:110;32773:236;;;32944:50;;-1:-1:-1;;;32944:50:96;;-1:-1:-1;;;;;32977:15:96;2535:31:160;32944:50:96;;;2517::160;2490:18;;32944:50:96;2373:200:160;32773:236:96;33029:23;33055:42;;;:28;;;:42;;;;;;-1:-1:-1;;;;;33055:42:96;33131:22;33111:16;;:42;;;;;;;;:::i;:::-;;33107:1722;;33274:23;;;;33252:19;;;;:45;;-1:-1:-1;;;;;33274:23:96;;33252:45;:::i;:::-;-1:-1:-1;;;;;33234:63:96;:15;:63;33230:159;;;33324:50;;-1:-1:-1;;;33324:50:96;;-1:-1:-1;;;;;33357:15:96;2535:31:160;33324:50:96;;;2517::160;2490:18;;33324:50:96;2373:200:160;33230:159:96;33407:18;33403:201;;;33548:41;33562:12;33576;33548:13;:41::i;:::-;;33403:201;33849:32;;;;:18;;;:32;;;;;:72;;-1:-1:-1;;33849:72:96;33891:30;33849:72;;;33986:27;;34094:16;;;;34075;;;;-1:-1:-1;;;;;33986:27:96;;;;:74;;34061:12;;34075:35;;34094:16;34075:35;:::i;:::-;33986:125;;-1:-1:-1;;;;;;33986:125:96;;;;;;;;;;21641:25:160;;;;-1:-1:-1;;;;;21702:31:160;21682:18;;;21675:59;21614:18;;33986:125:96;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;33937:32:96;;;;:18;;;:32;;;;;:44;;33936:175;;-1:-1:-1;;;;;33936:175:96;;;-1:-1:-1;;;33936:175:96;-1:-1:-1;;;;;33936:175:96;;;;;;;;;;34159:74;34192:9;34203:15;33956:12;34159:32;:74::i;:::-;34126:107;;34322:12;34294;34253:83;;;;;;;;;;34358:10;;;-1:-1:-1;34350:19:96;;-1:-1:-1;;;;;34350:19:96;33107:1722;34410:25;34390:16;;:45;;;;;;;;:::i;:::-;;34386:443;;34451:74;34484:9;34495:15;34512:12;34451:32;:74::i;:::-;;34539:39;34565:12;34539:25;:39::i;:::-;34736:4;34729:11;;;;;;;;;34386:443;34801:16;;34778:40;;-1:-1:-1;;;34778:40:96;;;;34801:16;34778:40;;;:::i;30800:322::-;30966:73;30992:12;31006:18;31026:12;30966:25;:73::i;:::-;30961:155;;31062:43;;-1:-1:-1;;;31062:43:96;;;;;4510:25:160;;;4483:18;;31062:43:96;4364:177:160;19039:2162:96;19395:7;19414:31;19448:27;:25;:27::i;:::-;19578;;;;19414:61;;-1:-1:-1;19578:27:96;-1:-1:-1;;;19578:27:96;;;;;19558:47;;;;;:114;;-1:-1:-1;4058:5:96;19625:47;;;;19558:114;19541:213;;;19704:39;;-1:-1:-1;;;19704:39:96;;2752:6:160;2740:19;;19704:39:96;;;2722:38:160;2695:18;;19704:39:96;2578:188:160;19541:213:96;19787:23;;;;-1:-1:-1;;;;;19787:23:96;;;19768:42;;;;19764:121;;;19833:41;;-1:-1:-1;;;19833:41:96;;-1:-1:-1;;;;;2535:31:160;;19833:41:96;;;2517:50:160;2490:18;;19833:41:96;2373:200:160;19764:121:96;19969:1;:21;;;19955:11;:35;:74;;;;20008:1;:21;;;19994:11;:35;19955:74;19951:143;;;20052:31;;-1:-1:-1;;;20052:31:96;;;;;4510:25:160;;;4483:18;;20052:31:96;4364:177:160;19951:143:96;-1:-1:-1;;;;;20108:29:96;;20104:106;;20160:39;;-1:-1:-1;;;20160:39:96;;-1:-1:-1;;;;;4859:32:160;;20160:39:96;;;4841:51:160;4814:18;;20160:39:96;4671:227:160;20104:106:96;20263:19;20285:18;20291:11;20285:5;:18::i;:::-;20263:40;;20314:13;20330:26;20344:11;20330:13;:26::i;:::-;20314:42;;20366:20;20389:1;:10;;;;;;;;;;-1:-1:-1;;;;;20389:10:96;-1:-1:-1;;;;;20389:40:96;;20452:6;20486:12;20535:21;20584:12;20618:6;20389:246;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;20366:269;-1:-1:-1;20646:13:96;966:10:142;20646:28:96;;20727:5;20685:1;:19;;:33;20705:12;20685:33;;;;;;;;;;;:39;;;:47;;;;;-1:-1:-1;;;;;20685:47:96;;;;;-1:-1:-1;;;;;20685:47:96;;;;;;20796:17;20742:1;:19;;:33;20762:12;20742:33;;;;;;;;;;;:51;;;:71;;;;;;;;;;;;;;;;;;20876:16;20823:1;:19;;:33;20843:12;20823:33;;;;;;;;;;;:50;;;:69;;;;;-1:-1:-1;;;;;20823:69:96;;;;;-1:-1:-1;;;;;20823:69:96;;;;;;20952:1;20902;:19;;:33;20922:12;20902:33;;;;;;;;;;;:47;;;:51;;;;;-1:-1:-1;;;;;20902:51:96;;;;;-1:-1:-1;;;;;20902:51:96;;;;;;20999:15;20963:1;:19;;:33;20983:12;20963:33;;;;;;;;;;;;:51;;;;;-1:-1:-1;;;;;20963:51:96;;;;;-1:-1:-1;;;;;20963:51:96;;;;;;21095:5;-1:-1:-1;;;;;21030:134:96;21081:12;21030:134;21102:17;21121:16;21139:15;21030:134;;;;;;;23892:6:160;23880:19;;;;23862:38;;-1:-1:-1;;;;;23936:31:160;;;;23931:2;23916:18;;23909:59;-1:-1:-1;;;;;24004:32:160;23999:2;23984:18;;23977:60;23850:2;23835:18;;23664:379;21030:134:96;;;;;;;;-1:-1:-1;21182:12:96;19039:2162;-1:-1:-1;;;;;;;;;;;;19039:2162:96:o;42117:424::-;42219:31;42253:27;:25;:27::i;:::-;42291:15;42309:43;;;:29;;;:43;;;;;;;42362:50;;;42219:61;;-1:-1:-1;42423:33:96;42431:15;42309:43;42423:7;:33::i;:::-;42509:15;-1:-1:-1;;;;;42472:62:96;42495:12;42472:62;42526:7;42472:62;;;;4510:25:160;;4498:2;4483:18;;4364:177;42472:62:96;;;;;;;;42209:332;;42117:424;;:::o;5266:150:92:-;-1:-1:-1;;;;;;;;;;;5346:39:92;:63;;-1:-1:-1;;;;;5346:39:92;5399:2;5403:5;5346:52;:63::i;10782:325:96:-;10948:76;10977:12;10991:18;11011:12;10948:28;:76::i;:::-;10943:158;;11047:43;;-1:-1:-1;;;11047:43:96;;;;;4510:25:160;;;4483:18;;11047:43:96;4364:177:160;2683:259:92;6931:20:140;:18;:20::i;:::-;2846:31:92::1;2868:8;2846:21;:31::i;:::-;2887:48;2929:5;2887:41;:48::i;25714:2438:96:-:0;25909:7;25928:31;25962:27;:25;:27::i;:::-;25928:61;;25999:13;26015:38;26029:23;26035:16;26029:5;:23::i;26015:38::-;25999:54;;26128:29;26144:12;26128:15;:29::i;:::-;26123:97;;26180:29;;-1:-1:-1;;;26180:29:96;;;;;4510:25:160;;;4483:18;;26180:29:96;4364:177:160;26123:97:96;-1:-1:-1;;;;;26234:29:96;;26230:106;;26286:39;;-1:-1:-1;;;26286:39:96;;-1:-1:-1;;;;;4859:32:160;;26286:39:96;;;4841:51:160;4814:18;;26286:39:96;4671:227:160;26230:106:96;26463:10;;:37;;-1:-1:-1;;;26463:37:96;;;;;4510:25:160;;;26385::96;;;;-1:-1:-1;;;;;26463:10:96;;;;:23;;4483:18:160;;26463:37:96;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;26463:37:96;;;;;;;;;;;;:::i;:::-;26434:66;;26554:6;26535:9;:16;;;:25;;;;:::i;:::-;26514:46;;26626:1;:25;;;;;;;;;;-1:-1:-1;;;;;26626:25:96;26599:9;:24;;;:52;;;;:::i;:::-;-1:-1:-1;;;;;26578:73:96;:18;-1:-1:-1;;;;;26578:73:96;;26574:156;;;26678:37;;-1:-1:-1;;;26678:37:96;;-1:-1:-1;;;;;2535:31:160;;26678:37:96;;;2517:50:160;2490:18;;26678:37:96;2373:200:160;26574:156:96;-1:-1:-1;26798:10:96;;:74;;-1:-1:-1;;;26798:74:96;;;;;21641:25:160;;;-1:-1:-1;;;;;21702:31:160;;21682:18;;;21675:59;26751:12:96;;;;-1:-1:-1;;;;;26798:10:96;;;;:40;;21614:18:160;;26798:74:96;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;26750:122;;;;26883:20;26933:12;26947:5;26916:37;;;;;;;;24465:19:160;;;24540:3;24518:16;-1:-1:-1;;;;;;24514:51:160;24509:2;24500:12;;24493:73;24591:2;24582:12;;24310:290;26916:37:96;;;;-1:-1:-1;;26916:37:96;;;;;;;;;26906:48;;26916:37;26906:48;;;;27216:32;;;;:18;;;:32;;;;;:70;;26906:48;;-1:-1:-1;27258:28:96;;-1:-1:-1;;27216:70:96;27258:28;;27216:70;;;;;27337:16;27296:1;:18;;:32;27315:12;27296:32;;;;;;;;;;;:38;;;:57;;;;;-1:-1:-1;;;;;27296:57:96;;;;;-1:-1:-1;;;;;27296:57:96;;;;;;27411:12;27363:1;:18;;:32;27382:12;27363:32;;;;;;;;;;;:45;;:60;;;;27475:6;27433:1;:18;;:32;27452:12;27433:32;;;;;;;;;;;:39;;;:48;;;;;-1:-1:-1;;;;;27433:48:96;;;;;-1:-1:-1;;;;;27433:48:96;;;;;;27536:1;27491;:18;;:32;27510:12;27491:32;;;;;;;;;;;:42;;;:46;;;;;-1:-1:-1;;;;;27491:46:96;;;;;-1:-1:-1;;;;;27491:46:96;;;;;;27596:5;27547:1;:18;;:32;27566:12;27547:32;;;;;;;;;;;:46;;;:54;;;;;-1:-1:-1;;;;;27547:54:96;;;;;-1:-1:-1;;;;;27547:54:96;;;;;;27658:1;27611;:18;;:32;27630:12;27611:32;;;;;;;;;;;:44;;;:48;;;;;-1:-1:-1;;;;;27611:48:96;;;;;-1:-1:-1;;;;;27611:48:96;;;;;;27714:15;27669:1;:28;;:42;27698:12;27669:42;;;;;;;;;;;;:60;;;;;-1:-1:-1;;;;;27669:60:96;;;;;-1:-1:-1;;;;;27669:60:96;;;;;;27888:16;-1:-1:-1;;;;;27745:371:96;27844:12;27804;27745:371;27925:5;27961:18;28010:6;28050:9;28090:15;27745:371;;;;;;;;;-1:-1:-1;;;;;24913:15:160;;;24895:34;;24965:15;;;24960:2;24945:18;;24938:43;25017:15;;;;25012:2;24997:18;;24990:43;25064:2;25049:18;;25042:34;;;;-1:-1:-1;;;;;25113:32:160;;;;25107:3;25092:19;;25085:61;24845:3;24830:19;;24605:547;27745:371:96;;;;;;;;28133:12;25714:2438;-1:-1:-1;;;;;;;;;;25714:2438:96:o;42547:1082::-;42700:7;42709;42728:31;42762:27;:25;:27::i;:::-;42800:25;42885:43;;;:29;;;:43;;;;;;42728:61;;-1:-1:-1;42800:25:96;;;42943:11;;42939:632;;42977:43;;;;:29;;;:43;;;;;;;;42970:50;;;43062:33;;;:19;;;:33;;;;;:51;4118:5;;43052:61;;-1:-1:-1;;;43062:51:96;;43051:104;43062:51;43052:7;:61;:::i;:::-;43051:104;;;;:::i;:::-;43035:120;;43279:13;43232:1;:29;;:43;43262:12;43232:43;;;;;;;;;;;;:60;;;;;;;:::i;:::-;;;;-1:-1:-1;43388:23:96;;-1:-1:-1;43398:13:96;43388:7;:23;:::i;:::-;43368:43;;43425;43433:15;43450:17;43425:7;:43::i;:::-;43525:15;-1:-1:-1;;;;;43488:72:96;43511:12;43488:72;43542:17;43488:72;;;;4510:25:160;;4498:2;4483:18;;4364:177;43488:72:96;;;;;;;;42939:632;-1:-1:-1;43589:17:96;;;;-1:-1:-1;42547:1082:96;-1:-1:-1;;;;;42547:1082:96:o;35046:1642::-;35210:7;35229:31;35263:27;:25;:27::i;:::-;35330:10;;35354:22;;;;;35330:47;;-1:-1:-1;;;35330:47:96;;35229:61;;-1:-1:-1;35301:26:96;;-1:-1:-1;;;;;35330:10:96;;;;:23;;:47;;;;4510:25:160;;;4498:2;4483:18;;4364:177;35330:47:96;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;35330:47:96;;;;;;;;;;;;:::i;:::-;35301:76;-1:-1:-1;35388:24:96;35459:30;35439:16;;:50;;;;;;;;:::i;:::-;;:115;;;-1:-1:-1;35529:25:96;35509:16;;:45;;;;;;;;:::i;:::-;;35439:115;35422:443;;;-1:-1:-1;35599:17:96;;;;35422:443;;;35657:22;35637:16;;:42;;;;;;;;:::i;:::-;;35633:232;;-1:-1:-1;35722:15:96;35633:232;35998:9;:19;;;-1:-1:-1;;;;;35977:40:96;:17;-1:-1:-1;;;;;35977:40:96;;35973:79;;36040:1;36033:8;;;;;;;35973:79;36079:19;;;;36156:16;;;;36062:14;;-1:-1:-1;;;;;36079:19:96;;:35;;36142:31;;:13;:31::i;:::-;36207:19;;;;36258;;;;36373:22;;;;;36353:43;;;;:19;;;:43;;;;;:57;;;36079:342;;;;;;-1:-1:-1;;;;;;36079:342:96;;;;;;19378:25:160;;;;-1:-1:-1;;;;;19476:15:160;;;19456:18;;;19449:43;19528:15;;;19508:18;;;19501:43;19580:15;;;19560:18;;;19553:43;36353:57:96;19612:19:160;;;19605:44;19350:19;;36079:342:96;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;36062:359;-1:-1:-1;;;;;;36436:29:96;;36432:93;;36499:9;:15;;;36481:33;;36432:93;36535:43;;;;:29;;;:43;;;;;;;;:52;;;36597:28;;;;:42;;;;;;:60;;-1:-1:-1;;;;;36597:60:96;;-1:-1:-1;;;;;;36597:60:96;;;;;;-1:-1:-1;36581:6:96;;-1:-1:-1;;35046:1642:96;;;;;:::o;4955:175:92:-;5034:7;5060:63;5117:5;-1:-1:-1;;;;;;;;;;;5060:39:92;-1:-1:-1;;;;;5060:39:92;;:56;:63::i;5482:209::-;5568:41;-1:-1:-1;;;;;;;;;;;5654:8:92;;:30;;-1:-1:-1;;;5654:30:92;;-1:-1:-1;;;;;10226:32:160;;;5654:30:92;;;10208:51:160;10275:18;;;10268:34;;;5654:8:92;;-1:-1:-1;5654:8:92;;;:13;;10181:18:160;;5654:30:92;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1303:160:152;1412:43;;-1:-1:-1;;;;;10226:32:160;;;1412:43:152;;;10208:51:160;10275:18;;;10268:34;;;1385:71:152;;1405:5;;1427:14;;;;;10181:18:160;;1412:43:152;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;1412:43:152;;;;;;;;;;;1385:19;:71::i;7084:141:140:-;8870:21;8560:40;-1:-1:-1;;;8560:40:140;;;;7146:73;;7191:17;;-1:-1:-1;;;7191:17:140;;;;;;;;;;;7146:73;7084:141::o;6044:756:96:-;6931:20:140;:18;:20::i;:::-;6167:24:96::1;:22;:24::i;:::-;6201:592;6256:16;;::::0;::::1;:8:::0;:16:::1;:::i;:::-;6306:27;::::0;::::1;;6367;::::0;::::1;;6430:29;::::0;;;::::1;::::0;::::1;;:::i;:::-;6499:33;::::0;;;::::1;::::0;::::1;;:::i;:::-;6570:31;::::0;;;::::1;::::0;::::1;;:::i;:::-;6636:28;::::0;::::1;;6696:25;::::0;;;::::1;::::0;::::1;;:::i;:::-;6755:8;:27;;;6201:31;:592::i;:::-;6044:756:::0;:::o;3001:320:92:-;6931:20:140;:18;:20::i;:::-;-1:-1:-1;;;;;;;;;;;;;;;;3214:28:92;::::1;3210:79;;3265:13;;-1:-1:-1::0;;;3265:13:92::1;;;;;;;;;;;3210:79;3298:16:::0;;-1:-1:-1;;;;;;3298:16:92::1;-1:-1:-1::0;;;;;3298:16:92;;;::::1;::::0;;;::::1;::::0;;3001:320::o;1332:150:86:-;1406:7;1432:43;1449:5;1456:10;1468:6;1432:16;:43::i;4059:629:152:-;4478:23;4504:33;-1:-1:-1;;;;;4504:27:152;;4532:4;4504:27;:33::i;:::-;4478:59;;4551:10;:17;4572:1;4551:22;;:57;;;;;4589:10;4578:30;;;;;;;;;;;;:::i;:::-;4577:31;4551:57;4547:135;;;4631:40;;-1:-1:-1;;;4631:40:152;;-1:-1:-1;;;;;4859:32:160;;4631:40:152;;;4841:51:160;4814:18;;4631:40:152;4671:227:160;2540:111:143;6931:20:140;:18;:20::i;:::-;2610:34:143::1;:32;:34::i;6859:2126:96:-:0;6931:20:140;:18;:20::i;:::-;7282:31:96::1;7316:27;:25;:27::i;:::-;7282:61:::0;-1:-1:-1;7357:29:96::1;::::0;::::1;::::0;;:87:::1;;-1:-1:-1::0;4058:5:96::1;7390:54;::::0;::::1;;7357:87;7353:179;;;7475:46;::::0;-1:-1:-1;;;7475:46:96;;2752:6:160;2740:19;;7475:46:96::1;::::0;::::1;2722:38:160::0;2695:18;;7475:46:96::1;2578:188:160::0;7353:179:96::1;7566:18;7545;:39;7541:115;;;7607:38;::::0;-1:-1:-1;;;7607:38:96;;::::1;::::0;::::1;4510:25:160::0;;;4483:18;;7607:38:96::1;4364:177:160::0;7541:115:96::1;7669:27;::::0;::::1;::::0;;:86:::1;;-1:-1:-1::0;3996:2:96::1;7700:55;::::0;::::1;;7669:86;7665:178;;;7786:46;::::0;-1:-1:-1;;;7786:46:96;;691:4:160;679:17;;7786:46:96::1;::::0;::::1;661:36:160::0;634:18;;7786:46:96::1;519:184:160::0;7665:178:96::1;-1:-1:-1::0;;;;;7856:30:96;::::1;7852:81;;7909:13;;-1:-1:-1::0;;;7909:13:96::1;;;;;;;;;;;7852:81;-1:-1:-1::0;;;;;7946:39:96;::::1;7942:90;;8008:13;;-1:-1:-1::0;;;8008:13:96::1;;;;;;;;;;;7942:90;8180:7;-1:-1:-1::0;;;;;8180:29:96::1;;:31;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;8157:54:96::1;:20;-1:-1:-1::0;;;;;8157:54:96::1;;8153:137;;;8234:45;::::0;-1:-1:-1;;;8234:45:96;;-1:-1:-1;;;;;2535:31:160;;8234:45:96::1;::::0;::::1;2517:50:160::0;2490:18;;8234:45:96::1;2373:200:160::0;8153:137:96::1;8303:19;8326:1;8303:24:::0;8299:87:::1;;8350:25;;-1:-1:-1::0;;;8350:25:96::1;;;;;;;;;;;8299:87;8399:18:::0;8395:115:::1;;8454:45;::::0;-1:-1:-1;;;8454:45:96;;::::1;::::0;::::1;4510:25:160::0;;;4483:18;;8454:45:96::1;4364:177:160::0;8395:115:96::1;8520:20:::0;;-1:-1:-1;;;;;8520:20:96;;::::1;-1:-1:-1::0;;;;;;8520:20:96;;::::1;;::::0;;;8550:21;::::1;:42:::0;;;;8602:21:::1;::::0;::::1;:42:::0;;;;8654:23:::1;::::0;::::1;:46:::0;;-1:-1:-1;;;8774:50:96::1;::::0;;::::1;::::0;;;::::1;-1:-1:-1::0;;;;8710:54:96::1;::::0;;::::1;-1:-1:-1::0;;;8710:54:96::1;-1:-1:-1::0;;8710:54:96;;;-1:-1:-1;;;;;8654:46:96;;::::1;8710:54:::0;;;;;;;::::1;8774:50:::0;;;::::1;::::0;;;::::1;::::0;;;8834:22:::1;::::0;::::1;:44:::0;8888:19:::1;::::0;::::1;:38:::0;;;;;::::1;::::0;;;::::1;;::::0;;;8936:21:::1;::::0;;::::1;:42:::0;6859:2126::o;2254:464:86:-;2415:30;;-1:-1:-1;;;2415:30:86;;2439:4;2415:30;;;4841:51:160;2372:7:86;;;;-1:-1:-1;;;;;2415:15:86;;;;;4814:18:160;;2415:30:86;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;2391:54;-1:-1:-1;2455:51:86;-1:-1:-1;;;;;2455:22:86;;2478:4;2492;2499:6;2455:22;:51::i;:::-;2539:30;;-1:-1:-1;;;2539:30:86;;2563:4;2539:30;;;4841:51:160;2516:20:86;;-1:-1:-1;;;;;2539:15:86;;;;;4814:18:160;;2539:30:86;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;2516:53;;2603:13;2588:12;:28;2580:85;;;;-1:-1:-1;;;2580:85:86;;26763:2:160;2580:85:86;;;26745:21:160;26802:2;26782:18;;;26775:30;26841:34;26821:18;;;26814:62;-1:-1:-1;;;26892:18:160;;;26885:42;26944:19;;2580:85:86;26561:408:160;2580:85:86;2683:28;2698:13;2683:12;:28;:::i;:::-;2676:35;2254:464;-1:-1:-1;;;;;;2254:464:86:o;2705:151:153:-;2780:12;2811:38;2833:6;2841:4;2847:1;2811:21;:38::i;2657:183:143:-;6931:20:140;:18;:20::i;1702:188:152:-;1829:53;;-1:-1:-1;;;;;27232:15:160;;;1829:53:152;;;27214:34:160;27284:15;;;27264:18;;;27257:43;27316:18;;;27309:34;;;1802:81:152;;1822:5;;1844:18;;;;;27149::160;;1829:53:152;26974:375:160;3180:392:153;3279:12;3331:5;3307:21;:29;3303:108;;;3359:41;;-1:-1:-1;;;3359:41:153;;3394:4;3359:41;;;4841:51:160;4814:18;;3359:41:153;4671:227:160;3303:108:153;3421:12;3435:23;3462:6;-1:-1:-1;;;;;3462:11:153;3481:5;3488:4;3462:31;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3420:73;;;;3510:55;3537:6;3545:7;3554:10;4769:12;4798:7;4793:408;;4821:19;4829:10;4821:7;:19::i;:::-;4793:408;;;5045:17;;:22;:49;;;;-1:-1:-1;;;;;;5071:18:153;;;:23;5045:49;5041:119;;;5121:24;;-1:-1:-1;;;5121:24:153;;-1:-1:-1;;;;;4859:32:160;;5121:24:153;;;4841:51:160;4814:18;;5121:24:153;4671:227:160;5041:119:153;-1:-1:-1;5180:10:153;5173:17;;5743:516;5874:17;;:21;5870:383;;6102:10;6096:17;6158:15;6145:10;6141:2;6137:19;6130:44;5870:383;6225:17;;-1:-1:-1;;;6225:17:153;;;;;;;;;;;14:163:160;81:20;;141:10;130:22;;120:33;;110:61;;167:1;164;157:12;182:252;249:6;257;310:2;298:9;289:7;285:23;281:32;278:52;;;326:1;323;316:12;278:52;362:9;349:23;339:33;;391:37;424:2;413:9;409:18;391:37;:::i;:::-;381:47;;182:252;;;;;:::o;708:118::-;794:5;787:13;780:21;773:5;770:32;760:60;;816:1;813;806:12;831:381;904:6;912;920;973:2;961:9;952:7;948:23;944:32;941:52;;;989:1;986;979:12;941:52;1025:9;1012:23;1002:33;;1085:2;1074:9;1070:18;1057:32;1098:28;1120:5;1098:28;:::i;:::-;1145:5;-1:-1:-1;1169:37:160;1202:2;1187:18;;1169:37;:::i;:::-;1159:47;;831:381;;;;;:::o;1217:180::-;1276:6;1329:2;1317:9;1308:7;1304:23;1300:32;1297:52;;;1345:1;1342;1335:12;1297:52;-1:-1:-1;1368:23:160;;1217:180;-1:-1:-1;1217:180:160:o;2771:127::-;2832:10;2827:3;2823:20;2820:1;2813:31;2863:4;2860:1;2853:15;2887:4;2884:1;2877:15;2903:146;2990:1;2983:5;2980:12;2970:46;;2996:18;;:::i;:::-;3025;;2903:146::o;3054:784::-;3202:4;3244:3;3233:9;3229:19;3221:27;;3257:57;3304:9;3295:6;3289:13;3257:57;:::i;:::-;3399:1;3395;3390:3;3386:11;3382:19;3374:4;3366:6;3362:17;3356:24;3352:50;3345:4;3334:9;3330:20;3323:80;3459:4;3451:6;3447:17;3441:24;3434:4;3423:9;3419:20;3412:54;3513:4;3505:6;3501:17;3495:24;-1:-1:-1;;;;;3612:2:160;3598:12;3594:21;3587:4;3576:9;3572:20;3565:51;3684:2;3676:4;3668:6;3664:17;3658:24;3654:33;3647:4;3636:9;3632:20;3625:63;3756:2;3748:4;3740:6;3736:17;3730:24;3726:33;3719:4;3708:9;3704:20;3697:63;3828:2;3820:4;3812:6;3808:17;3802:24;3798:33;3791:4;3780:9;3776:20;3769:63;;;3054:784;;;;:::o;3843:129::-;-1:-1:-1;;;;;3921:5:160;3917:30;3910:5;3907:41;3897:69;;3962:1;3959;3952:12;3977:132;4044:20;;4073:30;4044:20;4073:30;:::i;4114:245::-;4172:6;4225:2;4213:9;4204:7;4200:23;4196:32;4193:52;;;4241:1;4238;4231:12;4193:52;4280:9;4267:23;4299:30;4323:5;4299:30;:::i;5085:127::-;5146:10;5141:3;5137:20;5134:1;5127:31;5177:4;5174:1;5167:15;5201:4;5198:1;5191:15;5217:257;5289:4;5283:11;;;5321:17;;-1:-1:-1;;;;;5353:34:160;;5389:22;;;5350:62;5347:88;;;5415:18;;:::i;:::-;5451:4;5444:24;5217:257;:::o;5479:255::-;5551:2;5545:9;5593:6;5581:19;;-1:-1:-1;;;;;5615:34:160;;5651:22;;;5612:62;5609:88;;;5677:18;;:::i;5739:275::-;5810:2;5804:9;5875:2;5856:13;;-1:-1:-1;;5852:27:160;5840:40;;-1:-1:-1;;;;;5895:34:160;;5931:22;;;5892:62;5889:88;;;5957:18;;:::i;:::-;5993:2;5986:22;5739:275;;-1:-1:-1;5739:275:160:o;6019:186::-;6067:4;-1:-1:-1;;;;;6092:6:160;6089:30;6086:56;;;6122:18;;:::i;:::-;-1:-1:-1;6188:2:160;6167:15;-1:-1:-1;;6163:29:160;6194:4;6159:40;;6019:186::o;6210:462::-;6252:5;6305:3;6298:4;6290:6;6286:17;6282:27;6272:55;;6323:1;6320;6313:12;6272:55;6359:6;6346:20;6390:48;6406:31;6434:2;6406:31;:::i;:::-;6390:48;:::i;:::-;6463:2;6454:7;6447:19;6509:3;6502:4;6497:2;6489:6;6485:15;6481:26;6478:35;6475:55;;;6526:1;6523;6516:12;6475:55;6591:2;6584:4;6576:6;6572:17;6565:4;6556:7;6552:18;6539:55;6639:1;6614:16;;;6632:4;6610:27;6603:38;;;;6618:7;6210:462;-1:-1:-1;;;6210:462:160:o;6677:131::-;-1:-1:-1;;;;;6752:31:160;;6742:42;;6732:70;;6798:1;6795;6788:12;6813:134;6881:20;;6910:31;6881:20;6910:31;:::i;6952:1105::-;7010:5;7058:4;7046:9;7041:3;7037:19;7033:30;7030:50;;;7076:1;7073;7066:12;7030:50;7098:22;;:::i;:::-;7089:31;;7143:28;7161:9;7143:28;:::i;:::-;7136:5;7129:43;7191:2;7244;7233:9;7229:18;7216:32;-1:-1:-1;;;;;7308:2:160;7300:6;7297:14;7294:34;;;7324:1;7321;7314:12;7294:34;7362:6;7351:9;7347:22;7337:32;;7407:3;7400:4;7396:2;7392:13;7388:23;7378:51;;7425:1;7422;7415:12;7378:51;7461:2;7448:16;7483:2;7479;7476:10;7473:36;;;7489:18;;:::i;:::-;7535:2;7532:1;7528:10;7518:20;;7558:28;7582:2;7578;7574:11;7558:28;:::i;:::-;7620:15;;;7690:11;;;7686:20;;;7651:12;;;;7718:15;;;7715:35;;;7746:1;7743;7736:12;7715:35;7770:11;;;;7790:223;7806:6;7801:3;7798:15;7790:223;;;7888:3;7875:17;7860:32;;7905:33;7930:7;7905:33;:::i;:::-;7951:20;;;7823:12;;;;7991;;;;7790:223;;;8045:5;8040:2;8033:5;8029:14;8022:29;;;;;;;6952:1105;;;;:::o;8062:159::-;8129:20;;8189:6;8178:18;;8168:29;;8158:57;;8211:1;8208;8201:12;8226:1294;8424:6;8432;8440;8448;8456;8464;8472;8480;8533:3;8521:9;8512:7;8508:23;8504:33;8501:53;;;8550:1;8547;8540:12;8501:53;8590:9;8577:23;-1:-1:-1;;;;;8660:2:160;8652:6;8649:14;8646:34;;;8676:1;8673;8666:12;8646:34;8699:49;8740:7;8731:6;8720:9;8716:22;8699:49;:::i;:::-;8689:59;;8801:2;8790:9;8786:18;8773:32;8757:48;;8830:2;8820:8;8817:16;8814:36;;;8846:1;8843;8836:12;8814:36;8869:51;8912:7;8901:8;8890:9;8886:24;8869:51;:::i;:::-;8859:61;;8973:2;8962:9;8958:18;8945:32;8929:48;;9002:2;8992:8;8989:16;8986:36;;;9018:1;9015;9008:12;8986:36;9041:64;9097:7;9086:8;9075:9;9071:24;9041:64;:::i;:::-;9031:74;;9158:2;9147:9;9143:18;9130:32;9114:48;;9187:2;9177:8;9174:16;9171:36;;;9203:1;9200;9193:12;9171:36;;9226:64;9282:7;9271:8;9260:9;9256:24;9226:64;:::i;:::-;9216:74;;;9309:38;9342:3;9331:9;9327:19;9309:38;:::i;:::-;9299:48;;9366:38;9399:3;9388:9;9384:19;9366:38;:::i;:::-;9356:48;;9451:3;9440:9;9436:19;9423:33;9413:43;;9475:39;9509:3;9498:9;9494:19;9475:39;:::i;:::-;9465:49;;8226:1294;;;;;;;;;;;:::o;9525:315::-;9593:6;9601;9654:2;9642:9;9633:7;9629:23;9625:32;9622:52;;;9670:1;9667;9660:12;9622:52;9706:9;9693:23;9683:33;;9766:2;9755:9;9751:18;9738:32;9779:31;9804:5;9779:31;:::i;:::-;9829:5;9819:15;;;9525:315;;;;;:::o;9845:184::-;9903:6;9956:2;9944:9;9935:7;9931:23;9927:32;9924:52;;;9972:1;9969;9962:12;9924:52;9995:28;10013:9;9995:28;:::i;10313:452::-;10448:6;10456;10500:9;10491:7;10487:23;10530:3;10526:2;10522:12;10519:32;;;10547:1;10544;10537:12;10519:32;10570:3;10593:2;10589;10585:11;10582:31;;;10609:1;10606;10599:12;10582:31;10632:9;;-1:-1:-1;10676:18:160;;10663:32;;-1:-1:-1;10704:31:160;10663:32;10704:31;:::i;11003:1054::-;11254:13;;-1:-1:-1;;;;;11250:39:160;11232:58;;11346:4;11334:17;;;11328:24;11306:20;;;11299:54;11409:4;11397:17;;;11391:24;11369:20;;;11362:54;11463:4;11451:17;;;11445:24;11219:3;11204:19;;;11478:53;;11510:20;;11445:24;-1:-1:-1;;;;;1562:30:160;1550:43;;1497:102;11478:53;;11580:4;11572:6;11568:17;11562:24;11595:55;11644:4;11633:9;11629:20;11613:14;1478:6;1467:18;1455:31;;1402:90;11595:55;;11699:4;11691:6;11687:17;11681:24;11714:54;11762:4;11751:9;11747:20;11731:14;506:4;495:16;483:29;;439:75;11714:54;;11824:4;11816:6;11812:17;11806:24;11799:4;11788:9;11784:20;11777:54;11880:4;11872:6;11868:17;11862:24;11895:72;11961:4;11950:9;11946:20;11930:14;-1:-1:-1;;;;;4628:31:160;4616:44;;4546:120;11895:72;-1:-1:-1;11986:6:160;12034:15;;;12028:22;12008:18;;;;12001:50;11003:1054;:::o;12062:383::-;12139:6;12147;12155;12208:2;12196:9;12187:7;12183:23;12179:32;12176:52;;;12224:1;12221;12214:12;12176:52;12260:9;12247:23;12237:33;;12317:2;12306:9;12302:18;12289:32;12279:42;;12371:2;12360:9;12356:18;12343:32;12384:31;12409:5;12384:31;:::i;:::-;12434:5;12424:15;;;12062:383;;;;;:::o;12450:221::-;12603:2;12588:18;;12615:50;12592:9;12647:6;12615:50;:::i;12676:160::-;12768:13;;12810:1;12800:12;;12790:40;;12826:1;12823;12816:12;12841:250;12926:1;12936:113;12950:6;12947:1;12944:13;12936:113;;;13026:11;;;13020:18;13007:11;;;13000:39;12972:2;12965:10;12936:113;;;-1:-1:-1;;13083:1:160;13065:16;;13058:27;12841:250::o;13096:441::-;13149:5;13202:3;13195:4;13187:6;13183:17;13179:27;13169:55;;13220:1;13217;13210:12;13169:55;13249:6;13243:13;13280:48;13296:31;13324:2;13296:31;:::i;13280:48::-;13353:2;13344:7;13337:19;13399:3;13392:4;13387:2;13379:6;13375:15;13371:26;13368:35;13365:55;;;13416:1;13413;13406:12;13365:55;13429:77;13503:2;13496:4;13487:7;13483:18;13476:4;13468:6;13464:17;13429:77;:::i;:::-;13524:7;13096:441;-1:-1:-1;;;;13096:441:160:o;13542:136::-;13620:13;;13642:30;13620:13;13642:30;:::i;13683:1161::-;13781:6;13834:2;13822:9;13813:7;13809:23;13805:32;13802:52;;;13850:1;13847;13840:12;13802:52;13883:9;13877:16;-1:-1:-1;;;;;13953:2:160;13945:6;13942:14;13939:34;;;13969:1;13966;13959:12;13939:34;13992:22;;;;14048:6;14030:16;;;14026:29;14023:49;;;14068:1;14065;14058:12;14023:49;14094:22;;:::i;:::-;14139:46;14182:2;14139:46;:::i;:::-;14132:5;14125:61;14225:2;14221;14217:11;14211:18;14254:2;14244:8;14241:16;14238:36;;;14270:1;14267;14260:12;14238:36;14306:55;14353:7;14342:8;14338:2;14334:17;14306:55;:::i;:::-;14301:2;14294:5;14290:14;14283:79;;14394:41;14431:2;14427;14423:11;14394:41;:::i;:::-;14389:2;14382:5;14378:14;14371:65;14468:41;14505:2;14501;14497:11;14468:41;:::i;:::-;14463:2;14456:5;14452:14;14445:65;14543:42;14580:3;14576:2;14572:12;14543:42;:::i;:::-;14537:3;14530:5;14526:15;14519:67;14619:42;14656:3;14652:2;14648:12;14619:42;:::i;:::-;14613:3;14606:5;14602:15;14595:67;14695:42;14732:3;14728:2;14724:12;14695:42;:::i;:::-;14689:3;14682:5;14678:15;14671:67;14771:42;14808:3;14804:2;14800:12;14771:42;:::i;:::-;14765:3;14754:15;;14747:67;14758:5;13683:1161;-1:-1:-1;;;;;13683:1161:160:o;15046:310::-;15124:6;15132;15185:2;15173:9;15164:7;15160:23;15156:32;15153:52;;;15201:1;15198;15191:12;15153:52;15230:9;15224:16;15214:26;;15283:2;15272:9;15268:18;15262:25;15296:30;15320:5;15296:30;:::i;15997:335::-;16076:6;16129:2;16117:9;16108:7;16104:23;16100:32;16097:52;;;16145:1;16142;16135:12;16097:52;16178:9;16172:16;-1:-1:-1;;;;;16203:6:160;16200:30;16197:50;;;16243:1;16240;16233:12;16197:50;16266:60;16318:7;16309:6;16298:9;16294:22;16266:60;:::i;16337:270::-;16378:3;16416:5;16410:12;16443:6;16438:3;16431:19;16459:76;16528:6;16521:4;16516:3;16512:14;16505:4;16498:5;16494:16;16459:76;:::i;:::-;16589:2;16568:15;-1:-1:-1;;16564:29:160;16555:39;;;;16596:4;16551:50;;16337:270;-1:-1:-1;;16337:270:160:o;16612:217::-;16759:2;16748:9;16741:21;16722:4;16779:44;16819:2;16808:9;16804:18;16796:6;16779:44;:::i;16834:184::-;16904:6;16957:2;16945:9;16936:7;16932:23;16928:32;16925:52;;;16973:1;16970;16963:12;16925:52;-1:-1:-1;16996:16:160;;16834:184;-1:-1:-1;16834:184:160:o;17023:252::-;17176:2;17161:18;;17209:1;17198:13;;17188:47;;17215:18;;:::i;:::-;17244:25;;;17023:252;:::o;17280:127::-;17341:10;17336:3;17332:20;17329:1;17322:31;17372:4;17369:1;17362:15;17396:4;17393:1;17386:15;17412:217;17452:1;17478;17468:132;;17522:10;17517:3;17513:20;17510:1;17503:31;17557:4;17554:1;17547:15;17585:4;17582:1;17575:15;17468:132;-1:-1:-1;17614:9:160;;17412:217::o;17840:168::-;17913:9;;;17944;;17961:15;;;17955:22;;17941:37;17931:71;;17982:18;;:::i;18435:249::-;18504:6;18557:2;18545:9;18536:7;18532:23;18528:32;18525:52;;;18573:1;18570;18563:12;18525:52;18605:9;18599:16;18624:30;18648:5;18624:30;:::i;18689:180::-;-1:-1:-1;;;;;18794:10:160;;;18806;;;18790:27;;18829:11;;;18826:37;;;18843:18;;:::i;:::-;18826:37;18689:180;;;;:::o;19849:125::-;19914:9;;;19935:10;;;19932:36;;;19948:18;;:::i;19979:1067::-;20086:6;20094;20147:2;20135:9;20126:7;20122:23;20118:32;20115:52;;;20163:1;20160;20153:12;20115:52;20196:9;20190:16;-1:-1:-1;;;;;20266:2:160;20258:6;20255:14;20252:34;;;20282:1;20279;20272:12;20252:34;20305:22;;;;20361:4;20343:16;;;20339:27;20336:47;;;20379:1;20376;20369:12;20336:47;20412:2;20406:9;20454:4;20446:6;20442:17;20509:6;20497:10;20494:22;20489:2;20477:10;20474:18;20471:46;20468:72;;;20520:18;;:::i;:::-;20556:2;20549:22;20595:9;;20580:25;;20641:2;20633:11;;20627:18;20654:31;20627:18;20654:31;:::i;:::-;20713:2;20701:15;;20694:30;20763:2;20755:11;;20749:18;20779:16;;;20776:36;;;20808:1;20805;20798:12;20776:36;20845:55;20892:7;20881:8;20877:2;20873:17;20845:55;:::i;:::-;20840:2;20832:6;20828:15;20821:80;;20920:6;20910:16;;;;;20971:2;20960:9;20956:18;20950:25;20984:30;21006:7;20984:30;:::i;21281:183::-;-1:-1:-1;;;;;21400:10:160;;;21388;;;21384:27;;21423:12;;;21420:38;;;21438:18;;:::i;21745:310::-;21823:6;21831;21884:2;21872:9;21863:7;21859:23;21855:32;21852:52;;;21900:1;21897;21890:12;21852:52;21932:9;21926:16;21951:30;21975:5;21951:30;:::i;:::-;22045:2;22030:18;;;;22024:25;22000:5;;22024:25;;-1:-1:-1;;;21745:310:160:o;22060:690::-;22114:3;22153:4;22148:3;22144:14;22197:10;22189:5;22183:12;22179:29;22174:3;22167:42;22228:4;22278;22271:5;22267:16;22261:23;22316:4;22309;22304:3;22300:14;22293:28;22343:4;22376:12;22370:19;22411:6;22405:4;22398:20;22445:2;22440:3;22436:12;22427:21;;22489:4;22475:12;22471:23;22457:37;;22512:1;22503:10;;22522:201;22536:6;22533:1;22530:13;22522:201;;;22603:13;;-1:-1:-1;;;;;22599:39:160;22585:54;;22698:15;;;;22635:1;22551:9;;;;;22661:14;;;;22522:201;;;-1:-1:-1;22739:5:160;22060:690;-1:-1:-1;;;;;;22060:690:160:o;22755:904::-;23150:3;23139:9;23132:22;23113:4;23177:45;23217:3;23206:9;23202:19;23194:6;23177:45;:::i;:::-;23270:9;23262:6;23258:22;23253:2;23242:9;23238:18;23231:50;23304:32;23329:6;23321;23304:32;:::i;:::-;23290:46;;23384:9;23376:6;23372:22;23367:2;23356:9;23352:18;23345:50;23418:45;23456:6;23448;23418:45;:::i;:::-;23404:59;;23511:9;23503:6;23499:22;23494:2;23483:9;23479:18;23472:50;23539:45;23577:6;23569;23539:45;:::i;:::-;23531:53;;;-1:-1:-1;;;;;23625:6:160;23621:31;23615:3;23604:9;23600:19;23593:60;22755:904;;;;;;;;:::o;24048:257::-;-1:-1:-1;;;;;24169:10:160;;;24181;;;24165:27;24212:20;;;;24119:18;24251:24;;;24241:58;;24279:18;;:::i;:::-;24241:58;;24048:257;;;;:::o;25157:128::-;25224:9;;;25245:11;;;25242:37;;;25259:18;;:::i;25290:274::-;25376:6;25429:2;25417:9;25408:7;25404:23;25400:32;25397:52;;;25445:1;25442;25435:12;25397:52;25484:9;25471:23;25503:31;25528:5;25503:31;:::i;25569:184::-;25627:6;25680:2;25668:9;25659:7;25655:23;25651:32;25648:52;;;25696:1;25693;25686:12;25648:52;25719:28;25737:9;25719:28;:::i;25758:269::-;25815:6;25868:2;25856:9;25847:7;25843:23;25839:32;25836:52;;;25884:1;25881;25874:12;25836:52;25923:9;25910:23;25973:4;25966:5;25962:16;25955:5;25952:27;25942:55;;25993:1;25990;25983:12;26311:245;26378:6;26431:2;26419:9;26410:7;26406:23;26402:32;26399:52;;;26447:1;26444;26437:12;26399:52;26479:9;26473:16;26498:28;26520:5;26498:28;:::i;27354:287::-;27483:3;27521:6;27515:13;27537:66;27596:6;27591:3;27584:4;27576:6;27572:17;27537:66;:::i;:::-;27619:16;;;;;27354:287;-1:-1:-1;;27354:287:160:o",
+ "linkReferences": {
+ "contracts/validator-manager/ValidatorMessages.sol": {
+ "ValidatorMessages": [
+ {
+ "start": 2578,
+ "length": 20
+ },
+ {
+ "start": 7985,
+ "length": 20
+ }
+ ]
+ }
+ }
+ },
+ "methodIdentifiers": {
+ "BIPS_CONVERSION_FACTOR()": "a9778a7a",
+ "ERC20_STAKING_MANAGER_STORAGE_LOCATION()": "e4a63c40",
+ "MAXIMUM_DELEGATION_FEE_BIPS()": "35455ded",
+ "MAXIMUM_STAKE_MULTIPLIER_LIMIT()": "151d30d1",
+ "STAKING_MANAGER_STORAGE_LOCATION()": "7a63ad85",
+ "WARP_MESSENGER()": "b771b3bc",
+ "changeDelegatorRewardRecipient(bytes32,address)": "fb8b11dd",
+ "changeValidatorRewardRecipient(bytes32,address)": "8ef34c98",
+ "claimDelegationFees(bytes32)": "93e24598",
+ "completeDelegatorRegistration(bytes32,uint32)": "60ad7784",
+ "completeDelegatorRemoval(bytes32,uint32)": "13409645",
+ "completeValidatorRegistration(uint32)": "a3a65e48",
+ "completeValidatorRemoval(uint32)": "9681d940",
+ "erc20()": "785e9e86",
+ "forceInitiateDelegatorRemoval(bytes32,bool,uint32)": "27bf60cd",
+ "forceInitiateValidatorRemoval(bytes32,bool,uint32)": "16679564",
+ "getDelegatorInfo(bytes32)": "53a13338",
+ "getDelegatorRewardInfo(bytes32)": "af1dd66c",
+ "getStakingManagerSettings()": "caa71874",
+ "getStakingValidator(bytes32)": "2674874b",
+ "getValidatorRewardInfo(bytes32)": "e24b2680",
+ "initialize((address,uint256,uint256,uint64,uint16,uint8,uint256,address,bytes32),address)": "b5c93498",
+ "initiateDelegatorRegistration(bytes32,uint256,address)": "cd236e7f",
+ "initiateDelegatorRemoval(bytes32,bool,uint32)": "2aa56638",
+ "initiateValidatorRegistration(bytes,bytes,(uint32,address[]),(uint32,address[]),uint16,uint64,uint256,address)": "7e65f4da",
+ "initiateValidatorRemoval(bytes32,bool,uint32)": "b2c1712e",
+ "resendUpdateDelegator(bytes32)": "245dafcb",
+ "submitUptimeProof(bytes32,uint32)": "25e1c776",
+ "valueToWeight(uint256)": "2e2194d8",
+ "weightToValue(uint64)": "62065856"
+ },
+ "rawMetadata": "{\"compiler\":{\"version\":\"0.8.25+commit.b61c2a91\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"enum ICMInitializable\",\"name\":\"init\",\"type\":\"uint8\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"}],\"name\":\"AddressEmptyCode\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"AddressInsufficientBalance\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"delegationID\",\"type\":\"bytes32\"}],\"name\":\"DelegatorIneligibleForRewards\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FailedInnerCall\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint16\",\"name\":\"delegationFeeBips\",\"type\":\"uint16\"}],\"name\":\"InvalidDelegationFee\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"delegationID\",\"type\":\"bytes32\"}],\"name\":\"InvalidDelegationID\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"enum DelegatorStatus\",\"name\":\"status\",\"type\":\"uint8\"}],\"name\":\"InvalidDelegatorStatus\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidInitialization\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"minStakeDuration\",\"type\":\"uint64\"}],\"name\":\"InvalidMinStakeDuration\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"name\":\"InvalidNonce\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"rewardRecipient\",\"type\":\"address\"}],\"name\":\"InvalidRewardRecipient\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"stakeAmount\",\"type\":\"uint256\"}],\"name\":\"InvalidStakeAmount\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"maximumStakeMultiplier\",\"type\":\"uint8\"}],\"name\":\"InvalidStakeMultiplier\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"uptimeBlockchainID\",\"type\":\"bytes32\"}],\"name\":\"InvalidUptimeBlockchainID\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"enum ValidatorStatus\",\"name\":\"status\",\"type\":\"uint8\"}],\"name\":\"InvalidValidatorStatus\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidWarpMessage\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"senderAddress\",\"type\":\"address\"}],\"name\":\"InvalidWarpOriginSenderAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"sourceChainID\",\"type\":\"bytes32\"}],\"name\":\"InvalidWarpSourceChainID\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"newValidatorWeight\",\"type\":\"uint64\"}],\"name\":\"MaxWeightExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"endTime\",\"type\":\"uint64\"}],\"name\":\"MinStakeDurationNotPassed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotInitializing\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ReentrancyGuardReentrantCall\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"SafeERC20FailedOperation\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"UnauthorizedOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"validationID\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"expectedValidationID\",\"type\":\"bytes32\"}],\"name\":\"UnexpectedValidationID\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"validationID\",\"type\":\"bytes32\"}],\"name\":\"ValidatorIneligibleForRewards\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"validationID\",\"type\":\"bytes32\"}],\"name\":\"ValidatorNotPoS\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroWeightToValueFactor\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"delegationID\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"validationID\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"startTime\",\"type\":\"uint256\"}],\"name\":\"CompletedDelegatorRegistration\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"delegationID\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"validationID\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"rewards\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"fees\",\"type\":\"uint256\"}],\"name\":\"CompletedDelegatorRemoval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"delegationID\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"DelegatorRewardClaimed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"delegationID\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"oldRecipient\",\"type\":\"address\"}],\"name\":\"DelegatorRewardRecipientChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"version\",\"type\":\"uint64\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"delegationID\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"validationID\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"delegatorAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"validatorWeight\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"delegatorWeight\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"setWeightMessageID\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"rewardRecipient\",\"type\":\"address\"}],\"name\":\"InitiatedDelegatorRegistration\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"delegationID\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"validationID\",\"type\":\"bytes32\"}],\"name\":\"InitiatedDelegatorRemoval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"validationID\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint16\",\"name\":\"delegationFeeBips\",\"type\":\"uint16\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"minStakeDuration\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"rewardRecipient\",\"type\":\"address\"}],\"name\":\"InitiatedStakingValidatorRegistration\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"validationID\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"uptime\",\"type\":\"uint64\"}],\"name\":\"UptimeUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"validationID\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"ValidatorRewardClaimed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"validationID\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"oldRecipient\",\"type\":\"address\"}],\"name\":\"ValidatorRewardRecipientChanged\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"BIPS_CONVERSION_FACTOR\",\"outputs\":[{\"internalType\":\"uint16\",\"name\":\"\",\"type\":\"uint16\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"ERC20_STAKING_MANAGER_STORAGE_LOCATION\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MAXIMUM_DELEGATION_FEE_BIPS\",\"outputs\":[{\"internalType\":\"uint16\",\"name\":\"\",\"type\":\"uint16\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MAXIMUM_STAKE_MULTIPLIER_LIMIT\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"STAKING_MANAGER_STORAGE_LOCATION\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"WARP_MESSENGER\",\"outputs\":[{\"internalType\":\"contract IWarpMessenger\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"delegationID\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"rewardRecipient\",\"type\":\"address\"}],\"name\":\"changeDelegatorRewardRecipient\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"validationID\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"rewardRecipient\",\"type\":\"address\"}],\"name\":\"changeValidatorRewardRecipient\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"validationID\",\"type\":\"bytes32\"}],\"name\":\"claimDelegationFees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"delegationID\",\"type\":\"bytes32\"},{\"internalType\":\"uint32\",\"name\":\"messageIndex\",\"type\":\"uint32\"}],\"name\":\"completeDelegatorRegistration\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"delegationID\",\"type\":\"bytes32\"},{\"internalType\":\"uint32\",\"name\":\"messageIndex\",\"type\":\"uint32\"}],\"name\":\"completeDelegatorRemoval\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"messageIndex\",\"type\":\"uint32\"}],\"name\":\"completeValidatorRegistration\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"messageIndex\",\"type\":\"uint32\"}],\"name\":\"completeValidatorRemoval\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"erc20\",\"outputs\":[{\"internalType\":\"contract IERC20Mintable\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"delegationID\",\"type\":\"bytes32\"},{\"internalType\":\"bool\",\"name\":\"includeUptimeProof\",\"type\":\"bool\"},{\"internalType\":\"uint32\",\"name\":\"messageIndex\",\"type\":\"uint32\"}],\"name\":\"forceInitiateDelegatorRemoval\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"validationID\",\"type\":\"bytes32\"},{\"internalType\":\"bool\",\"name\":\"includeUptimeProof\",\"type\":\"bool\"},{\"internalType\":\"uint32\",\"name\":\"messageIndex\",\"type\":\"uint32\"}],\"name\":\"forceInitiateValidatorRemoval\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"delegationID\",\"type\":\"bytes32\"}],\"name\":\"getDelegatorInfo\",\"outputs\":[{\"components\":[{\"internalType\":\"enum DelegatorStatus\",\"name\":\"status\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"validationID\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"weight\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"startTime\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"startingNonce\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"endingNonce\",\"type\":\"uint64\"}],\"internalType\":\"struct Delegator\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"delegationID\",\"type\":\"bytes32\"}],\"name\":\"getDelegatorRewardInfo\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStakingManagerSettings\",\"outputs\":[{\"components\":[{\"internalType\":\"contract IValidatorManager\",\"name\":\"manager\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minimumStakeAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maximumStakeAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint64\",\"name\":\"minimumStakeDuration\",\"type\":\"uint64\"},{\"internalType\":\"uint16\",\"name\":\"minimumDelegationFeeBips\",\"type\":\"uint16\"},{\"internalType\":\"uint8\",\"name\":\"maximumStakeMultiplier\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"weightToValueFactor\",\"type\":\"uint256\"},{\"internalType\":\"contract IRewardCalculator\",\"name\":\"rewardCalculator\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"uptimeBlockchainID\",\"type\":\"bytes32\"}],\"internalType\":\"struct StakingManagerSettings\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"validationID\",\"type\":\"bytes32\"}],\"name\":\"getStakingValidator\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"uint16\",\"name\":\"delegationFeeBips\",\"type\":\"uint16\"},{\"internalType\":\"uint64\",\"name\":\"minStakeDuration\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"uptimeSeconds\",\"type\":\"uint64\"}],\"internalType\":\"struct PoSValidatorInfo\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"validationID\",\"type\":\"bytes32\"}],\"name\":\"getValidatorRewardInfo\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"contract IValidatorManager\",\"name\":\"manager\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minimumStakeAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maximumStakeAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint64\",\"name\":\"minimumStakeDuration\",\"type\":\"uint64\"},{\"internalType\":\"uint16\",\"name\":\"minimumDelegationFeeBips\",\"type\":\"uint16\"},{\"internalType\":\"uint8\",\"name\":\"maximumStakeMultiplier\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"weightToValueFactor\",\"type\":\"uint256\"},{\"internalType\":\"contract IRewardCalculator\",\"name\":\"rewardCalculator\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"uptimeBlockchainID\",\"type\":\"bytes32\"}],\"internalType\":\"struct StakingManagerSettings\",\"name\":\"settings\",\"type\":\"tuple\"},{\"internalType\":\"contract IERC20Mintable\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"validationID\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"delegationAmount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"rewardRecipient\",\"type\":\"address\"}],\"name\":\"initiateDelegatorRegistration\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"delegationID\",\"type\":\"bytes32\"},{\"internalType\":\"bool\",\"name\":\"includeUptimeProof\",\"type\":\"bool\"},{\"internalType\":\"uint32\",\"name\":\"messageIndex\",\"type\":\"uint32\"}],\"name\":\"initiateDelegatorRemoval\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"nodeID\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"blsPublicKey\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"threshold\",\"type\":\"uint32\"},{\"internalType\":\"address[]\",\"name\":\"addresses\",\"type\":\"address[]\"}],\"internalType\":\"struct PChainOwner\",\"name\":\"remainingBalanceOwner\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"threshold\",\"type\":\"uint32\"},{\"internalType\":\"address[]\",\"name\":\"addresses\",\"type\":\"address[]\"}],\"internalType\":\"struct PChainOwner\",\"name\":\"disableOwner\",\"type\":\"tuple\"},{\"internalType\":\"uint16\",\"name\":\"delegationFeeBips\",\"type\":\"uint16\"},{\"internalType\":\"uint64\",\"name\":\"minStakeDuration\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"stakeAmount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"rewardRecipient\",\"type\":\"address\"}],\"name\":\"initiateValidatorRegistration\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"validationID\",\"type\":\"bytes32\"},{\"internalType\":\"bool\",\"name\":\"includeUptimeProof\",\"type\":\"bool\"},{\"internalType\":\"uint32\",\"name\":\"messageIndex\",\"type\":\"uint32\"}],\"name\":\"initiateValidatorRemoval\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"delegationID\",\"type\":\"bytes32\"}],\"name\":\"resendUpdateDelegator\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"validationID\",\"type\":\"bytes32\"},{\"internalType\":\"uint32\",\"name\":\"messageIndex\",\"type\":\"uint32\"}],\"name\":\"submitUptimeProof\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"valueToWeight\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"weight\",\"type\":\"uint64\"}],\"name\":\"weightToValue\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"custom:security-contact\":\"https://github.com/ava-labs/icm-contracts/blob/main/SECURITY.md\",\"details\":\"Implementation of the {IERC20TokenStakingManager} interface.\",\"errors\":{\"AddressEmptyCode(address)\":[{\"details\":\"There's no code at `target` (it is not a contract).\"}],\"AddressInsufficientBalance(address)\":[{\"details\":\"The ETH balance of the account is not enough to perform the operation.\"}],\"FailedInnerCall()\":[{\"details\":\"A call to an address target failed. The target may have reverted.\"}],\"InvalidInitialization()\":[{\"details\":\"The contract is already initialized.\"}],\"NotInitializing()\":[{\"details\":\"The contract is not initializing.\"}],\"ReentrancyGuardReentrantCall()\":[{\"details\":\"Unauthorized reentrant call.\"}],\"SafeERC20FailedOperation(address)\":[{\"details\":\"An operation with an ERC20 token failed.\"}]},\"events\":{\"CompletedDelegatorRegistration(bytes32,bytes32,uint256)\":{\"params\":{\"delegationID\":\"The ID of the delegation\",\"startTime\":\"The time at which the registration was completed\",\"validationID\":\"The ID of the validation period\"}},\"CompletedDelegatorRemoval(bytes32,bytes32,uint256,uint256)\":{\"params\":{\"delegationID\":\"The ID of the delegation\",\"fees\":\"The portion of the delegator's rewards paid to the validator\",\"rewards\":\"The rewards given to the delegator\",\"validationID\":\"The ID of the validator the delegator was staked to\"}},\"DelegatorRewardClaimed(bytes32,address,uint256)\":{\"params\":{\"amount\":\"The amount of rewards claimed\",\"delegationID\":\"The ID of the delegation\",\"recipient\":\"The address of the recipient of the rewards\"}},\"DelegatorRewardRecipientChanged(bytes32,address,address)\":{\"params\":{\"delegationID\":\"The ID of the validation period\",\"oldRecipient\":\"The address of the old recipient of the rewards\",\"recipient\":\"The address of the new recipient of the rewards\"}},\"Initialized(uint64)\":{\"details\":\"Triggered when the contract has been initialized or reinitialized.\"},\"InitiatedDelegatorRegistration(bytes32,bytes32,address,uint64,uint64,uint64,bytes32,address)\":{\"params\":{\"delegationID\":\"The ID of the delegation\",\"delegatorAddress\":\"The address of the delegator\",\"delegatorWeight\":\"The weight of the delegator\",\"nonce\":\"The message nonce used to update the validator weight\",\"rewardRecipient\":\"The address of the recipient of the delegator's rewards\",\"setWeightMessageID\":\"The ID of the ICM message that updates the validator's weight on the P-Chain\",\"validationID\":\"The ID of the validation period being delegated to\",\"validatorWeight\":\"The updated validator weight that is sent to the P-Chain\"}},\"InitiatedDelegatorRemoval(bytes32,bytes32)\":{\"params\":{\"delegationID\":\"The ID of the delegation\",\"validationID\":\"The ID of the validation period the delegator was staked to\"}},\"InitiatedStakingValidatorRegistration(bytes32,address,uint16,uint64,address)\":{\"params\":{\"delegationFeeBips\":\"The delegation fee in basis points\",\"minStakeDuration\":\"The minimum stake duration\",\"owner\":\"The address of the owner of the validator\",\"rewardRecipient\":\"The address of the recipient of the validator's rewards\",\"validationID\":\"The ID of the validation period\"}},\"UptimeUpdated(bytes32,uint64)\":{\"params\":{\"uptime\":\"The updated uptime of the validator\",\"validationID\":\"The ID of the validation period\"}},\"ValidatorRewardClaimed(bytes32,address,uint256)\":{\"params\":{\"amount\":\"The amount of rewards claimed\",\"recipient\":\"The address of the recipient of the rewards\",\"validationID\":\"The ID of the validation period\"}},\"ValidatorRewardRecipientChanged(bytes32,address,address)\":{\"params\":{\"oldRecipient\":\"The address of the old recipient of the rewards\",\"recipient\":\"The address of the new recipient of the rewards\",\"validationID\":\"The ID of the validation period\"}}},\"kind\":\"dev\",\"methods\":{\"getDelegatorRewardInfo(bytes32)\":{\"returns\":{\"_0\":\"The current delegation reward recipient\",\"_1\":\"The current claimable delegation reward amount\"}},\"getValidatorRewardInfo(bytes32)\":{\"returns\":{\"_0\":\"The current validation reward recipient\",\"_1\":\"The current claimable validation reward amount\"}},\"initialize((address,uint256,uint256,uint64,uint16,uint8,uint256,address,bytes32),address)\":{\"params\":{\"settings\":\"Initial settings for the PoS validator manager\",\"token\":\"The ERC20 token to be staked\"}},\"resendUpdateDelegator(bytes32)\":{\"details\":\"Resending the latest validator weight with the latest nonce is safe because all weight changes are cumulative, so the latest weight change will always include the weight change for any added delegators.\"},\"valueToWeight(uint256)\":{\"params\":{\"value\":\"Token value to convert.\"}},\"weightToValue(uint64)\":{\"params\":{\"weight\":\"weight to convert.\"}}},\"version\":1},\"userdoc\":{\"events\":{\"CompletedDelegatorRegistration(bytes32,bytes32,uint256)\":{\"notice\":\"Event emitted when a delegator registration is completed\"},\"CompletedDelegatorRemoval(bytes32,bytes32,uint256,uint256)\":{\"notice\":\"Event emitted when delegator removal is completed\"},\"DelegatorRewardClaimed(bytes32,address,uint256)\":{\"notice\":\"Event emitted when a delegator claims rewards.\"},\"DelegatorRewardRecipientChanged(bytes32,address,address)\":{\"notice\":\"Event emitted when the recipient of a delegator's rewards is changed.\"},\"InitiatedDelegatorRegistration(bytes32,bytes32,address,uint64,uint64,uint64,bytes32,address)\":{\"notice\":\"Event emitted when a delegator registration is initiated\"},\"InitiatedDelegatorRemoval(bytes32,bytes32)\":{\"notice\":\"Event emitted when delegator removal is initiated\"},\"InitiatedStakingValidatorRegistration(bytes32,address,uint16,uint64,address)\":{\"notice\":\"Event emitted when a staking validator registration is initiated\"},\"UptimeUpdated(bytes32,uint64)\":{\"notice\":\"Event emitted when the uptime of a validator is updated. Only emitted when the uptime is greater than the stored uptime.\"},\"ValidatorRewardClaimed(bytes32,address,uint256)\":{\"notice\":\"Event emitted when a validator claims rewards. Emitted when validation rewards and delegation fees are claimed.\"},\"ValidatorRewardRecipientChanged(bytes32,address,address)\":{\"notice\":\"Event emitted when the recipient of a validator's rewards is changed.\"}},\"kind\":\"user\",\"methods\":{\"changeDelegatorRewardRecipient(bytes32,address)\":{\"notice\":\"See {IStakingManager-changeDelegatorRewardRecipient}.\"},\"changeValidatorRewardRecipient(bytes32,address)\":{\"notice\":\"See {IStakingManager-changeValidatorRewardRecipient}.\"},\"claimDelegationFees(bytes32)\":{\"notice\":\"See {IStakingManager-claimDelegationFees}.\"},\"completeDelegatorRegistration(bytes32,uint32)\":{\"notice\":\"See {IStakingManager-completeDelegatorRegistration}. Extends the functionality of {ACP99Manager-completeValidatorWeightUpdate} by updating the delegation status.\"},\"completeDelegatorRemoval(bytes32,uint32)\":{\"notice\":\"See {IStakingManager-completeDelegatorRemoval}. Extends the functionality of {ACP99Manager-completeValidatorWeightUpdate} by updating the delegation status and unlocking delegation rewards.\"},\"completeValidatorRegistration(uint32)\":{\"notice\":\"See {IStakingManager-completeValidatorRegistration}.\"},\"completeValidatorRemoval(uint32)\":{\"notice\":\"See {IStakingManager-completeValidatorRemoval}. Extends the functionality of {ACP99Manager-completeValidatorRemoval} by unlocking staking rewards.\"},\"erc20()\":{\"notice\":\"Returns the ERC20 token being staked\"},\"forceInitiateDelegatorRemoval(bytes32,bool,uint32)\":{\"notice\":\"See {IStakingManager-forceInitiateDelegatorRemoval}.\"},\"forceInitiateValidatorRemoval(bytes32,bool,uint32)\":{\"notice\":\"See {IStakingManager-forceInitiateValidatorRemoval}.\"},\"getDelegatorInfo(bytes32)\":{\"notice\":\"Returns the delegator information for the given delegationID\"},\"getDelegatorRewardInfo(bytes32)\":{\"notice\":\"Returns the reward recipient and claimable reward amount for the given delegationID\"},\"getStakingManagerSettings()\":{\"notice\":\"Returns the settings used to initialize the StakingManager\"},\"getStakingValidator(bytes32)\":{\"notice\":\"Returns the PoS validator information for the given validationID See {ValidatorManager-getValidator} to retreive information about the validator not specific to PoS\"},\"getValidatorRewardInfo(bytes32)\":{\"notice\":\"Returns the reward recipient and claimable reward amount for the given validationID\"},\"initialize((address,uint256,uint256,uint64,uint16,uint8,uint256,address,bytes32),address)\":{\"notice\":\"Initialize the ERC20 token staking manager\"},\"initiateDelegatorRegistration(bytes32,uint256,address)\":{\"notice\":\"See {IERC20TokenStakingManager-initiateDelegatorRegistration}\"},\"initiateDelegatorRemoval(bytes32,bool,uint32)\":{\"notice\":\"See {IStakingManager-initiateDelegatorRemoval}.\"},\"initiateValidatorRegistration(bytes,bytes,(uint32,address[]),(uint32,address[]),uint16,uint64,uint256,address)\":{\"notice\":\"See {IERC20TokenStakingManager-initiateValidatorRegistration}\"},\"initiateValidatorRemoval(bytes32,bool,uint32)\":{\"notice\":\"See {IStakingManager-initiateValidatorRemoval}.\"},\"resendUpdateDelegator(bytes32)\":{\"notice\":\"See {IStakingManager-resendUpdateDelegator}.\"},\"submitUptimeProof(bytes32,uint32)\":{\"notice\":\"See {IStakingManager-submitUptimeProof}.\"},\"valueToWeight(uint256)\":{\"notice\":\"Converts a token value to a weight.\"},\"weightToValue(uint64)\":{\"notice\":\"Converts a weight to a token value.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/validator-manager/ERC20TokenStakingManager.sol\":\"ERC20TokenStakingManager\"},\"evmVersion\":\"shanghai\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"none\"},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[\":@avalabs/subnet-evm-contracts@1.2.2/=lib/subnet-evm/contracts/\",\":@forge-std/=lib/forge-std/src/\",\":@mocks/=contracts/mocks/\",\":@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/\",\":@openzeppelin/contracts-upgradeable@5.0.2/=lib/openzeppelin-contracts-upgradeable/contracts/\",\":@openzeppelin/contracts/=lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/\",\":@openzeppelin/contracts@5.0.2/=lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/\",\":@teleporter/=contracts/teleporter/\",\":@utilities/=contracts/utilities/\",\":ds-test/=lib/openzeppelin-contracts-upgradeable/lib/forge-std/lib/ds-test/src/\",\":erc4626-tests/=lib/openzeppelin-contracts-upgradeable/lib/erc4626-tests/\",\":forge-std/=lib/forge-std/src/\",\":openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/\",\":openzeppelin-contracts/=lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/\",\":subnet-evm/=lib/subnet-evm/\"]},\"sources\":{\"contracts/utilities/ICMInitializable.sol\":{\"keccak256\":\"0x84f559fe344442572165246f83ed5a0ce23be1d1504f8317d94650a88c666976\",\"license\":\"LicenseRef-Ecosystem\",\"urls\":[\"bzz-raw://9deb4a9fc5b1b0fd9b457900617765f7a3d24ed3bd32c78d31400cf22146baf9\",\"dweb:/ipfs/QmcKwpA3xG5uDo35bevigKmY4zR6zjgAQD8JDmzmnDPjdC\"]},\"contracts/utilities/SafeERC20TransferFrom.sol\":{\"keccak256\":\"0x485867dc46af4ee0812024758b2f3493b3efc15f8ba23d73223dd847b04c8018\",\"license\":\"LicenseRef-Ecosystem\",\"urls\":[\"bzz-raw://2b9b29d8ee033a2ed8dd1bdb024027704f1180a1316732cb3d3874898d277736\",\"dweb:/ipfs/QmR257FurAqL57rzY1BVJhxCS6yndrBow1J4hMHCwfcvyA\"]},\"contracts/validator-manager/ACP99Manager.sol\":{\"keccak256\":\"0xac707d933ce27e52de51c11dc2d47d7d8bb97273c24d05c2585fe22efb058889\",\"license\":\"LicenseRef-Ecosystem\",\"urls\":[\"bzz-raw://aafe1df2053a34836dbf7ba7b2768377f454976fcf50621ead0c542f1fe9cde6\",\"dweb:/ipfs/QmSx1EDEbuFLRMKDnBvq3hZvpKTr8Jx9zqVwsV1wxrW1oG\"]},\"contracts/validator-manager/ERC20TokenStakingManager.sol\":{\"keccak256\":\"0xc1082cae1172c399e7a279256de533805c77242bf4f24342e9c4d38a2af05ef2\",\"license\":\"LicenseRef-Ecosystem\",\"urls\":[\"bzz-raw://405e09bf9bd7397242024cd5aece047b82cdfcd5b5a0edd1972fb21acb6047f9\",\"dweb:/ipfs/Qmbgd7wqHRriajD1qTmo8twWb8rqRVYYta3QaGTNtpHeh5\"]},\"contracts/validator-manager/StakingManager.sol\":{\"keccak256\":\"0xf8906325bbeeb4b51840b0e8562572ca1f9f926581cd04e64eb90c7ec78f7625\",\"license\":\"LicenseRef-Ecosystem\",\"urls\":[\"bzz-raw://76ec5debcca9b31009c18c6802058411470f426ff1dc0960486d40d50268397e\",\"dweb:/ipfs/QmXocGvrshPq5TEPeyy5o4wwYU3umasQVq1pBwDiuizNEz\"]},\"contracts/validator-manager/ValidatorMessages.sol\":{\"keccak256\":\"0x47938a3226d2fa48028954bffcdef4eddeb2fedd366cea6617682c7813ea685e\",\"license\":\"LicenseRef-Ecosystem\",\"urls\":[\"bzz-raw://f1a148a96f6c2b30777cc6f8b634f3c21ee6765e4037e3623c10bfcb6c32c439\",\"dweb:/ipfs/QmVyeMqdaa8DgXf2Nor4rd1DRB4MpouiUioecr9kecXS9E\"]},\"contracts/validator-manager/interfaces/IACP99Manager.sol\":{\"keccak256\":\"0x284d77192a5dcae149064aa74591ae53e7af2c310bbf5d67ff9bc9517410c7b4\",\"license\":\"LicenseRef-Ecosystem\",\"urls\":[\"bzz-raw://492a40cdffd8ad0928ce5ab082fd9de6a2e65f2ae16e1ca233126f89e063e0fa\",\"dweb:/ipfs/QmRyK7iyvK2jAHSjgtBfWrBUPjGYpsMD8dPL63Uy2ji8sk\"]},\"contracts/validator-manager/interfaces/IERC20Mintable.sol\":{\"keccak256\":\"0x2cfb122a4d1a8c4d4182f803838ef555f1333d541c91a1097ee353af9d56a5bb\",\"license\":\"LicenseRef-Ecosystem\",\"urls\":[\"bzz-raw://e6b05b96cc0b58364fe2243ebd38ae1e802e1a505da011554a693336acee1586\",\"dweb:/ipfs/Qmc98C4RqiTkuCCJET1xtbP6Ty6tuSQAm3fYd9j7Uc3Raf\"]},\"contracts/validator-manager/interfaces/IERC20TokenStakingManager.sol\":{\"keccak256\":\"0x036cda784eecff72755c5a92539d39728304b13f8b0bf7a899b964aa6ae3aa64\",\"license\":\"LicenseRef-Ecosystem\",\"urls\":[\"bzz-raw://8b162c4a55a15bfe467e9bc16cb558edd6c70d17235ef3efe10d426fbe9c9f13\",\"dweb:/ipfs/QmSH8JywT1jbZ9kBVvKLn1VeePuizrKc5DRuguURAP3bms\"]},\"contracts/validator-manager/interfaces/IRewardCalculator.sol\":{\"keccak256\":\"0x0e2ed48da58e2eda3766361e315467e2ba9f258e48684501ab337e8a65c29e47\",\"license\":\"LicenseRef-Ecosystem\",\"urls\":[\"bzz-raw://faf1da0f5d33fa1f9e7d29ada9884dc6554b47b4d948af6f1f6261153414e42a\",\"dweb:/ipfs/QmTn97vcnd3Haf9fBVvBzLenp8xwdGGnnzxwxuK9Yt3ryi\"]},\"contracts/validator-manager/interfaces/IStakingManager.sol\":{\"keccak256\":\"0xe7e86b636fb493642beef2dfa27da6029aaba8bd0dc88deb99b5ffe05e0c645a\",\"license\":\"LicenseRef-Ecosystem\",\"urls\":[\"bzz-raw://566b5e00ba692164d948af776f5d127ac813541ee390d330629138aa43340864\",\"dweb:/ipfs/QmVEkhcF8XnkKA4hkeXWdCMpsvpe45DssHzP56h7mQaGrf\"]},\"contracts/validator-manager/interfaces/IValidatorManager.sol\":{\"keccak256\":\"0x59ba881e14793d6e84ef72fdf6db03da2117694d0cf4e17f21989fc5a76a9ebb\",\"license\":\"LicenseRef-Ecosystem\",\"urls\":[\"bzz-raw://f84232c4adaa616ae90a27f2d2bb169a4331ccb074a26c98f83636da139383d2\",\"dweb:/ipfs/QmNj4DKvEZoCi8NvnYdHCZLHJvDt8sdDVqg85Fk61Pff65\"]},\"lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x631188737069917d2f909d29ce62c4d48611d326686ba6683e26b72a23bfac0b\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://7a61054ae84cd6c4d04c0c4450ba1d6de41e27e0a2c4f1bcdf58f796b401c609\",\"dweb:/ipfs/QmUvtdp7X1mRVyC3CsHrtPbgoqWaXHp3S1ZR24tpAQYJWM\"]},\"lib/openzeppelin-contracts-upgradeable/contracts/utils/ContextUpgradeable.sol\":{\"keccak256\":\"0xdbef5f0c787055227243a7318ef74c8a5a1108ca3a07f2b3a00ef67769e1e397\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://08e39f23d5b4692f9a40803e53a8156b72b4c1f9902a88cd65ba964db103dab9\",\"dweb:/ipfs/QmPKn6EYDgpga7KtpkA8wV2yJCYGMtc9K4LkJfhKX2RVSV\"]},\"lib/openzeppelin-contracts-upgradeable/contracts/utils/ReentrancyGuardUpgradeable.sol\":{\"keccak256\":\"0xb44e086e941292cdc7f440de51478493894ef0b1aeccb0c4047445919f667f74\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://942dad22fbdc1669f025540ba63aa3ccfad5f8458fc5d4525b31ebf272e7af45\",\"dweb:/ipfs/Qmdo4X2M82aM3AMoW2kf2jhYkSCyC4T1pHNd6obdsDFnAB\"]},\"lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\":{\"keccak256\":\"0xc6a8ff0ea489379b61faa647490411b80102578440ab9d84e9a957cc12164e70\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://0ea104e577e63faea3b69c415637e99e755dcbf64c5833d7140c35a714d6d90c\",\"dweb:/ipfs/Qmau6x4Ns9XdyynRCNNp3RhLqijJjFm7z5fyZazfYFGYdq\"]},\"lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol\":{\"keccak256\":\"0x6008dabfe393240d73d7dd7688033f72740d570aa422254d29a7dce8568f3aff\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://f5196ec75139918c6c7bb4251b36395e668f1fa6d206beba7e7520e74913940d\",\"dweb:/ipfs/QmSyqjksXxmm2mCG6qRd1yuwLykypkSVBbnBnGqJRcuJMi\"]},\"lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\":{\"keccak256\":\"0x37bb49513c49c87c4642a891b13b63571bc87013dde806617aa1efb54605f386\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://b3036b3a83b7c48f96641f2a9002b9f2dcb6a5958dd670894ada21ae8229b3d0\",\"dweb:/ipfs/QmUNfSBdoVtjhETaUJCYcaC7pTMgbhht926tJ2uXJbiVd3\"]},\"lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/utils/Address.sol\":{\"keccak256\":\"0xaf28a975a78550e45f65e559a3ad6a5ad43b9b8a37366999abd1b7084eb70721\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://b7bd24e224f67f65bfadf85dc2929fa965456bb2415478bd0125471b5ce35245\",\"dweb:/ipfs/QmRaydGr8BTHs1kvaZfsNU69pKzUAGFrvABn1KiRSbE51y\"]},\"lib/subnet-evm/contracts/contracts/interfaces/IWarpMessenger.sol\":{\"keccak256\":\"0x9f75d13b8995e3b13a39b88b9f7d8046a3127c1b81abcd202c2438ddece42819\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://12af89d9499252371faa23dfc13b4067876f7d7b6b01a1a3d891cbf7c9b1f90c\",\"dweb:/ipfs/QmXntNu3vLECvSAJdacsebtecoaUpeYvUDATpxS5GbB8bL\"]}},\"version\":1}",
+ "metadata": {
+ "compiler": {
+ "version": "0.8.25+commit.b61c2a91"
+ },
+ "language": "Solidity",
+ "output": {
+ "abi": [
+ {
+ "inputs": [
+ {
+ "internalType": "enum ICMInitializable",
+ "name": "init",
+ "type": "uint8"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "constructor"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "target",
+ "type": "address"
+ }
+ ],
+ "type": "error",
+ "name": "AddressEmptyCode"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "account",
+ "type": "address"
+ }
+ ],
+ "type": "error",
+ "name": "AddressInsufficientBalance"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes32",
+ "name": "delegationID",
+ "type": "bytes32"
+ }
+ ],
+ "type": "error",
+ "name": "DelegatorIneligibleForRewards"
+ },
+ {
+ "inputs": [],
+ "type": "error",
+ "name": "FailedInnerCall"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint16",
+ "name": "delegationFeeBips",
+ "type": "uint16"
+ }
+ ],
+ "type": "error",
+ "name": "InvalidDelegationFee"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes32",
+ "name": "delegationID",
+ "type": "bytes32"
+ }
+ ],
+ "type": "error",
+ "name": "InvalidDelegationID"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "enum DelegatorStatus",
+ "name": "status",
+ "type": "uint8"
+ }
+ ],
+ "type": "error",
+ "name": "InvalidDelegatorStatus"
+ },
+ {
+ "inputs": [],
+ "type": "error",
+ "name": "InvalidInitialization"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint64",
+ "name": "minStakeDuration",
+ "type": "uint64"
+ }
+ ],
+ "type": "error",
+ "name": "InvalidMinStakeDuration"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint64",
+ "name": "nonce",
+ "type": "uint64"
+ }
+ ],
+ "type": "error",
+ "name": "InvalidNonce"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "rewardRecipient",
+ "type": "address"
+ }
+ ],
+ "type": "error",
+ "name": "InvalidRewardRecipient"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint256",
+ "name": "stakeAmount",
+ "type": "uint256"
+ }
+ ],
+ "type": "error",
+ "name": "InvalidStakeAmount"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint8",
+ "name": "maximumStakeMultiplier",
+ "type": "uint8"
+ }
+ ],
+ "type": "error",
+ "name": "InvalidStakeMultiplier"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes32",
+ "name": "uptimeBlockchainID",
+ "type": "bytes32"
+ }
+ ],
+ "type": "error",
+ "name": "InvalidUptimeBlockchainID"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "enum ValidatorStatus",
+ "name": "status",
+ "type": "uint8"
+ }
+ ],
+ "type": "error",
+ "name": "InvalidValidatorStatus"
+ },
+ {
+ "inputs": [],
+ "type": "error",
+ "name": "InvalidWarpMessage"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "senderAddress",
+ "type": "address"
+ }
+ ],
+ "type": "error",
+ "name": "InvalidWarpOriginSenderAddress"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes32",
+ "name": "sourceChainID",
+ "type": "bytes32"
+ }
+ ],
+ "type": "error",
+ "name": "InvalidWarpSourceChainID"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint64",
+ "name": "newValidatorWeight",
+ "type": "uint64"
+ }
+ ],
+ "type": "error",
+ "name": "MaxWeightExceeded"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint64",
+ "name": "endTime",
+ "type": "uint64"
+ }
+ ],
+ "type": "error",
+ "name": "MinStakeDurationNotPassed"
+ },
+ {
+ "inputs": [],
+ "type": "error",
+ "name": "NotInitializing"
+ },
+ {
+ "inputs": [],
+ "type": "error",
+ "name": "ReentrancyGuardReentrantCall"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "token",
+ "type": "address"
+ }
+ ],
+ "type": "error",
+ "name": "SafeERC20FailedOperation"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ }
+ ],
+ "type": "error",
+ "name": "UnauthorizedOwner"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes32",
+ "name": "validationID",
+ "type": "bytes32"
+ },
+ {
+ "internalType": "bytes32",
+ "name": "expectedValidationID",
+ "type": "bytes32"
+ }
+ ],
+ "type": "error",
+ "name": "UnexpectedValidationID"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes32",
+ "name": "validationID",
+ "type": "bytes32"
+ }
+ ],
+ "type": "error",
+ "name": "ValidatorIneligibleForRewards"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes32",
+ "name": "validationID",
+ "type": "bytes32"
+ }
+ ],
+ "type": "error",
+ "name": "ValidatorNotPoS"
+ },
+ {
+ "inputs": [],
+ "type": "error",
+ "name": "ZeroAddress"
+ },
+ {
+ "inputs": [],
+ "type": "error",
+ "name": "ZeroWeightToValueFactor"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes32",
+ "name": "delegationID",
+ "type": "bytes32",
+ "indexed": true
+ },
+ {
+ "internalType": "bytes32",
+ "name": "validationID",
+ "type": "bytes32",
+ "indexed": true
+ },
+ {
+ "internalType": "uint256",
+ "name": "startTime",
+ "type": "uint256",
+ "indexed": false
+ }
+ ],
+ "type": "event",
+ "name": "CompletedDelegatorRegistration",
+ "anonymous": false
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes32",
+ "name": "delegationID",
+ "type": "bytes32",
+ "indexed": true
+ },
+ {
+ "internalType": "bytes32",
+ "name": "validationID",
+ "type": "bytes32",
+ "indexed": true
+ },
+ {
+ "internalType": "uint256",
+ "name": "rewards",
+ "type": "uint256",
+ "indexed": false
+ },
+ {
+ "internalType": "uint256",
+ "name": "fees",
+ "type": "uint256",
+ "indexed": false
+ }
+ ],
+ "type": "event",
+ "name": "CompletedDelegatorRemoval",
+ "anonymous": false
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes32",
+ "name": "delegationID",
+ "type": "bytes32",
+ "indexed": true
+ },
+ {
+ "internalType": "address",
+ "name": "recipient",
+ "type": "address",
+ "indexed": true
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256",
+ "indexed": false
+ }
+ ],
+ "type": "event",
+ "name": "DelegatorRewardClaimed",
+ "anonymous": false
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes32",
+ "name": "delegationID",
+ "type": "bytes32",
+ "indexed": true
+ },
+ {
+ "internalType": "address",
+ "name": "recipient",
+ "type": "address",
+ "indexed": true
+ },
+ {
+ "internalType": "address",
+ "name": "oldRecipient",
+ "type": "address",
+ "indexed": true
+ }
+ ],
+ "type": "event",
+ "name": "DelegatorRewardRecipientChanged",
+ "anonymous": false
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint64",
+ "name": "version",
+ "type": "uint64",
+ "indexed": false
+ }
+ ],
+ "type": "event",
+ "name": "Initialized",
+ "anonymous": false
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes32",
+ "name": "delegationID",
+ "type": "bytes32",
+ "indexed": true
+ },
+ {
+ "internalType": "bytes32",
+ "name": "validationID",
+ "type": "bytes32",
+ "indexed": true
+ },
+ {
+ "internalType": "address",
+ "name": "delegatorAddress",
+ "type": "address",
+ "indexed": true
+ },
+ {
+ "internalType": "uint64",
+ "name": "nonce",
+ "type": "uint64",
+ "indexed": false
+ },
+ {
+ "internalType": "uint64",
+ "name": "validatorWeight",
+ "type": "uint64",
+ "indexed": false
+ },
+ {
+ "internalType": "uint64",
+ "name": "delegatorWeight",
+ "type": "uint64",
+ "indexed": false
+ },
+ {
+ "internalType": "bytes32",
+ "name": "setWeightMessageID",
+ "type": "bytes32",
+ "indexed": false
+ },
+ {
+ "internalType": "address",
+ "name": "rewardRecipient",
+ "type": "address",
+ "indexed": false
+ }
+ ],
+ "type": "event",
+ "name": "InitiatedDelegatorRegistration",
+ "anonymous": false
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes32",
+ "name": "delegationID",
+ "type": "bytes32",
+ "indexed": true
+ },
+ {
+ "internalType": "bytes32",
+ "name": "validationID",
+ "type": "bytes32",
+ "indexed": true
+ }
+ ],
+ "type": "event",
+ "name": "InitiatedDelegatorRemoval",
+ "anonymous": false
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes32",
+ "name": "validationID",
+ "type": "bytes32",
+ "indexed": true
+ },
+ {
+ "internalType": "address",
+ "name": "owner",
+ "type": "address",
+ "indexed": true
+ },
+ {
+ "internalType": "uint16",
+ "name": "delegationFeeBips",
+ "type": "uint16",
+ "indexed": false
+ },
+ {
+ "internalType": "uint64",
+ "name": "minStakeDuration",
+ "type": "uint64",
+ "indexed": false
+ },
+ {
+ "internalType": "address",
+ "name": "rewardRecipient",
+ "type": "address",
+ "indexed": false
+ }
+ ],
+ "type": "event",
+ "name": "InitiatedStakingValidatorRegistration",
+ "anonymous": false
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes32",
+ "name": "validationID",
+ "type": "bytes32",
+ "indexed": true
+ },
+ {
+ "internalType": "uint64",
+ "name": "uptime",
+ "type": "uint64",
+ "indexed": false
+ }
+ ],
+ "type": "event",
+ "name": "UptimeUpdated",
+ "anonymous": false
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes32",
+ "name": "validationID",
+ "type": "bytes32",
+ "indexed": true
+ },
+ {
+ "internalType": "address",
+ "name": "recipient",
+ "type": "address",
+ "indexed": true
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256",
+ "indexed": false
+ }
+ ],
+ "type": "event",
+ "name": "ValidatorRewardClaimed",
+ "anonymous": false
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes32",
+ "name": "validationID",
+ "type": "bytes32",
+ "indexed": true
+ },
+ {
+ "internalType": "address",
+ "name": "recipient",
+ "type": "address",
+ "indexed": true
+ },
+ {
+ "internalType": "address",
+ "name": "oldRecipient",
+ "type": "address",
+ "indexed": true
+ }
+ ],
+ "type": "event",
+ "name": "ValidatorRewardRecipientChanged",
+ "anonymous": false
+ },
+ {
+ "inputs": [],
+ "stateMutability": "view",
+ "type": "function",
+ "name": "BIPS_CONVERSION_FACTOR",
+ "outputs": [
+ {
+ "internalType": "uint16",
+ "name": "",
+ "type": "uint16"
+ }
+ ]
+ },
+ {
+ "inputs": [],
+ "stateMutability": "view",
+ "type": "function",
+ "name": "ERC20_STAKING_MANAGER_STORAGE_LOCATION",
+ "outputs": [
+ {
+ "internalType": "bytes32",
+ "name": "",
+ "type": "bytes32"
+ }
+ ]
+ },
+ {
+ "inputs": [],
+ "stateMutability": "view",
+ "type": "function",
+ "name": "MAXIMUM_DELEGATION_FEE_BIPS",
+ "outputs": [
+ {
+ "internalType": "uint16",
+ "name": "",
+ "type": "uint16"
+ }
+ ]
+ },
+ {
+ "inputs": [],
+ "stateMutability": "view",
+ "type": "function",
+ "name": "MAXIMUM_STAKE_MULTIPLIER_LIMIT",
+ "outputs": [
+ {
+ "internalType": "uint8",
+ "name": "",
+ "type": "uint8"
+ }
+ ]
+ },
+ {
+ "inputs": [],
+ "stateMutability": "view",
+ "type": "function",
+ "name": "STAKING_MANAGER_STORAGE_LOCATION",
+ "outputs": [
+ {
+ "internalType": "bytes32",
+ "name": "",
+ "type": "bytes32"
+ }
+ ]
+ },
+ {
+ "inputs": [],
+ "stateMutability": "view",
+ "type": "function",
+ "name": "WARP_MESSENGER",
+ "outputs": [
+ {
+ "internalType": "contract IWarpMessenger",
+ "name": "",
+ "type": "address"
+ }
+ ]
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes32",
+ "name": "delegationID",
+ "type": "bytes32"
+ },
+ {
+ "internalType": "address",
+ "name": "rewardRecipient",
+ "type": "address"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function",
+ "name": "changeDelegatorRewardRecipient"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes32",
+ "name": "validationID",
+ "type": "bytes32"
+ },
+ {
+ "internalType": "address",
+ "name": "rewardRecipient",
+ "type": "address"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function",
+ "name": "changeValidatorRewardRecipient"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes32",
+ "name": "validationID",
+ "type": "bytes32"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function",
+ "name": "claimDelegationFees"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes32",
+ "name": "delegationID",
+ "type": "bytes32"
+ },
+ {
+ "internalType": "uint32",
+ "name": "messageIndex",
+ "type": "uint32"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function",
+ "name": "completeDelegatorRegistration"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes32",
+ "name": "delegationID",
+ "type": "bytes32"
+ },
+ {
+ "internalType": "uint32",
+ "name": "messageIndex",
+ "type": "uint32"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function",
+ "name": "completeDelegatorRemoval"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint32",
+ "name": "messageIndex",
+ "type": "uint32"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function",
+ "name": "completeValidatorRegistration",
+ "outputs": [
+ {
+ "internalType": "bytes32",
+ "name": "",
+ "type": "bytes32"
+ }
+ ]
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint32",
+ "name": "messageIndex",
+ "type": "uint32"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function",
+ "name": "completeValidatorRemoval",
+ "outputs": [
+ {
+ "internalType": "bytes32",
+ "name": "",
+ "type": "bytes32"
+ }
+ ]
+ },
+ {
+ "inputs": [],
+ "stateMutability": "view",
+ "type": "function",
+ "name": "erc20",
+ "outputs": [
+ {
+ "internalType": "contract IERC20Mintable",
+ "name": "",
+ "type": "address"
+ }
+ ]
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes32",
+ "name": "delegationID",
+ "type": "bytes32"
+ },
+ {
+ "internalType": "bool",
+ "name": "includeUptimeProof",
+ "type": "bool"
+ },
+ {
+ "internalType": "uint32",
+ "name": "messageIndex",
+ "type": "uint32"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function",
+ "name": "forceInitiateDelegatorRemoval"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes32",
+ "name": "validationID",
+ "type": "bytes32"
+ },
+ {
+ "internalType": "bool",
+ "name": "includeUptimeProof",
+ "type": "bool"
+ },
+ {
+ "internalType": "uint32",
+ "name": "messageIndex",
+ "type": "uint32"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function",
+ "name": "forceInitiateValidatorRemoval"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes32",
+ "name": "delegationID",
+ "type": "bytes32"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function",
+ "name": "getDelegatorInfo",
+ "outputs": [
+ {
+ "internalType": "struct Delegator",
+ "name": "",
+ "type": "tuple",
+ "components": [
+ {
+ "internalType": "enum DelegatorStatus",
+ "name": "status",
+ "type": "uint8"
+ },
+ {
+ "internalType": "address",
+ "name": "owner",
+ "type": "address"
+ },
+ {
+ "internalType": "bytes32",
+ "name": "validationID",
+ "type": "bytes32"
+ },
+ {
+ "internalType": "uint64",
+ "name": "weight",
+ "type": "uint64"
+ },
+ {
+ "internalType": "uint64",
+ "name": "startTime",
+ "type": "uint64"
+ },
+ {
+ "internalType": "uint64",
+ "name": "startingNonce",
+ "type": "uint64"
+ },
+ {
+ "internalType": "uint64",
+ "name": "endingNonce",
+ "type": "uint64"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes32",
+ "name": "delegationID",
+ "type": "bytes32"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function",
+ "name": "getDelegatorRewardInfo",
+ "outputs": [
+ {
+ "internalType": "address",
+ "name": "",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ]
+ },
+ {
+ "inputs": [],
+ "stateMutability": "view",
+ "type": "function",
+ "name": "getStakingManagerSettings",
+ "outputs": [
+ {
+ "internalType": "struct StakingManagerSettings",
+ "name": "",
+ "type": "tuple",
+ "components": [
+ {
+ "internalType": "contract IValidatorManager",
+ "name": "manager",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "minimumStakeAmount",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maximumStakeAmount",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint64",
+ "name": "minimumStakeDuration",
+ "type": "uint64"
+ },
+ {
+ "internalType": "uint16",
+ "name": "minimumDelegationFeeBips",
+ "type": "uint16"
+ },
+ {
+ "internalType": "uint8",
+ "name": "maximumStakeMultiplier",
+ "type": "uint8"
+ },
+ {
+ "internalType": "uint256",
+ "name": "weightToValueFactor",
+ "type": "uint256"
+ },
+ {
+ "internalType": "contract IRewardCalculator",
+ "name": "rewardCalculator",
+ "type": "address"
+ },
+ {
+ "internalType": "bytes32",
+ "name": "uptimeBlockchainID",
+ "type": "bytes32"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes32",
+ "name": "validationID",
+ "type": "bytes32"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function",
+ "name": "getStakingValidator",
+ "outputs": [
+ {
+ "internalType": "struct PoSValidatorInfo",
+ "name": "",
+ "type": "tuple",
+ "components": [
+ {
+ "internalType": "address",
+ "name": "owner",
+ "type": "address"
+ },
+ {
+ "internalType": "uint16",
+ "name": "delegationFeeBips",
+ "type": "uint16"
+ },
+ {
+ "internalType": "uint64",
+ "name": "minStakeDuration",
+ "type": "uint64"
+ },
+ {
+ "internalType": "uint64",
+ "name": "uptimeSeconds",
+ "type": "uint64"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes32",
+ "name": "validationID",
+ "type": "bytes32"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function",
+ "name": "getValidatorRewardInfo",
+ "outputs": [
+ {
+ "internalType": "address",
+ "name": "",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ]
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "struct StakingManagerSettings",
+ "name": "settings",
+ "type": "tuple",
+ "components": [
+ {
+ "internalType": "contract IValidatorManager",
+ "name": "manager",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "minimumStakeAmount",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maximumStakeAmount",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint64",
+ "name": "minimumStakeDuration",
+ "type": "uint64"
+ },
+ {
+ "internalType": "uint16",
+ "name": "minimumDelegationFeeBips",
+ "type": "uint16"
+ },
+ {
+ "internalType": "uint8",
+ "name": "maximumStakeMultiplier",
+ "type": "uint8"
+ },
+ {
+ "internalType": "uint256",
+ "name": "weightToValueFactor",
+ "type": "uint256"
+ },
+ {
+ "internalType": "contract IRewardCalculator",
+ "name": "rewardCalculator",
+ "type": "address"
+ },
+ {
+ "internalType": "bytes32",
+ "name": "uptimeBlockchainID",
+ "type": "bytes32"
+ }
+ ]
+ },
+ {
+ "internalType": "contract IERC20Mintable",
+ "name": "token",
+ "type": "address"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function",
+ "name": "initialize"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes32",
+ "name": "validationID",
+ "type": "bytes32"
+ },
+ {
+ "internalType": "uint256",
+ "name": "delegationAmount",
+ "type": "uint256"
+ },
+ {
+ "internalType": "address",
+ "name": "rewardRecipient",
+ "type": "address"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function",
+ "name": "initiateDelegatorRegistration",
+ "outputs": [
+ {
+ "internalType": "bytes32",
+ "name": "",
+ "type": "bytes32"
+ }
+ ]
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes32",
+ "name": "delegationID",
+ "type": "bytes32"
+ },
+ {
+ "internalType": "bool",
+ "name": "includeUptimeProof",
+ "type": "bool"
+ },
+ {
+ "internalType": "uint32",
+ "name": "messageIndex",
+ "type": "uint32"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function",
+ "name": "initiateDelegatorRemoval"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes",
+ "name": "nodeID",
+ "type": "bytes"
+ },
+ {
+ "internalType": "bytes",
+ "name": "blsPublicKey",
+ "type": "bytes"
+ },
+ {
+ "internalType": "struct PChainOwner",
+ "name": "remainingBalanceOwner",
+ "type": "tuple",
+ "components": [
+ {
+ "internalType": "uint32",
+ "name": "threshold",
+ "type": "uint32"
+ },
+ {
+ "internalType": "address[]",
+ "name": "addresses",
+ "type": "address[]"
+ }
+ ]
+ },
+ {
+ "internalType": "struct PChainOwner",
+ "name": "disableOwner",
+ "type": "tuple",
+ "components": [
+ {
+ "internalType": "uint32",
+ "name": "threshold",
+ "type": "uint32"
+ },
+ {
+ "internalType": "address[]",
+ "name": "addresses",
+ "type": "address[]"
+ }
+ ]
+ },
+ {
+ "internalType": "uint16",
+ "name": "delegationFeeBips",
+ "type": "uint16"
+ },
+ {
+ "internalType": "uint64",
+ "name": "minStakeDuration",
+ "type": "uint64"
+ },
+ {
+ "internalType": "uint256",
+ "name": "stakeAmount",
+ "type": "uint256"
+ },
+ {
+ "internalType": "address",
+ "name": "rewardRecipient",
+ "type": "address"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function",
+ "name": "initiateValidatorRegistration",
+ "outputs": [
+ {
+ "internalType": "bytes32",
+ "name": "",
+ "type": "bytes32"
+ }
+ ]
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes32",
+ "name": "validationID",
+ "type": "bytes32"
+ },
+ {
+ "internalType": "bool",
+ "name": "includeUptimeProof",
+ "type": "bool"
+ },
+ {
+ "internalType": "uint32",
+ "name": "messageIndex",
+ "type": "uint32"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function",
+ "name": "initiateValidatorRemoval"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes32",
+ "name": "delegationID",
+ "type": "bytes32"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function",
+ "name": "resendUpdateDelegator"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes32",
+ "name": "validationID",
+ "type": "bytes32"
+ },
+ {
+ "internalType": "uint32",
+ "name": "messageIndex",
+ "type": "uint32"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function",
+ "name": "submitUptimeProof"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint256",
+ "name": "value",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function",
+ "name": "valueToWeight",
+ "outputs": [
+ {
+ "internalType": "uint64",
+ "name": "",
+ "type": "uint64"
+ }
+ ]
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint64",
+ "name": "weight",
+ "type": "uint64"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function",
+ "name": "weightToValue",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ]
+ }
+ ],
+ "devdoc": {
+ "kind": "dev",
+ "methods": {
+ "getDelegatorRewardInfo(bytes32)": {
+ "returns": {
+ "_0": "The current delegation reward recipient",
+ "_1": "The current claimable delegation reward amount"
+ }
+ },
+ "getValidatorRewardInfo(bytes32)": {
+ "returns": {
+ "_0": "The current validation reward recipient",
+ "_1": "The current claimable validation reward amount"
+ }
+ },
+ "initialize((address,uint256,uint256,uint64,uint16,uint8,uint256,address,bytes32),address)": {
+ "params": {
+ "settings": "Initial settings for the PoS validator manager",
+ "token": "The ERC20 token to be staked"
+ }
+ },
+ "resendUpdateDelegator(bytes32)": {
+ "details": "Resending the latest validator weight with the latest nonce is safe because all weight changes are cumulative, so the latest weight change will always include the weight change for any added delegators."
+ },
+ "valueToWeight(uint256)": {
+ "params": {
+ "value": "Token value to convert."
+ }
+ },
+ "weightToValue(uint64)": {
+ "params": {
+ "weight": "weight to convert."
+ }
+ }
+ },
+ "version": 1
+ },
+ "userdoc": {
+ "kind": "user",
+ "methods": {
+ "changeDelegatorRewardRecipient(bytes32,address)": {
+ "notice": "See {IStakingManager-changeDelegatorRewardRecipient}."
+ },
+ "changeValidatorRewardRecipient(bytes32,address)": {
+ "notice": "See {IStakingManager-changeValidatorRewardRecipient}."
+ },
+ "claimDelegationFees(bytes32)": {
+ "notice": "See {IStakingManager-claimDelegationFees}."
+ },
+ "completeDelegatorRegistration(bytes32,uint32)": {
+ "notice": "See {IStakingManager-completeDelegatorRegistration}. Extends the functionality of {ACP99Manager-completeValidatorWeightUpdate} by updating the delegation status."
+ },
+ "completeDelegatorRemoval(bytes32,uint32)": {
+ "notice": "See {IStakingManager-completeDelegatorRemoval}. Extends the functionality of {ACP99Manager-completeValidatorWeightUpdate} by updating the delegation status and unlocking delegation rewards."
+ },
+ "completeValidatorRegistration(uint32)": {
+ "notice": "See {IStakingManager-completeValidatorRegistration}."
+ },
+ "completeValidatorRemoval(uint32)": {
+ "notice": "See {IStakingManager-completeValidatorRemoval}. Extends the functionality of {ACP99Manager-completeValidatorRemoval} by unlocking staking rewards."
+ },
+ "erc20()": {
+ "notice": "Returns the ERC20 token being staked"
+ },
+ "forceInitiateDelegatorRemoval(bytes32,bool,uint32)": {
+ "notice": "See {IStakingManager-forceInitiateDelegatorRemoval}."
+ },
+ "forceInitiateValidatorRemoval(bytes32,bool,uint32)": {
+ "notice": "See {IStakingManager-forceInitiateValidatorRemoval}."
+ },
+ "getDelegatorInfo(bytes32)": {
+ "notice": "Returns the delegator information for the given delegationID"
+ },
+ "getDelegatorRewardInfo(bytes32)": {
+ "notice": "Returns the reward recipient and claimable reward amount for the given delegationID"
+ },
+ "getStakingManagerSettings()": {
+ "notice": "Returns the settings used to initialize the StakingManager"
+ },
+ "getStakingValidator(bytes32)": {
+ "notice": "Returns the PoS validator information for the given validationID See {ValidatorManager-getValidator} to retreive information about the validator not specific to PoS"
+ },
+ "getValidatorRewardInfo(bytes32)": {
+ "notice": "Returns the reward recipient and claimable reward amount for the given validationID"
+ },
+ "initialize((address,uint256,uint256,uint64,uint16,uint8,uint256,address,bytes32),address)": {
+ "notice": "Initialize the ERC20 token staking manager"
+ },
+ "initiateDelegatorRegistration(bytes32,uint256,address)": {
+ "notice": "See {IERC20TokenStakingManager-initiateDelegatorRegistration}"
+ },
+ "initiateDelegatorRemoval(bytes32,bool,uint32)": {
+ "notice": "See {IStakingManager-initiateDelegatorRemoval}."
+ },
+ "initiateValidatorRegistration(bytes,bytes,(uint32,address[]),(uint32,address[]),uint16,uint64,uint256,address)": {
+ "notice": "See {IERC20TokenStakingManager-initiateValidatorRegistration}"
+ },
+ "initiateValidatorRemoval(bytes32,bool,uint32)": {
+ "notice": "See {IStakingManager-initiateValidatorRemoval}."
+ },
+ "resendUpdateDelegator(bytes32)": {
+ "notice": "See {IStakingManager-resendUpdateDelegator}."
+ },
+ "submitUptimeProof(bytes32,uint32)": {
+ "notice": "See {IStakingManager-submitUptimeProof}."
+ },
+ "valueToWeight(uint256)": {
+ "notice": "Converts a token value to a weight."
+ },
+ "weightToValue(uint64)": {
+ "notice": "Converts a weight to a token value."
+ }
+ },
+ "version": 1
+ }
+ },
+ "settings": {
+ "remappings": [
+ "@avalabs/subnet-evm-contracts@1.2.2/=lib/subnet-evm/contracts/",
+ "@forge-std/=lib/forge-std/src/",
+ "@mocks/=contracts/mocks/",
+ "@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/",
+ "@openzeppelin/contracts-upgradeable@5.0.2/=lib/openzeppelin-contracts-upgradeable/contracts/",
+ "@openzeppelin/contracts/=lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/",
+ "@openzeppelin/contracts@5.0.2/=lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/",
+ "@teleporter/=contracts/teleporter/",
+ "@utilities/=contracts/utilities/",
+ "ds-test/=lib/openzeppelin-contracts-upgradeable/lib/forge-std/lib/ds-test/src/",
+ "erc4626-tests/=lib/openzeppelin-contracts-upgradeable/lib/erc4626-tests/",
+ "forge-std/=lib/forge-std/src/",
+ "openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/",
+ "openzeppelin-contracts/=lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/",
+ "subnet-evm/=lib/subnet-evm/"
+ ],
+ "optimizer": {
+ "enabled": true,
+ "runs": 200
+ },
+ "metadata": {
+ "bytecodeHash": "none"
+ },
+ "compilationTarget": {
+ "contracts/validator-manager/ERC20TokenStakingManager.sol": "ERC20TokenStakingManager"
+ },
+ "evmVersion": "shanghai",
+ "libraries": {}
+ },
+ "sources": {
+ "contracts/utilities/ICMInitializable.sol": {
+ "keccak256": "0x84f559fe344442572165246f83ed5a0ce23be1d1504f8317d94650a88c666976",
+ "urls": [
+ "bzz-raw://9deb4a9fc5b1b0fd9b457900617765f7a3d24ed3bd32c78d31400cf22146baf9",
+ "dweb:/ipfs/QmcKwpA3xG5uDo35bevigKmY4zR6zjgAQD8JDmzmnDPjdC"
+ ],
+ "license": "LicenseRef-Ecosystem"
+ },
+ "contracts/utilities/SafeERC20TransferFrom.sol": {
+ "keccak256": "0x485867dc46af4ee0812024758b2f3493b3efc15f8ba23d73223dd847b04c8018",
+ "urls": [
+ "bzz-raw://2b9b29d8ee033a2ed8dd1bdb024027704f1180a1316732cb3d3874898d277736",
+ "dweb:/ipfs/QmR257FurAqL57rzY1BVJhxCS6yndrBow1J4hMHCwfcvyA"
+ ],
+ "license": "LicenseRef-Ecosystem"
+ },
+ "contracts/validator-manager/ACP99Manager.sol": {
+ "keccak256": "0xac707d933ce27e52de51c11dc2d47d7d8bb97273c24d05c2585fe22efb058889",
+ "urls": [
+ "bzz-raw://aafe1df2053a34836dbf7ba7b2768377f454976fcf50621ead0c542f1fe9cde6",
+ "dweb:/ipfs/QmSx1EDEbuFLRMKDnBvq3hZvpKTr8Jx9zqVwsV1wxrW1oG"
+ ],
+ "license": "LicenseRef-Ecosystem"
+ },
+ "contracts/validator-manager/ERC20TokenStakingManager.sol": {
+ "keccak256": "0xc1082cae1172c399e7a279256de533805c77242bf4f24342e9c4d38a2af05ef2",
+ "urls": [
+ "bzz-raw://405e09bf9bd7397242024cd5aece047b82cdfcd5b5a0edd1972fb21acb6047f9",
+ "dweb:/ipfs/Qmbgd7wqHRriajD1qTmo8twWb8rqRVYYta3QaGTNtpHeh5"
+ ],
+ "license": "LicenseRef-Ecosystem"
+ },
+ "contracts/validator-manager/StakingManager.sol": {
+ "keccak256": "0xf8906325bbeeb4b51840b0e8562572ca1f9f926581cd04e64eb90c7ec78f7625",
+ "urls": [
+ "bzz-raw://76ec5debcca9b31009c18c6802058411470f426ff1dc0960486d40d50268397e",
+ "dweb:/ipfs/QmXocGvrshPq5TEPeyy5o4wwYU3umasQVq1pBwDiuizNEz"
+ ],
+ "license": "LicenseRef-Ecosystem"
+ },
+ "contracts/validator-manager/ValidatorMessages.sol": {
+ "keccak256": "0x47938a3226d2fa48028954bffcdef4eddeb2fedd366cea6617682c7813ea685e",
+ "urls": [
+ "bzz-raw://f1a148a96f6c2b30777cc6f8b634f3c21ee6765e4037e3623c10bfcb6c32c439",
+ "dweb:/ipfs/QmVyeMqdaa8DgXf2Nor4rd1DRB4MpouiUioecr9kecXS9E"
+ ],
+ "license": "LicenseRef-Ecosystem"
+ },
+ "contracts/validator-manager/interfaces/IACP99Manager.sol": {
+ "keccak256": "0x284d77192a5dcae149064aa74591ae53e7af2c310bbf5d67ff9bc9517410c7b4",
+ "urls": [
+ "bzz-raw://492a40cdffd8ad0928ce5ab082fd9de6a2e65f2ae16e1ca233126f89e063e0fa",
+ "dweb:/ipfs/QmRyK7iyvK2jAHSjgtBfWrBUPjGYpsMD8dPL63Uy2ji8sk"
+ ],
+ "license": "LicenseRef-Ecosystem"
+ },
+ "contracts/validator-manager/interfaces/IERC20Mintable.sol": {
+ "keccak256": "0x2cfb122a4d1a8c4d4182f803838ef555f1333d541c91a1097ee353af9d56a5bb",
+ "urls": [
+ "bzz-raw://e6b05b96cc0b58364fe2243ebd38ae1e802e1a505da011554a693336acee1586",
+ "dweb:/ipfs/Qmc98C4RqiTkuCCJET1xtbP6Ty6tuSQAm3fYd9j7Uc3Raf"
+ ],
+ "license": "LicenseRef-Ecosystem"
+ },
+ "contracts/validator-manager/interfaces/IERC20TokenStakingManager.sol": {
+ "keccak256": "0x036cda784eecff72755c5a92539d39728304b13f8b0bf7a899b964aa6ae3aa64",
+ "urls": [
+ "bzz-raw://8b162c4a55a15bfe467e9bc16cb558edd6c70d17235ef3efe10d426fbe9c9f13",
+ "dweb:/ipfs/QmSH8JywT1jbZ9kBVvKLn1VeePuizrKc5DRuguURAP3bms"
+ ],
+ "license": "LicenseRef-Ecosystem"
+ },
+ "contracts/validator-manager/interfaces/IRewardCalculator.sol": {
+ "keccak256": "0x0e2ed48da58e2eda3766361e315467e2ba9f258e48684501ab337e8a65c29e47",
+ "urls": [
+ "bzz-raw://faf1da0f5d33fa1f9e7d29ada9884dc6554b47b4d948af6f1f6261153414e42a",
+ "dweb:/ipfs/QmTn97vcnd3Haf9fBVvBzLenp8xwdGGnnzxwxuK9Yt3ryi"
+ ],
+ "license": "LicenseRef-Ecosystem"
+ },
+ "contracts/validator-manager/interfaces/IStakingManager.sol": {
+ "keccak256": "0xe7e86b636fb493642beef2dfa27da6029aaba8bd0dc88deb99b5ffe05e0c645a",
+ "urls": [
+ "bzz-raw://566b5e00ba692164d948af776f5d127ac813541ee390d330629138aa43340864",
+ "dweb:/ipfs/QmVEkhcF8XnkKA4hkeXWdCMpsvpe45DssHzP56h7mQaGrf"
+ ],
+ "license": "LicenseRef-Ecosystem"
+ },
+ "contracts/validator-manager/interfaces/IValidatorManager.sol": {
+ "keccak256": "0x59ba881e14793d6e84ef72fdf6db03da2117694d0cf4e17f21989fc5a76a9ebb",
+ "urls": [
+ "bzz-raw://f84232c4adaa616ae90a27f2d2bb169a4331ccb074a26c98f83636da139383d2",
+ "dweb:/ipfs/QmNj4DKvEZoCi8NvnYdHCZLHJvDt8sdDVqg85Fk61Pff65"
+ ],
+ "license": "LicenseRef-Ecosystem"
+ },
+ "lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol": {
+ "keccak256": "0x631188737069917d2f909d29ce62c4d48611d326686ba6683e26b72a23bfac0b",
+ "urls": [
+ "bzz-raw://7a61054ae84cd6c4d04c0c4450ba1d6de41e27e0a2c4f1bcdf58f796b401c609",
+ "dweb:/ipfs/QmUvtdp7X1mRVyC3CsHrtPbgoqWaXHp3S1ZR24tpAQYJWM"
+ ],
+ "license": "MIT"
+ },
+ "lib/openzeppelin-contracts-upgradeable/contracts/utils/ContextUpgradeable.sol": {
+ "keccak256": "0xdbef5f0c787055227243a7318ef74c8a5a1108ca3a07f2b3a00ef67769e1e397",
+ "urls": [
+ "bzz-raw://08e39f23d5b4692f9a40803e53a8156b72b4c1f9902a88cd65ba964db103dab9",
+ "dweb:/ipfs/QmPKn6EYDgpga7KtpkA8wV2yJCYGMtc9K4LkJfhKX2RVSV"
+ ],
+ "license": "MIT"
+ },
+ "lib/openzeppelin-contracts-upgradeable/contracts/utils/ReentrancyGuardUpgradeable.sol": {
+ "keccak256": "0xb44e086e941292cdc7f440de51478493894ef0b1aeccb0c4047445919f667f74",
+ "urls": [
+ "bzz-raw://942dad22fbdc1669f025540ba63aa3ccfad5f8458fc5d4525b31ebf272e7af45",
+ "dweb:/ipfs/Qmdo4X2M82aM3AMoW2kf2jhYkSCyC4T1pHNd6obdsDFnAB"
+ ],
+ "license": "MIT"
+ },
+ "lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol": {
+ "keccak256": "0xc6a8ff0ea489379b61faa647490411b80102578440ab9d84e9a957cc12164e70",
+ "urls": [
+ "bzz-raw://0ea104e577e63faea3b69c415637e99e755dcbf64c5833d7140c35a714d6d90c",
+ "dweb:/ipfs/Qmau6x4Ns9XdyynRCNNp3RhLqijJjFm7z5fyZazfYFGYdq"
+ ],
+ "license": "MIT"
+ },
+ "lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol": {
+ "keccak256": "0x6008dabfe393240d73d7dd7688033f72740d570aa422254d29a7dce8568f3aff",
+ "urls": [
+ "bzz-raw://f5196ec75139918c6c7bb4251b36395e668f1fa6d206beba7e7520e74913940d",
+ "dweb:/ipfs/QmSyqjksXxmm2mCG6qRd1yuwLykypkSVBbnBnGqJRcuJMi"
+ ],
+ "license": "MIT"
+ },
+ "lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol": {
+ "keccak256": "0x37bb49513c49c87c4642a891b13b63571bc87013dde806617aa1efb54605f386",
+ "urls": [
+ "bzz-raw://b3036b3a83b7c48f96641f2a9002b9f2dcb6a5958dd670894ada21ae8229b3d0",
+ "dweb:/ipfs/QmUNfSBdoVtjhETaUJCYcaC7pTMgbhht926tJ2uXJbiVd3"
+ ],
+ "license": "MIT"
+ },
+ "lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/utils/Address.sol": {
+ "keccak256": "0xaf28a975a78550e45f65e559a3ad6a5ad43b9b8a37366999abd1b7084eb70721",
+ "urls": [
+ "bzz-raw://b7bd24e224f67f65bfadf85dc2929fa965456bb2415478bd0125471b5ce35245",
+ "dweb:/ipfs/QmRaydGr8BTHs1kvaZfsNU69pKzUAGFrvABn1KiRSbE51y"
+ ],
+ "license": "MIT"
+ },
+ "lib/subnet-evm/contracts/contracts/interfaces/IWarpMessenger.sol": {
+ "keccak256": "0x9f75d13b8995e3b13a39b88b9f7d8046a3127c1b81abcd202c2438ddece42819",
+ "urls": [
+ "bzz-raw://12af89d9499252371faa23dfc13b4067876f7d7b6b01a1a3d891cbf7c9b1f90c",
+ "dweb:/ipfs/QmXntNu3vLECvSAJdacsebtecoaUpeYvUDATpxS5GbB8bL"
+ ],
+ "license": "MIT"
+ }
+ },
+ "version": 1
+ },
+ "id": 92
+}
diff --git a/contracts/icm-contracts/entrypoint.sh b/contracts/icm-contracts/entrypoint.sh
index c49efbf21fc..ec2d421df7f 100755
--- a/contracts/icm-contracts/entrypoint.sh
+++ b/contracts/icm-contracts/entrypoint.sh
@@ -35,6 +35,7 @@ for file in \
/teleporter_src/out/TeleporterRegistry.sol/TeleporterRegistry.json \
/teleporter_src/out/TeleporterMessenger.sol/TeleporterMessenger.json \
/teleporter_src/out/NativeTokenStakingManager.sol/NativeTokenStakingManager.json \
+ /teleporter_src/out/ERC20TokenStakingManager.sol/ERC20TokenStakingManager.json \
/teleporter_src/out/ExampleERC20.sol/ExampleERC20.json \
/teleporter_src/out/ERC20TokenHome.sol/ERC20TokenHome.json \
/teleporter_src/out/ERC20TokenRemote.sol/ERC20TokenRemote.json \
From 686712cfc6a2351e2bfca1e1c2ecadf1812aa0ed Mon Sep 17 00:00:00 2001
From: Owen
Date: Thu, 25 Sep 2025 15:24:06 -0400
Subject: [PATCH 02/12] update sidebar to split native and erc20 staking
manager
---
components/console/console-sidebar.tsx | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/components/console/console-sidebar.tsx b/components/console/console-sidebar.tsx
index 21284746990..c3ae385ed96 100644
--- a/components/console/console-sidebar.tsx
+++ b/components/console/console-sidebar.tsx
@@ -221,8 +221,13 @@ const data = {
icon: Globe,
items: [
{
- title: "Migrate from Permissioned L1",
- url: "/console/permissionless-l1s/staking-manager-setup",
+ title: "Native Staking Manager Setup",
+ url: "/console/permissionless-l1s/native-staking-manager-setup",
+ icon: GitMerge,
+ },
+ {
+ title: "ERC20 Staking Manager Setup",
+ url: "/console/permissionless-l1s/erc20-staking-manager-setup",
icon: GitMerge,
},
{
From 4cf5a4e22f87c525b278d91b6d15bdebdef5cf6d Mon Sep 17 00:00:00 2001
From: Owen
Date: Thu, 25 Sep 2025 15:50:21 -0400
Subject: [PATCH 03/12] use new notify hook, fix bug in native init
---
.../[step]/client-page.tsx | 15 +++++++
.../[step]/page.tsx | 8 ++++
.../erc20-staking-manager-setup/page.tsx | 7 +++
.../erc20-staking-manager-setup/steps.ts | 27 ++++++++++++
.../[step]/client-page.tsx | 15 +++++++
.../[step]/page.tsx | 8 ++++
.../native-staking-manager-setup/page.tsx | 7 +++
.../native-staking-manager-setup/steps.ts | 28 ++++++++++++
.../validator-manager-setup/Initialize.tsx | 17 +++----
.../setup/DeployExampleRewardCalculator.tsx | 19 ++++++--
.../setup/erc20/DeployERC20StakingManager.tsx | 15 ++++++-
.../erc20/InitializeERC20StakingManager.tsx | 44 +++++++++++++++++--
.../native/DeployNativeStakingManager.tsx | 15 ++++++-
.../native/InitializeNativeStakingManager.tsx | 44 +++++++++++++++++--
14 files changed, 248 insertions(+), 21 deletions(-)
create mode 100644 app/console/permissionless-l1s/erc20-staking-manager-setup/[step]/client-page.tsx
create mode 100644 app/console/permissionless-l1s/erc20-staking-manager-setup/[step]/page.tsx
create mode 100644 app/console/permissionless-l1s/erc20-staking-manager-setup/page.tsx
create mode 100644 app/console/permissionless-l1s/erc20-staking-manager-setup/steps.ts
create mode 100644 app/console/permissionless-l1s/native-staking-manager-setup/[step]/client-page.tsx
create mode 100644 app/console/permissionless-l1s/native-staking-manager-setup/[step]/page.tsx
create mode 100644 app/console/permissionless-l1s/native-staking-manager-setup/page.tsx
create mode 100644 app/console/permissionless-l1s/native-staking-manager-setup/steps.ts
diff --git a/app/console/permissionless-l1s/erc20-staking-manager-setup/[step]/client-page.tsx b/app/console/permissionless-l1s/erc20-staking-manager-setup/[step]/client-page.tsx
new file mode 100644
index 00000000000..6cbb711dd7b
--- /dev/null
+++ b/app/console/permissionless-l1s/erc20-staking-manager-setup/[step]/client-page.tsx
@@ -0,0 +1,15 @@
+"use client";
+
+import StepFlow from "@/components/console/step-flow";
+import { steps } from "../steps";
+
+export default function ERC20StakingManagerSetupClientPage({ currentStepKey }: { currentStepKey: string }) {
+ const basePath = "/console/permissionless-l1s/erc20-staking-manager-setup";
+ return (
+
+ );
+}
diff --git a/app/console/permissionless-l1s/erc20-staking-manager-setup/[step]/page.tsx b/app/console/permissionless-l1s/erc20-staking-manager-setup/[step]/page.tsx
new file mode 100644
index 00000000000..111cb362311
--- /dev/null
+++ b/app/console/permissionless-l1s/erc20-staking-manager-setup/[step]/page.tsx
@@ -0,0 +1,8 @@
+import ERC20StakingManagerSetupClientPage from "./client-page";
+
+export default async function Page({ params }: { params: Promise<{ step: string }> }) {
+ const { step } = await params;
+ return (
+
+ );
+}
diff --git a/app/console/permissionless-l1s/erc20-staking-manager-setup/page.tsx b/app/console/permissionless-l1s/erc20-staking-manager-setup/page.tsx
new file mode 100644
index 00000000000..9cd25c725fb
--- /dev/null
+++ b/app/console/permissionless-l1s/erc20-staking-manager-setup/page.tsx
@@ -0,0 +1,7 @@
+import { redirect } from "next/navigation";
+
+export default function Page() {
+ redirect("/console/permissionless-l1s/erc20-staking-manager-setup/deploy-erc20-staking-manager");
+}
+
+
diff --git a/app/console/permissionless-l1s/erc20-staking-manager-setup/steps.ts b/app/console/permissionless-l1s/erc20-staking-manager-setup/steps.ts
new file mode 100644
index 00000000000..8b12dec98ab
--- /dev/null
+++ b/app/console/permissionless-l1s/erc20-staking-manager-setup/steps.ts
@@ -0,0 +1,27 @@
+import { type StepDefinition } from "@/components/console/step-flow";
+import ReadContract from "@/components/toolbox/console/permissioned-l1s/validator-manager-setup/ReadContract";
+import DeployNativeTokenStakingManager from "@/components/toolbox/console/permissionless-l1s/setup/native/DeployNativeStakingManager";
+import InitializeNativeTokenStakingManager from "@/components/toolbox/console/permissionless-l1s/setup/native/InitializeNativeStakingManager";
+import DeployERC20StakingManager from "@/components/toolbox/console/permissionless-l1s/setup/erc20/DeployERC20StakingManager";
+import InitializeERC20StakingManager from "@/components/toolbox/console/permissionless-l1s/setup/erc20/InitializeERC20StakingManager";
+import DeployExampleRewardCalculator from "@/components/toolbox/console/permissionless-l1s/setup/DeployExampleRewardCalculator";
+import TransferOwnership from "@/components/toolbox/console/permissioned-l1s/multisig-setup/TransferOwnership";
+import EnableStakingManagerMinting from "@/components/toolbox/console/permissionless-l1s/setup/native/EnableStakingManagerMinting";
+
+export const steps: StepDefinition[] = [
+ {
+ type: "single",
+ key: "deploy-erc20-staking-manager",
+ title: "Deploy ERC20 Token Staking Manager",
+ component: DeployERC20StakingManager,
+ },
+ { type: "single", key: "deploy-example-reward-calculator", title: "Deploy Example Reward Calculator", component: DeployExampleRewardCalculator },
+ {
+ type: "single",
+ key: "initialize-erc20-staking-manager",
+ title: "Initialize ERC20 Token Staking Manager",
+ component: InitializeERC20StakingManager,
+ },
+ { type: "single", key: "transfer-ownership", title: "Transfer Ownership", component: TransferOwnership },
+ { type: "single", key: "read-contract", title: "Read Contract", component: ReadContract },
+];
diff --git a/app/console/permissionless-l1s/native-staking-manager-setup/[step]/client-page.tsx b/app/console/permissionless-l1s/native-staking-manager-setup/[step]/client-page.tsx
new file mode 100644
index 00000000000..ff33f3c11f0
--- /dev/null
+++ b/app/console/permissionless-l1s/native-staking-manager-setup/[step]/client-page.tsx
@@ -0,0 +1,15 @@
+"use client";
+
+import StepFlow from "@/components/console/step-flow";
+import { steps } from "../steps";
+
+export default function NativeStakingManagerSetupClientPage({ currentStepKey }: { currentStepKey: string }) {
+ const basePath = "/console/permissionless-l1s/native-staking-manager-setup";
+ return (
+
+ );
+}
diff --git a/app/console/permissionless-l1s/native-staking-manager-setup/[step]/page.tsx b/app/console/permissionless-l1s/native-staking-manager-setup/[step]/page.tsx
new file mode 100644
index 00000000000..26e85795d63
--- /dev/null
+++ b/app/console/permissionless-l1s/native-staking-manager-setup/[step]/page.tsx
@@ -0,0 +1,8 @@
+import NativeStakingManagerSetupClientPage from "./client-page";
+
+export default async function Page({ params }: { params: Promise<{ step: string }> }) {
+ const { step } = await params;
+ return (
+
+ );
+}
diff --git a/app/console/permissionless-l1s/native-staking-manager-setup/page.tsx b/app/console/permissionless-l1s/native-staking-manager-setup/page.tsx
new file mode 100644
index 00000000000..d5efb969be1
--- /dev/null
+++ b/app/console/permissionless-l1s/native-staking-manager-setup/page.tsx
@@ -0,0 +1,7 @@
+import { redirect } from "next/navigation";
+
+export default function Page() {
+ redirect("/console/permissionless-l1s/native-staking-manager-setup/deploy-native-token-staking-manager");
+}
+
+
diff --git a/app/console/permissionless-l1s/native-staking-manager-setup/steps.ts b/app/console/permissionless-l1s/native-staking-manager-setup/steps.ts
new file mode 100644
index 00000000000..4ea89b2aa9e
--- /dev/null
+++ b/app/console/permissionless-l1s/native-staking-manager-setup/steps.ts
@@ -0,0 +1,28 @@
+import { type StepDefinition } from "@/components/console/step-flow";
+import ReadContract from "@/components/toolbox/console/permissioned-l1s/validator-manager-setup/ReadContract";
+import DeployNativeTokenStakingManager from "@/components/toolbox/console/permissionless-l1s/setup/native/DeployNativeStakingManager";
+import InitializeNativeTokenStakingManager from "@/components/toolbox/console/permissionless-l1s/setup/native/InitializeNativeStakingManager";
+import DeployERC20StakingManager from "@/components/toolbox/console/permissionless-l1s/setup/erc20/DeployERC20StakingManager";
+import InitializeERC20StakingManager from "@/components/toolbox/console/permissionless-l1s/setup/erc20/InitializeERC20StakingManager";
+import DeployExampleRewardCalculator from "@/components/toolbox/console/permissionless-l1s/setup/DeployExampleRewardCalculator";
+import TransferOwnership from "@/components/toolbox/console/permissioned-l1s/multisig-setup/TransferOwnership";
+import EnableStakingManagerMinting from "@/components/toolbox/console/permissionless-l1s/setup/native/EnableStakingManagerMinting";
+
+export const steps: StepDefinition[] = [
+ {
+ type: "single",
+ key: "deploy-native-token-staking-manager",
+ title: "Deploy Staking Manager",
+ component: DeployNativeTokenStakingManager,
+ },
+ { type: "single", key: "deploy-example-reward-calculator", title: "Deploy Example Reward Calculator", component: DeployExampleRewardCalculator },
+ {
+ type: "single",
+ key: "initialize-native-staking-manager",
+ title: "Initialize Staking Manager",
+ component: InitializeNativeTokenStakingManager,
+ },
+ { type: "single", key: "enable-staking-minting", title: "Enable StakingManager in Native Minter", component: EnableStakingManagerMinting, optional: true },
+ { type: "single", key: "transfer-ownership", title: "Transfer Ownership", component: TransferOwnership },
+ { type: "single", key: "read-contract", title: "Read Contract", component: ReadContract },
+];
diff --git a/components/toolbox/console/permissioned-l1s/validator-manager-setup/Initialize.tsx b/components/toolbox/console/permissioned-l1s/validator-manager-setup/Initialize.tsx
index 81ea6dea897..4cbc52bdc2a 100644
--- a/components/toolbox/console/permissioned-l1s/validator-manager-setup/Initialize.tsx
+++ b/components/toolbox/console/permissioned-l1s/validator-manager-setup/Initialize.tsx
@@ -28,7 +28,6 @@ const metadata: ConsoleToolMetadata = {
};
function Initialize({ onSuccess }: BaseConsoleToolProps) {
- const [proxyAddress, setProxyAddress] = useState("");
const { walletEVMAddress, publicClient } = useWalletStore();
const { coreWalletClient } = useConnectedWallet();
const [isChecking, setIsChecking] = useState(false);
@@ -42,6 +41,8 @@ function Initialize({ onSuccess }: BaseConsoleToolProps) {
const selectedL1 = useSelectedL1()();
const [subnetId, setSubnetId] = useState("");
const createChainStoreSubnetId = useCreateChainStore()(state => state.subnetId);
+ const managerAddress = useCreateChainStore()(state => state.managerAddress);
+ const setManagerAddress = useCreateChainStore()(state => state.setManagerAddress);
const { sendCoreWalletNotSetNotification, notify } = useConsoleNotifications();
@@ -68,7 +69,7 @@ function Initialize({ onSuccess }: BaseConsoleToolProps) {
async function checkIfInitialized() {
- if (!proxyAddress || !window.avalanche) return;
+ if (!managerAddress || !window.avalanche) return;
setIsChecking(true);
try {
@@ -84,7 +85,7 @@ function Initialize({ onSuccess }: BaseConsoleToolProps) {
try {
// Try to call a read-only method that would fail if not initialized
const isInit = await publicClient.readContract({
- address: proxyAddress as `0x${string}`,
+ address: managerAddress as `0x${string}`,
abi: ValidatorManagerABI.abi,
functionName: 'admin'
});
@@ -109,7 +110,7 @@ function Initialize({ onSuccess }: BaseConsoleToolProps) {
const fromBlock = latestBlock > 2000n ? latestBlock - 2000n : 0n;
const logs = await publicClient.getLogs({
- address: proxyAddress as `0x${string}`,
+ address: managerAddress as `0x${string}`,
event: initializedEvent as AbiEvent,
fromBlock: fromBlock,
toBlock: 'latest'
@@ -142,7 +143,7 @@ function Initialize({ onSuccess }: BaseConsoleToolProps) {
};
const initPromise = coreWalletClient.writeContract({
- address: proxyAddress as `0x${string}`,
+ address: managerAddress as `0x${string}`,
abi: ValidatorManagerABI.abi,
functionName: 'initialize',
args: [settings],
@@ -174,8 +175,8 @@ function Initialize({ onSuccess }: BaseConsoleToolProps) {
@@ -183,7 +184,7 @@ function Initialize({ onSuccess }: BaseConsoleToolProps) {
Check Status
diff --git a/components/toolbox/console/permissionless-l1s/setup/DeployExampleRewardCalculator.tsx b/components/toolbox/console/permissionless-l1s/setup/DeployExampleRewardCalculator.tsx
index 119c1a23251..b234e8cee55 100644
--- a/components/toolbox/console/permissionless-l1s/setup/DeployExampleRewardCalculator.tsx
+++ b/components/toolbox/console/permissionless-l1s/setup/DeployExampleRewardCalculator.tsx
@@ -11,6 +11,7 @@ import { CheckWalletRequirements } from "@/components/toolbox/components/CheckWa
import { WalletRequirementsConfigKey } from "@/components/toolbox/hooks/useWalletRequirements";
import ExampleRewardCalculator from "@/contracts/icm-contracts/compiled/ExampleRewardCalculator.json";
import versions from '@/scripts/versions.json';
+import useConsoleNotifications from '@/hooks/useConsoleNotifications';
const ICM_COMMIT = versions["ava-labs/icm-contracts"];
const EXAMPLE_REWARD_CALCULATOR_SOURCE_URL = `https://github.com/ava-labs/icm-contracts/blob/${ICM_COMMIT}/contracts/validator-manager/ExampleRewardCalculator.sol`;
@@ -20,9 +21,10 @@ export default function DeployExampleRewardCalculator() {
const [isDeploying, setIsDeploying] = useState(false);
const [rewardBasisPoints, setRewardBasisPoints] = useState("500"); // Default 5% APR (500 basis points)
- const { coreWalletClient, publicClient } = useWalletStore();
+ const { coreWalletClient, publicClient, walletEVMAddress } = useWalletStore();
const viemChain = useViemChainStore();
const { rewardCalculatorAddress, setRewardCalculatorAddress } = useToolboxStore();
+ const { notify } = useConsoleNotifications();
// Throw critical errors during render
if (criticalError) {
@@ -33,18 +35,29 @@ export default function DeployExampleRewardCalculator() {
setIsDeploying(true);
setRewardCalculatorAddress("");
try {
+ if (!coreWalletClient) throw new Error("Wallet not connected");
+ if (!walletEVMAddress) throw new Error("Wallet address not available");
+ if (!viemChain) throw new Error("Chain not selected");
+
await coreWalletClient.addChain({ chain: viemChain });
await coreWalletClient.switchChain({ id: viemChain!.id });
// Let viem handle gas estimation automatically
// ExampleRewardCalculator is a simple contract, so auto-estimation should work
- const hash = await coreWalletClient.deployContract({
- abi: ExampleRewardCalculator.abi,
+ const deployPromise = coreWalletClient.deployContract({
+ abi: ExampleRewardCalculator.abi as any,
bytecode: ExampleRewardCalculator.bytecode.object as `0x${string}`,
args: [BigInt(rewardBasisPoints)], // Constructor takes uint64 rewardBasisPoints
chain: viemChain,
+ account: walletEVMAddress as `0x${string}`,
});
+ notify({
+ type: 'deploy',
+ name: 'Example Reward Calculator'
+ }, deployPromise, viemChain ?? undefined);
+
+ const hash = await deployPromise;
const receipt = await publicClient.waitForTransactionReceipt({ hash });
if (!receipt.contractAddress) {
diff --git a/components/toolbox/console/permissionless-l1s/setup/erc20/DeployERC20StakingManager.tsx b/components/toolbox/console/permissionless-l1s/setup/erc20/DeployERC20StakingManager.tsx
index 627a050d273..7c98dd6fc51 100644
--- a/components/toolbox/console/permissionless-l1s/setup/erc20/DeployERC20StakingManager.tsx
+++ b/components/toolbox/console/permissionless-l1s/setup/erc20/DeployERC20StakingManager.tsx
@@ -11,6 +11,7 @@ import { WalletRequirementsConfigKey } from "@/components/toolbox/hooks/useWalle
import ERC20TokenStakingManager from "@/contracts/icm-contracts/compiled/ERC20TokenStakingManager.json";
import versions from '@/scripts/versions.json';
import { keccak256 } from 'viem';
+import useConsoleNotifications from '@/hooks/useConsoleNotifications';
const ICM_COMMIT = versions["ava-labs/icm-contracts"];
const ERC20_TOKEN_STAKING_MANAGER_SOURCE_URL = `https://github.com/ava-labs/icm-contracts/blob/main/contracts/validator-manager/ERC20TokenStakingManager.sol`;
@@ -30,6 +31,7 @@ export default function DeployERC20StakingManager() {
const { coreWalletClient, publicClient, walletEVMAddress } = useWalletStore();
const viemChain = useViemChainStore();
const { erc20StakingManagerAddress, setErc20StakingManagerAddress, validatorMessagesLibAddress } = useToolboxStore();
+ const { notify } = useConsoleNotifications();
// Throw critical errors during render
if (criticalError) {
@@ -61,6 +63,8 @@ export default function DeployERC20StakingManager() {
setErc20StakingManagerAddress("");
try {
if (!viemChain) throw new Error("Viem chain not found");
+ if (!coreWalletClient) throw new Error("Wallet not connected");
+ if (!walletEVMAddress) throw new Error("Wallet address not available");
// Check for library first
if (!validatorMessagesLibAddress) {
@@ -71,13 +75,20 @@ export default function DeployERC20StakingManager() {
await coreWalletClient.addChain({ chain: viemChain });
await coreWalletClient.switchChain({ id: viemChain!.id });
- const hash = await coreWalletClient.deployContract({
- abi: ERC20TokenStakingManager.abi,
+ const deployPromise = coreWalletClient.deployContract({
+ abi: ERC20TokenStakingManager.abi as any,
bytecode: getLinkedBytecode(), // Use linked bytecode with library
args: [0], // ICMInitializable.Allowed
chain: viemChain,
+ account: walletEVMAddress as `0x${string}`,
});
+ notify({
+ type: 'deploy',
+ name: 'ERC20 Token Staking Manager'
+ }, deployPromise, viemChain ?? undefined);
+
+ const hash = await deployPromise;
const receipt = await publicClient.waitForTransactionReceipt({ hash });
if (!receipt.contractAddress) {
diff --git a/components/toolbox/console/permissionless-l1s/setup/erc20/InitializeERC20StakingManager.tsx b/components/toolbox/console/permissionless-l1s/setup/erc20/InitializeERC20StakingManager.tsx
index 19de8cdd423..495f26b8ead 100644
--- a/components/toolbox/console/permissionless-l1s/setup/erc20/InitializeERC20StakingManager.tsx
+++ b/components/toolbox/console/permissionless-l1s/setup/erc20/InitializeERC20StakingManager.tsx
@@ -17,6 +17,8 @@ import { Callout } from "fumadocs-ui/components/callout";
import ERC20TokenStakingManager from "@/contracts/icm-contracts/compiled/ERC20TokenStakingManager.json";
import { parseEther } from "viem";
import versions from '@/scripts/versions.json';
+import { cb58ToHex } from '@/components/toolbox/console/utilities/format-converter/FormatConverter';
+import useConsoleNotifications from '@/hooks/useConsoleNotifications';
const ICM_COMMIT = versions["ava-labs/icm-contracts"];
const INITIALIZE_FUNCTION_SOURCE_URL = `https://github.com/ava-labs/icm-contracts/blob/main/contracts/validator-manager/ERC20TokenStakingManager.sol#L53`;
@@ -46,6 +48,7 @@ export default function InitializeERC20StakingManager() {
const { coreWalletClient, publicClient } = useWalletStore();
const viemChain = useViemChainStore();
const { erc20StakingManagerAddress: storedStakingManagerAddress, rewardCalculatorAddress: storedRewardCalculatorAddress } = useToolboxStore();
+ const { notify } = useConsoleNotifications();
// Get validator manager details from subnet ID
const {
@@ -118,11 +121,26 @@ export default function InitializeERC20StakingManager() {
setIsInitializing(true);
try {
+ if (!coreWalletClient) throw new Error("Wallet not connected");
if (!validatorManagerAddress) throw new Error("Validator Manager address required");
if (!rewardCalculatorAddress) throw new Error("Reward Calculator address required");
if (!stakingTokenAddress) throw new Error("Staking Token address required");
if (!blockchainId) throw new Error("Blockchain ID not found. Please select a valid subnet.");
+ // Convert blockchain ID from CB58 to hex
+ let hexBlockchainId: string;
+ try {
+ hexBlockchainId = cb58ToHex(blockchainId);
+ // Ensure it's 32 bytes (64 hex chars)
+ if (hexBlockchainId.length < 64) {
+ // Pad with zeros on the left to make it 32 bytes
+ hexBlockchainId = hexBlockchainId.padStart(64, '0');
+ }
+ hexBlockchainId = `0x${hexBlockchainId}` as `0x${string}`;
+ } catch (error) {
+ throw new Error(`Failed to convert blockchain ID to hex: ${error instanceof Error ? error.message : 'Unknown error'}`);
+ }
+
// Create settings object
const settings = {
manager: validatorManagerAddress as `0x${string}`,
@@ -133,7 +151,7 @@ export default function InitializeERC20StakingManager() {
maximumStakeMultiplier: parseInt(maximumStakeMultiplier),
weightToValueFactor: parseEther(weightToValueFactor),
rewardCalculator: rewardCalculatorAddress as `0x${string}`,
- uptimeBlockchainID: blockchainId as `0x${string}`
+ uptimeBlockchainID: hexBlockchainId as `0x${string}`
};
// Estimate gas for initialization
@@ -148,7 +166,7 @@ export default function InitializeERC20StakingManager() {
// Add 20% buffer to gas estimate for safety
const gasWithBuffer = gasEstimate + (gasEstimate * 20n / 100n);
- const hash = await coreWalletClient.writeContract({
+ const writePromise = coreWalletClient.writeContract({
address: stakingManagerAddressInput as `0x${string}`,
abi: ERC20TokenStakingManager.abi,
functionName: 'initialize',
@@ -157,6 +175,12 @@ export default function InitializeERC20StakingManager() {
gas: gasWithBuffer,
});
+ notify({
+ type: 'call',
+ name: 'Initialize ERC20 Token Staking Manager'
+ }, writePromise, viemChain ?? undefined);
+
+ const hash = await writePromise;
await publicClient.waitForTransactionReceipt({ hash });
await checkIfInitialized();
} catch (error) {
@@ -243,8 +267,22 @@ export default function InitializeERC20StakingManager() {
Validator Manager Address: {validatorManagerAddress}
- Uptime Blockchain ID: {blockchainId || 'Loading...'}
+ Uptime Blockchain ID (CB58): {blockchainId || 'Loading...'}
+ {blockchainId && (
+
+ Uptime Blockchain ID (Hex):
+ {(() => {
+ try {
+ const hex = cb58ToHex(blockchainId);
+ return `0x${hex.padStart(64, '0')}`;
+ } catch {
+ return 'Invalid CB58';
+ }
+ })()}
+
+
+ )}
)}
diff --git a/components/toolbox/console/permissionless-l1s/setup/native/DeployNativeStakingManager.tsx b/components/toolbox/console/permissionless-l1s/setup/native/DeployNativeStakingManager.tsx
index 1dfbd822d3b..90aae9e84b1 100644
--- a/components/toolbox/console/permissionless-l1s/setup/native/DeployNativeStakingManager.tsx
+++ b/components/toolbox/console/permissionless-l1s/setup/native/DeployNativeStakingManager.tsx
@@ -11,6 +11,7 @@ import { WalletRequirementsConfigKey } from "@/components/toolbox/hooks/useWalle
import NativeTokenStakingManager from "@/contracts/icm-contracts/compiled/NativeTokenStakingManager.json";
import versions from '@/scripts/versions.json';
import { keccak256 } from 'viem';
+import useConsoleNotifications from '@/hooks/useConsoleNotifications';
const ICM_COMMIT = versions["ava-labs/icm-contracts"];
const NATIVE_TOKEN_STAKING_MANAGER_SOURCE_URL = `https://github.com/ava-labs/icm-contracts/blob/main/contracts/validator-manager/NativeTokenStakingManager.sol`;
@@ -30,6 +31,7 @@ export default function DeployNativeStakingManager() {
const { coreWalletClient, publicClient, walletEVMAddress } = useWalletStore();
const viemChain = useViemChainStore();
const { nativeStakingManagerAddress, setNativeStakingManagerAddress, validatorMessagesLibAddress } = useToolboxStore();
+ const { notify } = useConsoleNotifications();
// Throw critical errors during render
if (criticalError) {
@@ -61,6 +63,8 @@ export default function DeployNativeStakingManager() {
setNativeStakingManagerAddress("");
try {
if (!viemChain) throw new Error("Viem chain not found");
+ if (!coreWalletClient) throw new Error("Wallet not connected");
+ if (!walletEVMAddress) throw new Error("Wallet address not available");
// Check for library first
if (!validatorMessagesLibAddress) {
@@ -71,13 +75,20 @@ export default function DeployNativeStakingManager() {
await coreWalletClient.addChain({ chain: viemChain });
await coreWalletClient.switchChain({ id: viemChain!.id });
- const hash = await coreWalletClient.deployContract({
- abi: NativeTokenStakingManager.abi,
+ const deployPromise = coreWalletClient.deployContract({
+ abi: NativeTokenStakingManager.abi as any,
bytecode: getLinkedBytecode(), // Use linked bytecode with library
args: [0], // ICMInitializable.Allowed
chain: viemChain,
+ account: walletEVMAddress as `0x${string}`,
});
+ notify({
+ type: 'deploy',
+ name: 'Native Token Staking Manager'
+ }, deployPromise, viemChain ?? undefined);
+
+ const hash = await deployPromise;
const receipt = await publicClient.waitForTransactionReceipt({ hash });
if (!receipt.contractAddress) {
diff --git a/components/toolbox/console/permissionless-l1s/setup/native/InitializeNativeStakingManager.tsx b/components/toolbox/console/permissionless-l1s/setup/native/InitializeNativeStakingManager.tsx
index e5524068f2e..14af2062e3b 100644
--- a/components/toolbox/console/permissionless-l1s/setup/native/InitializeNativeStakingManager.tsx
+++ b/components/toolbox/console/permissionless-l1s/setup/native/InitializeNativeStakingManager.tsx
@@ -16,6 +16,8 @@ import { useValidatorManagerDetails } from '@/components/toolbox/hooks/useValida
import NativeTokenStakingManager from "@/contracts/icm-contracts/compiled/NativeTokenStakingManager.json";
import { parseEther } from "viem";
import versions from '@/scripts/versions.json';
+import { cb58ToHex } from '@/components/toolbox/console/utilities/format-converter/FormatConverter';
+import useConsoleNotifications from '@/hooks/useConsoleNotifications';
const ICM_COMMIT = versions["ava-labs/icm-contracts"];
const INITIALIZE_FUNCTION_SOURCE_URL = `https://github.com/ava-labs/icm-contracts/blob/main/contracts/validator-manager/NativeTokenStakingManager.sol#L43`;
@@ -44,6 +46,7 @@ export default function InitializeNativeStakingManager() {
const { coreWalletClient, publicClient } = useWalletStore();
const viemChain = useViemChainStore();
const { nativeStakingManagerAddress: storedStakingManagerAddress, rewardCalculatorAddress: storedRewardCalculatorAddress } = useToolboxStore();
+ const { notify } = useConsoleNotifications();
// Get validator manager details from subnet ID
const {
@@ -111,10 +114,25 @@ export default function InitializeNativeStakingManager() {
setIsInitializing(true);
try {
+ if (!coreWalletClient) throw new Error("Wallet not connected");
if (!validatorManagerAddress) throw new Error("Validator Manager address required");
if (!rewardCalculatorAddress) throw new Error("Reward Calculator address required");
if (!blockchainId) throw new Error("Blockchain ID not found. Please select a valid subnet.");
+ // Convert blockchain ID from CB58 to hex
+ let hexBlockchainId: string;
+ try {
+ hexBlockchainId = cb58ToHex(blockchainId);
+ // Ensure it's 32 bytes (64 hex chars)
+ if (hexBlockchainId.length < 64) {
+ // Pad with zeros on the left to make it 32 bytes
+ hexBlockchainId = hexBlockchainId.padStart(64, '0');
+ }
+ hexBlockchainId = `0x${hexBlockchainId}` as `0x${string}`;
+ } catch (error) {
+ throw new Error(`Failed to convert blockchain ID to hex: ${error instanceof Error ? error.message : 'Unknown error'}`);
+ }
+
// Create settings object
const settings = {
manager: validatorManagerAddress as `0x${string}`,
@@ -125,7 +143,7 @@ export default function InitializeNativeStakingManager() {
maximumStakeMultiplier: parseInt(maximumStakeMultiplier),
weightToValueFactor: parseEther(weightToValueFactor),
rewardCalculator: rewardCalculatorAddress as `0x${string}`,
- uptimeBlockchainID: blockchainId as `0x${string}`
+ uptimeBlockchainID: hexBlockchainId as `0x${string}`
};
// Estimate gas for initialization
@@ -140,7 +158,7 @@ export default function InitializeNativeStakingManager() {
// Add 20% buffer to gas estimate for safety
const gasWithBuffer = gasEstimate + (gasEstimate * 20n / 100n);
- const hash = await coreWalletClient.writeContract({
+ const writePromise = coreWalletClient.writeContract({
address: stakingManagerAddressInput as `0x${string}`,
abi: NativeTokenStakingManager.abi,
functionName: 'initialize',
@@ -149,6 +167,12 @@ export default function InitializeNativeStakingManager() {
gas: gasWithBuffer,
});
+ notify({
+ type: 'call',
+ name: 'Initialize Native Token Staking Manager'
+ }, writePromise, viemChain ?? undefined);
+
+ const hash = await writePromise;
await publicClient.waitForTransactionReceipt({ hash });
await checkIfInitialized();
} catch (error) {
@@ -227,8 +251,22 @@ export default function InitializeNativeStakingManager() {
Validator Manager Address: {validatorManagerAddress}
- Uptime Blockchain ID: {blockchainId || 'Loading...'}
+ Uptime Blockchain ID (CB58): {blockchainId || 'Loading...'}
+ {blockchainId && (
+
+ Uptime Blockchain ID (Hex):
+ {(() => {
+ try {
+ const hex = cb58ToHex(blockchainId);
+ return `0x${hex.padStart(64, '0')}`;
+ } catch {
+ return 'Invalid CB58';
+ }
+ })()}
+
+
+ )}
)}
From 5931a235802e6700a09f2e91a3c8a57cad13e7de Mon Sep 17 00:00:00 2001
From: Owen
Date: Thu, 25 Sep 2025 16:00:26 -0400
Subject: [PATCH 04/12] fix history page, make enable native minter not
optional
---
app/console/history/page.tsx | 18 ++++++++++++++----
.../native-staking-manager-setup/steps.ts | 2 +-
2 files changed, 15 insertions(+), 5 deletions(-)
diff --git a/app/console/history/page.tsx b/app/console/history/page.tsx
index 504eb7bc877..564ca627f88 100644
--- a/app/console/history/page.tsx
+++ b/app/console/history/page.tsx
@@ -100,12 +100,22 @@ export default function ConsoleHistoryPage() {
type: 'address'
});
}
- if (toolboxStore.stakingManagerAddress && toolboxStore.stakingManagerAddress !== '') {
+ if (toolboxStore.nativeStakingManagerAddress && toolboxStore.nativeStakingManagerAddress !== '') {
items.push({
- id: 'tb-staking-mgr',
- title: 'Staking Manager',
+ id: 'tb-native-staking-mgr',
+ title: 'Native Token Staking Manager',
description: 'Deployed Contract',
- address: toolboxStore.stakingManagerAddress,
+ address: toolboxStore.nativeStakingManagerAddress,
+ chainId,
+ type: 'address'
+ });
+ }
+ if (toolboxStore.erc20StakingManagerAddress && toolboxStore.erc20StakingManagerAddress !== '') {
+ items.push({
+ id: 'tb-erc20-staking-mgr',
+ title: 'ERC20 Token Staking Manager',
+ description: 'Deployed Contract',
+ address: toolboxStore.erc20StakingManagerAddress,
chainId,
type: 'address'
});
diff --git a/app/console/permissionless-l1s/native-staking-manager-setup/steps.ts b/app/console/permissionless-l1s/native-staking-manager-setup/steps.ts
index 4ea89b2aa9e..656240fc699 100644
--- a/app/console/permissionless-l1s/native-staking-manager-setup/steps.ts
+++ b/app/console/permissionless-l1s/native-staking-manager-setup/steps.ts
@@ -22,7 +22,7 @@ export const steps: StepDefinition[] = [
title: "Initialize Staking Manager",
component: InitializeNativeTokenStakingManager,
},
- { type: "single", key: "enable-staking-minting", title: "Enable StakingManager in Native Minter", component: EnableStakingManagerMinting, optional: true },
+ { type: "single", key: "enable-staking-minting", title: "Enable StakingManager in Native Minter", component: EnableStakingManagerMinting },
{ type: "single", key: "transfer-ownership", title: "Transfer Ownership", component: TransferOwnership },
{ type: "single", key: "read-contract", title: "Read Contract", component: ReadContract },
];
From 684996fe8cbc728972759443772e9441e59be8fa Mon Sep 17 00:00:00 2001
From: Owen
Date: Tue, 21 Oct 2025 22:39:19 -0400
Subject: [PATCH 05/12] update components to align with master
---
.../setup/DeployExampleRewardCalculator.tsx | 113 ++---
.../setup/erc20/DeployERC20StakingManager.tsx | 27 +-
.../erc20/InitializeERC20StakingManager.tsx | 425 +++++++++---------
.../native/DeployNativeStakingManager.tsx | 129 +++---
.../native/EnableStakingManagerMinting.tsx | 99 ++--
.../native/InitializeNativeStakingManager.tsx | 387 ++++++++--------
6 files changed, 600 insertions(+), 580 deletions(-)
diff --git a/components/toolbox/console/permissionless-l1s/setup/DeployExampleRewardCalculator.tsx b/components/toolbox/console/permissionless-l1s/setup/DeployExampleRewardCalculator.tsx
index b234e8cee55..451b3bc29d1 100644
--- a/components/toolbox/console/permissionless-l1s/setup/DeployExampleRewardCalculator.tsx
+++ b/components/toolbox/console/permissionless-l1s/setup/DeployExampleRewardCalculator.tsx
@@ -4,23 +4,32 @@ import { useState } from "react";
import { useWalletStore } from "@/components/toolbox/stores/walletStore";
import { useToolboxStore, useViemChainStore } from "@/components/toolbox/stores/toolboxStore";
import { Button } from "@/components/toolbox/components/Button";
-import { Container } from "@/components/toolbox/components/Container";
import { Success } from "@/components/toolbox/components/Success";
import { Input } from "@/components/toolbox/components/Input";
-import { CheckWalletRequirements } from "@/components/toolbox/components/CheckWalletRequirements";
import { WalletRequirementsConfigKey } from "@/components/toolbox/hooks/useWalletRequirements";
import ExampleRewardCalculator from "@/contracts/icm-contracts/compiled/ExampleRewardCalculator.json";
import versions from '@/scripts/versions.json';
import useConsoleNotifications from '@/hooks/useConsoleNotifications';
+import { ConsoleToolMetadata, withConsoleToolMetadata } from '../../../components/WithConsoleToolMetadata';
+import { generateConsoleToolGitHubUrl } from "@/components/toolbox/utils/github-url";
const ICM_COMMIT = versions["ava-labs/icm-contracts"];
const EXAMPLE_REWARD_CALCULATOR_SOURCE_URL = `https://github.com/ava-labs/icm-contracts/blob/${ICM_COMMIT}/contracts/validator-manager/ExampleRewardCalculator.sol`;
-export default function DeployExampleRewardCalculator() {
+const metadata: ConsoleToolMetadata = {
+ title: "Deploy Example Reward Calculator",
+ description: "Deploy an Example Reward Calculator contract for calculating staking rewards.",
+ toolRequirements: [
+ WalletRequirementsConfigKey.EVMChainBalance,
+ ],
+ githubUrl: generateConsoleToolGitHubUrl(import.meta.url)
+};
+
+function DeployExampleRewardCalculator() {
const [criticalError, setCriticalError] = useState(null);
const [isDeploying, setIsDeploying] = useState(false);
const [rewardBasisPoints, setRewardBasisPoints] = useState("500"); // Default 5% APR (500 basis points)
-
+
const { coreWalletClient, publicClient, walletEVMAddress } = useWalletStore();
const viemChain = useViemChainStore();
const { rewardCalculatorAddress, setRewardCalculatorAddress } = useToolboxStore();
@@ -38,10 +47,10 @@ export default function DeployExampleRewardCalculator() {
if (!coreWalletClient) throw new Error("Wallet not connected");
if (!walletEVMAddress) throw new Error("Wallet address not available");
if (!viemChain) throw new Error("Chain not selected");
-
+
await coreWalletClient.addChain({ chain: viemChain });
await coreWalletClient.switchChain({ id: viemChain!.id });
-
+
// Let viem handle gas estimation automatically
// ExampleRewardCalculator is a simple contract, so auto-estimation should work
const deployPromise = coreWalletClient.deployContract({
@@ -73,55 +82,49 @@ export default function DeployExampleRewardCalculator() {
}
return (
-
-
+
+ This will deploy the ExampleRewardCalculator contract to the EVM network {viemChain?.id}.
+ The Example Reward Calculator implements a linear, non-compounding reward calculation that rewards a set percentage of tokens per year.
+
+
+ Contract source: ExampleRewardCalculator.sol @ {ICM_COMMIT.slice(0, 7)}
+
+
+
+
+
+
+
-
-
- This will deploy the ExampleRewardCalculator contract to the EVM network {viemChain?.id}.
- The Example Reward Calculator implements a linear, non-compounding reward calculation that rewards a set percentage of tokens per year.
-
-
- Contract source: ExampleRewardCalculator.sol @ {ICM_COMMIT.slice(0, 7)}
-
-
-
-
-
-
-
- Deploy Example Reward Calculator
-
-
-
Deployment Status: {rewardCalculatorAddress || "Not deployed"}
-
- {rewardCalculatorAddress && (
-
- )}
-
-
-
+ Deploy Example Reward Calculator
+
+
+ Deployment Status: {rewardCalculatorAddress || "Not deployed"}
+
+ {rewardCalculatorAddress && (
+
+ )}
+
);
}
+
+export default withConsoleToolMetadata(DeployExampleRewardCalculator, metadata);
+
diff --git a/components/toolbox/console/permissionless-l1s/setup/erc20/DeployERC20StakingManager.tsx b/components/toolbox/console/permissionless-l1s/setup/erc20/DeployERC20StakingManager.tsx
index 7c98dd6fc51..d1765905e38 100644
--- a/components/toolbox/console/permissionless-l1s/setup/erc20/DeployERC20StakingManager.tsx
+++ b/components/toolbox/console/permissionless-l1s/setup/erc20/DeployERC20StakingManager.tsx
@@ -4,9 +4,9 @@ import { useState } from "react";
import { useWalletStore } from "@/components/toolbox/stores/walletStore";
import { useToolboxStore, useViemChainStore } from "@/components/toolbox/stores/toolboxStore";
import { Button } from "@/components/toolbox/components/Button";
-import { Container } from "@/components/toolbox/components/Container";
import { Success } from "@/components/toolbox/components/Success";
-import { CheckWalletRequirements } from "@/components/toolbox/components/CheckWalletRequirements";
+import { ConsoleToolMetadata, withConsoleToolMetadata } from '../../../../components/WithConsoleToolMetadata';
+import { generateConsoleToolGitHubUrl } from "@/components/toolbox/utils/github-url";
import { WalletRequirementsConfigKey } from "@/components/toolbox/hooks/useWalletRequirements";
import ERC20TokenStakingManager from "@/contracts/icm-contracts/compiled/ERC20TokenStakingManager.json";
import versions from '@/scripts/versions.json';
@@ -24,7 +24,16 @@ function calculateLibraryHash(libraryPath: string) {
return hash.slice(0, 34);
}
-export default function DeployERC20StakingManager() {
+const metadata: ConsoleToolMetadata = {
+ title: "Deploy ERC20 Token Staking Manager",
+ description: "Deploy the ERC20 Token Staking Manager contract to the EVM network.",
+ toolRequirements: [
+ WalletRequirementsConfigKey.EVMChainBalance,
+ ],
+ githubUrl: generateConsoleToolGitHubUrl(import.meta.url)
+};
+
+function DeployERC20StakingManager() {
const [criticalError, setCriticalError] = useState(null);
const [isDeploying, setIsDeploying] = useState(false);
@@ -104,13 +113,7 @@ export default function DeployERC20StakingManager() {
}
return (
-
-
+
This will deploy the ERC20TokenStakingManager contract to the EVM network {viemChain?.id}.
@@ -160,7 +163,7 @@ export default function DeployERC20StakingManager() {
/>
)}
-
-
);
}
+
+export default withConsoleToolMetadata(DeployERC20StakingManager, metadata);
\ No newline at end of file
diff --git a/components/toolbox/console/permissionless-l1s/setup/erc20/InitializeERC20StakingManager.tsx b/components/toolbox/console/permissionless-l1s/setup/erc20/InitializeERC20StakingManager.tsx
index 495f26b8ead..4c41f7fd335 100644
--- a/components/toolbox/console/permissionless-l1s/setup/erc20/InitializeERC20StakingManager.tsx
+++ b/components/toolbox/console/permissionless-l1s/setup/erc20/InitializeERC20StakingManager.tsx
@@ -4,10 +4,10 @@ import { useState, useEffect } from "react";
import { useWalletStore } from "@/components/toolbox/stores/walletStore";
import { useToolboxStore, useViemChainStore } from "@/components/toolbox/stores/toolboxStore";
import { Button } from "@/components/toolbox/components/Button";
-import { Container } from "@/components/toolbox/components/Container";
import { Input } from "@/components/toolbox/components/Input";
import { EVMAddressInput } from "@/components/toolbox/components/EVMAddressInput";
-import { CheckWalletRequirements } from "@/components/toolbox/components/CheckWalletRequirements";
+import { ConsoleToolMetadata, withConsoleToolMetadata } from '../../../../components/WithConsoleToolMetadata';
+import { generateConsoleToolGitHubUrl } from "@/components/toolbox/utils/github-url";
import { WalletRequirementsConfigKey } from "@/components/toolbox/hooks/useWalletRequirements";
import { ResultField } from "@/components/toolbox/components/ResultField";
import { Step, Steps } from "fumadocs-ui/components/steps";
@@ -23,7 +23,16 @@ import useConsoleNotifications from '@/hooks/useConsoleNotifications';
const ICM_COMMIT = versions["ava-labs/icm-contracts"];
const INITIALIZE_FUNCTION_SOURCE_URL = `https://github.com/ava-labs/icm-contracts/blob/main/contracts/validator-manager/ERC20TokenStakingManager.sol#L53`;
-export default function InitializeERC20StakingManager() {
+const metadata: ConsoleToolMetadata = {
+ title: "Initialize ERC20 Token Staking Manager",
+ description: "Initialize the ERC20 Token Staking Manager contract with the required configuration.",
+ toolRequirements: [
+ WalletRequirementsConfigKey.EVMChainBalance,
+ ],
+ githubUrl: generateConsoleToolGitHubUrl(import.meta.url)
+};
+
+function InitializeERC20StakingManager() {
const [criticalError, setCriticalError] = useState(null);
const [stakingManagerAddressInput, setStakingManagerAddressInput] = useState("");
const [isChecking, setIsChecking] = useState(false);
@@ -34,7 +43,7 @@ export default function InitializeERC20StakingManager() {
subnetId: "",
subnet: null
});
-
+
// Initialization parameters
const [minimumStakeAmount, setMinimumStakeAmount] = useState("1");
const [maximumStakeAmount, setMaximumStakeAmount] = useState("1000000");
@@ -44,19 +53,19 @@ export default function InitializeERC20StakingManager() {
const [weightToValueFactor, setWeightToValueFactor] = useState("1");
const [rewardCalculatorAddress, setRewardCalculatorAddress] = useState("");
const [stakingTokenAddress, setStakingTokenAddress] = useState("");
-
- const { coreWalletClient, publicClient } = useWalletStore();
+
+ const { coreWalletClient, publicClient, walletEVMAddress } = useWalletStore();
const viemChain = useViemChainStore();
const { erc20StakingManagerAddress: storedStakingManagerAddress, rewardCalculatorAddress: storedRewardCalculatorAddress } = useToolboxStore();
const { notify } = useConsoleNotifications();
-
+
// Get validator manager details from subnet ID
const {
validatorManagerAddress,
error: validatorManagerError,
isLoading: isLoadingVMCDetails,
} = useValidatorManagerDetails({ subnetId: subnetSelection.subnetId });
-
+
// Extract blockchain ID from subnet data
const blockchainId = subnetSelection.subnet?.blockchains?.[0]?.blockchainId || null;
@@ -80,7 +89,7 @@ export default function InitializeERC20StakingManager() {
async function checkIfInitialized() {
if (!stakingManagerAddressInput) return;
-
+
setIsChecking(true);
try {
// Try to check initialization by reading a setting that would be 0 if not initialized
@@ -89,10 +98,10 @@ export default function InitializeERC20StakingManager() {
abi: ERC20TokenStakingManager.abi,
functionName: 'minimumStakeAmount',
});
-
+
const initialized = BigInt(data as string) > 0n;
setIsInitialized(initialized);
-
+
if (initialized) {
// If initialized, get more details
const [settings, token] = await Promise.all([
@@ -118,7 +127,7 @@ export default function InitializeERC20StakingManager() {
async function handleInitialize() {
if (!stakingManagerAddressInput) return;
-
+
setIsInitializing(true);
try {
if (!coreWalletClient) throw new Error("Wallet not connected");
@@ -126,7 +135,7 @@ export default function InitializeERC20StakingManager() {
if (!rewardCalculatorAddress) throw new Error("Reward Calculator address required");
if (!stakingTokenAddress) throw new Error("Staking Token address required");
if (!blockchainId) throw new Error("Blockchain ID not found. Please select a valid subnet.");
-
+
// Convert blockchain ID from CB58 to hex
let hexBlockchainId: string;
try {
@@ -140,7 +149,7 @@ export default function InitializeERC20StakingManager() {
} catch (error) {
throw new Error(`Failed to convert blockchain ID to hex: ${error instanceof Error ? error.message : 'Unknown error'}`);
}
-
+
// Create settings object
const settings = {
manager: validatorManagerAddress as `0x${string}`,
@@ -160,7 +169,7 @@ export default function InitializeERC20StakingManager() {
abi: ERC20TokenStakingManager.abi,
functionName: 'initialize',
args: [settings, stakingTokenAddress as `0x${string}`],
- account: coreWalletClient.account.address,
+ account: walletEVMAddress as `0x${string}`,
});
// Add 20% buffer to gas estimate for safety
@@ -173,6 +182,7 @@ export default function InitializeERC20StakingManager() {
args: [settings, stakingTokenAddress as `0x${string}`],
chain: viemChain,
gas: gasWithBuffer,
+ account: walletEVMAddress as `0x${string}`,
});
notify({
@@ -191,218 +201,213 @@ export default function InitializeERC20StakingManager() {
}
return (
-
-
-
-
- Select L1 Subnet
-
- Choose the L1 subnet where the ERC20 Token Staking Manager will be initialized. The Validator Manager address and blockchain ID will be automatically derived from your selection.
-
-
-
- {subnetSelection.subnet && !subnetSelection.subnet.isL1 && (
-
-
- Note: This subnet has not been converted to an L1 yet. ERC20 Token Staking Manager can only be initialized for L1s.
-
-
- )}
-
+ <>
+
+
+ Select L1 Subnet
+
+ Choose the L1 subnet where the ERC20 Token Staking Manager will be initialized. The Validator Manager address and blockchain ID will be automatically derived from your selection.
+
+
+
+ {subnetSelection.subnet && !subnetSelection.subnet.isL1 && (
+
+
+ Note: This subnet has not been converted to an L1 yet. ERC20 Token Staking Manager can only be initialized for L1s.
+
+
+ )}
+
+ {validatorManagerAddress && (
+
+
+ Validator Manager Address: {validatorManagerAddress}
+
+
+ )}
+
+
+
+ Select ERC20 Token Staking Manager
+
+ Select the ERC20 Token Staking Manager contract you want to initialize.
+
+
+ Initialize function source: initialize() @ {ICM_COMMIT.slice(0, 7)}
+
+
+
+
+
+ Check Status
+
+
+
+
+ Configure Staking Token & Rewards
+
+ Set the ERC20 token that will be used for staking and the Reward Calculator contract address. The Validator Manager address and Uptime Blockchain ID are automatically derived from your subnet selection.
+
+
+
{validatorManagerAddress && (
-
+
Validator Manager Address: {validatorManagerAddress}
+
+ Uptime Blockchain ID (CB58): {blockchainId || 'Loading...'}
+
+ {blockchainId && (
+
+ Uptime Blockchain ID (Hex):
+ {(() => {
+ try {
+ const hex = cb58ToHex(blockchainId);
+ return `0x${hex.padStart(64, '0')}`;
+ } catch {
+ return 'Invalid CB58';
+ }
+ })()}
+
+
+ )}
)}
-
-
-
- Select ERC20 Token Staking Manager
-
- Select the ERC20 Token Staking Manager contract you want to initialize.
-
-
- Initialize function source: initialize() @ {ICM_COMMIT.slice(0, 7)}
-
-
- Check Status
-
-
-
-
- Configure Staking Token & Rewards
-
- Set the ERC20 token that will be used for staking and the Reward Calculator contract address. The Validator Manager address and Uptime Blockchain ID are automatically derived from your subnet selection.
-
-
-
- {validatorManagerAddress && (
-
-
- Validator Manager Address: {validatorManagerAddress}
-
-
- Uptime Blockchain ID (CB58): {blockchainId || 'Loading...'}
-
- {blockchainId && (
-
- Uptime Blockchain ID (Hex):
- {(() => {
- try {
- const hex = cb58ToHex(blockchainId);
- return `0x${hex.padStart(64, '0')}`;
- } catch {
- return 'Invalid CB58';
- }
- })()}
-
-
- )}
-
- )}
-
-
-
-
- Important: Token Requirements
- The ERC20 token must implement the IERC20Mintable interface.
- This allows the staking manager to mint rewards. Care should be taken to enforce that only
+
+ Important: Token Requirements
+ The ERC20 token must implement the IERC20Mintable interface.
+ This allows the staking manager to mint rewards. Care should be taken to enforce that only
authorized users (i.e., the staking manager contract) are able to mint the ERC20 staking token.
-
-
-
-
-
-
-
- Set Staking Parameters
-
- Configure the staking parameters that define how validators and delegators can participate in securing the network.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
- Initialize Contract
-
-
-
-
- {isInitialized === true && (
-
- )}
-
-
+
+
+
+
+
+ Set Staking Parameters
+
+ Configure the staking parameters that define how validators and delegators can participate in securing the network.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Initialize Contract
+
+
+
+
+ {isInitialized === true && (
+
+ )}
+ >
);
}
+export default withConsoleToolMetadata(InitializeERC20StakingManager, metadata);
+
function jsonStringifyWithBigint(value: unknown) {
return JSON.stringify(value, (_, v) =>
typeof v === 'bigint' ? v.toString() : v
, 2);
-}
+}
\ No newline at end of file
diff --git a/components/toolbox/console/permissionless-l1s/setup/native/DeployNativeStakingManager.tsx b/components/toolbox/console/permissionless-l1s/setup/native/DeployNativeStakingManager.tsx
index 90aae9e84b1..9bed1b81875 100644
--- a/components/toolbox/console/permissionless-l1s/setup/native/DeployNativeStakingManager.tsx
+++ b/components/toolbox/console/permissionless-l1s/setup/native/DeployNativeStakingManager.tsx
@@ -4,10 +4,9 @@ import { useState } from "react";
import { useWalletStore } from "@/components/toolbox/stores/walletStore";
import { useToolboxStore, useViemChainStore } from "@/components/toolbox/stores/toolboxStore";
import { Button } from "@/components/toolbox/components/Button";
-import { Container } from "@/components/toolbox/components/Container";
import { Success } from "@/components/toolbox/components/Success";
-import { CheckWalletRequirements } from "@/components/toolbox/components/CheckWalletRequirements";
-import { WalletRequirementsConfigKey } from "@/components/toolbox/hooks/useWalletRequirements";
+import { ConsoleToolMetadata, withConsoleToolMetadata } from '../../../../components/WithConsoleToolMetadata';
+import { generateConsoleToolGitHubUrl } from "@/components/toolbox/utils/github-url"; import { WalletRequirementsConfigKey } from "@/components/toolbox/hooks/useWalletRequirements";
import NativeTokenStakingManager from "@/contracts/icm-contracts/compiled/NativeTokenStakingManager.json";
import versions from '@/scripts/versions.json';
import { keccak256 } from 'viem';
@@ -24,10 +23,19 @@ function calculateLibraryHash(libraryPath: string) {
return hash.slice(0, 34);
}
-export default function DeployNativeStakingManager() {
+const metadata: ConsoleToolMetadata = {
+ title: "Deploy Native Token Staking Manager",
+ description: "Deploy the Native Token Staking Manager contract to the EVM network.",
+ toolRequirements: [
+ WalletRequirementsConfigKey.EVMChainBalance,
+ ],
+ githubUrl: generateConsoleToolGitHubUrl(import.meta.url)
+};
+
+function DeployNativeStakingManager() {
const [criticalError, setCriticalError] = useState
(null);
const [isDeploying, setIsDeploying] = useState(false);
-
+
const { coreWalletClient, publicClient, walletEVMAddress } = useWalletStore();
const viemChain = useViemChainStore();
const { nativeStakingManagerAddress, setNativeStakingManagerAddress, validatorMessagesLibAddress } = useToolboxStore();
@@ -65,12 +73,12 @@ export default function DeployNativeStakingManager() {
if (!viemChain) throw new Error("Viem chain not found");
if (!coreWalletClient) throw new Error("Wallet not connected");
if (!walletEVMAddress) throw new Error("Wallet address not available");
-
+
// Check for library first
if (!validatorMessagesLibAddress) {
throw new Error('ValidatorMessages library must be deployed first. Please go to Validator Manager Setup and deploy the library.');
}
-
+
// Follow exact pattern from ValidatorManager deployment
await coreWalletClient.addChain({ chain: viemChain });
await coreWalletClient.switchChain({ id: viemChain!.id });
@@ -104,64 +112,57 @@ export default function DeployNativeStakingManager() {
}
return (
-
-
-
-
- This will deploy the NativeTokenStakingManager contract to the EVM network {viemChain?.id}.
- The Native Token Staking Manager enables permissionless staking on your L1 using the native token.
+
+
+ This will deploy the NativeTokenStakingManager contract to the EVM network {viemChain?.id}.
+ The Native Token Staking Manager enables permissionless staking on your L1 using the native token.
+
+
+ Contract source: NativeTokenStakingManager.sol @ {ICM_COMMIT.slice(0, 7)}
+
+ {walletEVMAddress && (
+
+ Connected wallet: {walletEVMAddress}
+
+ )}
+
+ {/* Library requirement notice */}
+ {!validatorMessagesLibAddress ? (
+
+
+ Required: ValidatorMessages library must be deployed first.
+ Please go to the Validator Manager Setup section and deploy the ValidatorMessages library.
-
- Contract source: NativeTokenStakingManager.sol @ {ICM_COMMIT.slice(0, 7)}
+
+ ) : (
+
+
+ Ready: ValidatorMessages library found at: {validatorMessagesLibAddress}
- {walletEVMAddress && (
-
- Connected wallet: {walletEVMAddress}
-
- )}
-
- {/* Library requirement notice */}
- {!validatorMessagesLibAddress ? (
-
-
- Required: ValidatorMessages library must be deployed first.
- Please go to the Validator Manager Setup section and deploy the ValidatorMessages library.
-
-
- ) : (
-
-
- Ready: ValidatorMessages library found at: {validatorMessagesLibAddress}
-
-
- )}
-
-
- {!validatorMessagesLibAddress
- ? "Deploy ValidatorMessages Library First"
- : "Deploy Native Token Staking Manager"}
-
-
-
Deployment Status: {nativeStakingManagerAddress || "Not deployed"}
-
- {nativeStakingManagerAddress && (
-
- )}
-
-
+ )}
+
+
+ {!validatorMessagesLibAddress
+ ? "Deploy ValidatorMessages Library First"
+ : "Deploy Native Token Staking Manager"}
+
+
+
Deployment Status: {nativeStakingManagerAddress || "Not deployed"}
+
+ {nativeStakingManagerAddress && (
+
+ )}
+
);
-}
\ No newline at end of file
+}
+
+export default withConsoleToolMetadata(DeployNativeStakingManager, metadata);
\ No newline at end of file
diff --git a/components/toolbox/console/permissionless-l1s/setup/native/EnableStakingManagerMinting.tsx b/components/toolbox/console/permissionless-l1s/setup/native/EnableStakingManagerMinting.tsx
index b2d470e0563..67b24cb35bb 100644
--- a/components/toolbox/console/permissionless-l1s/setup/native/EnableStakingManagerMinting.tsx
+++ b/components/toolbox/console/permissionless-l1s/setup/native/EnableStakingManagerMinting.tsx
@@ -5,14 +5,24 @@ import { useToolboxStore } from "@/components/toolbox/stores/toolboxStore";
import { Container } from "@/components/toolbox/components/Container";
import { AllowlistComponent } from "@/components/toolbox/components/AllowListComponents";
import { CheckPrecompile } from "@/components/toolbox/components/CheckPrecompile";
-import { CheckWalletRequirements } from "@/components/toolbox/components/CheckWalletRequirements";
+import { ConsoleToolMetadata, withConsoleToolMetadata } from '../../../../components/WithConsoleToolMetadata';
+import { generateConsoleToolGitHubUrl } from "@/components/toolbox/utils/github-url";
import { WalletRequirementsConfigKey } from "@/components/toolbox/hooks/useWalletRequirements";
import { Callout } from "fumadocs-ui/components/callout";
// Default Native Minter address
const DEFAULT_NATIVE_MINTER_ADDRESS = "0x0200000000000000000000000000000000000001";
-export default function EnableStakingManagerMinting() {
+const metadata: ConsoleToolMetadata = {
+ title: "Enable Staking Manager Minting",
+ description: "Grant the Native Token Staking Manager permission to mint rewards.",
+ toolRequirements: [
+ WalletRequirementsConfigKey.EVMChainBalance,
+ ],
+ githubUrl: generateConsoleToolGitHubUrl(import.meta.url)
+};
+
+function EnableStakingManagerMinting() {
const { nativeStakingManagerAddress } = useToolboxStore();
const [isNativeStaking, setIsNativeStaking] = useState
(null);
@@ -24,56 +34,49 @@ export default function EnableStakingManagerMinting() {
}, [nativeStakingManagerAddress]);
return (
-
-
-
-
-
- Why is this needed?
- The Native Token Staking Manager needs permission to mint native tokens as rewards for validators and delegators.
- You must add the staking manager address to the Native Minter allowlist.
- {nativeStakingManagerAddress && (
-
- Your Native Token Staking Manager Address: {nativeStakingManagerAddress}
-
- )}
-
+
+
+
+ Why is this needed?
+ The Native Token Staking Manager needs permission to mint native tokens as rewards for validators and delegators.
+ You must add the staking manager address to the Native Minter allowlist.
+ {nativeStakingManagerAddress && (
+
+ Your Native Token Staking Manager Address: {nativeStakingManagerAddress}
+
+ )}
+
-
- Skip this step if using ERC20 Token Staking
- This step is only required for Native Token Staking Manager. If you deployed an ERC20 Token Staking Manager,
- you can skip this step as the ERC20 token should handle its own minting permissions.
-
+
+ Skip this step if using ERC20 Token Staking
+ This step is only required for Native Token Staking Manager. If you deployed an ERC20 Token Staking Manager,
+ you can skip this step as the ERC20 token should handle its own minting permissions.
+
- {!nativeStakingManagerAddress && (
-
- No native staking manager address found. Please deploy and initialize a Native Token Staking Manager first.
-
- )}
+ {!nativeStakingManagerAddress && (
+
+ No native staking manager address found. Please deploy and initialize a Native Token Staking Manager first.
+
+ )}
- {nativeStakingManagerAddress && (
-
-
- Add your Native Token Staking Manager to the allowlist below:
-
-
- )}
+ {nativeStakingManagerAddress && (
+
+
+ Add your Native Token Staking Manager to the allowlist below:
+
-
+ )}
+
-
-
-
+
+
);
}
+
+export default withConsoleToolMetadata(EnableStakingManagerMinting, metadata);
\ No newline at end of file
diff --git a/components/toolbox/console/permissionless-l1s/setup/native/InitializeNativeStakingManager.tsx b/components/toolbox/console/permissionless-l1s/setup/native/InitializeNativeStakingManager.tsx
index 14af2062e3b..17ffe49f9e1 100644
--- a/components/toolbox/console/permissionless-l1s/setup/native/InitializeNativeStakingManager.tsx
+++ b/components/toolbox/console/permissionless-l1s/setup/native/InitializeNativeStakingManager.tsx
@@ -4,10 +4,10 @@ import { useState, useEffect } from "react";
import { useWalletStore } from "@/components/toolbox/stores/walletStore";
import { useToolboxStore, useViemChainStore } from "@/components/toolbox/stores/toolboxStore";
import { Button } from "@/components/toolbox/components/Button";
-import { Container } from "@/components/toolbox/components/Container";
import { Input } from "@/components/toolbox/components/Input";
import { EVMAddressInput } from "@/components/toolbox/components/EVMAddressInput";
-import { CheckWalletRequirements } from "@/components/toolbox/components/CheckWalletRequirements";
+import { ConsoleToolMetadata, withConsoleToolMetadata } from '../../../../components/WithConsoleToolMetadata';
+import { generateConsoleToolGitHubUrl } from "@/components/toolbox/utils/github-url";
import { WalletRequirementsConfigKey } from "@/components/toolbox/hooks/useWalletRequirements";
import { ResultField } from "@/components/toolbox/components/ResultField";
import { Step, Steps } from "fumadocs-ui/components/steps";
@@ -22,7 +22,16 @@ import useConsoleNotifications from '@/hooks/useConsoleNotifications';
const ICM_COMMIT = versions["ava-labs/icm-contracts"];
const INITIALIZE_FUNCTION_SOURCE_URL = `https://github.com/ava-labs/icm-contracts/blob/main/contracts/validator-manager/NativeTokenStakingManager.sol#L43`;
-export default function InitializeNativeStakingManager() {
+const metadata: ConsoleToolMetadata = {
+ title: "Initialize Native Token Staking Manager",
+ description: "Initialize the Native Token Staking Manager contract with the required configuration.",
+ toolRequirements: [
+ WalletRequirementsConfigKey.EVMChainBalance,
+ ],
+ githubUrl: generateConsoleToolGitHubUrl(import.meta.url)
+};
+
+function InitializeNativeStakingManager() {
const [criticalError, setCriticalError] = useState
(null);
const [stakingManagerAddressInput, setStakingManagerAddressInput] = useState("");
const [isChecking, setIsChecking] = useState(false);
@@ -33,7 +42,7 @@ export default function InitializeNativeStakingManager() {
subnetId: "",
subnet: null
});
-
+
// Initialization parameters
const [minimumStakeAmount, setMinimumStakeAmount] = useState("1");
const [maximumStakeAmount, setMaximumStakeAmount] = useState("1000000");
@@ -42,19 +51,19 @@ export default function InitializeNativeStakingManager() {
const [maximumStakeMultiplier, setMaximumStakeMultiplier] = useState("10");
const [weightToValueFactor, setWeightToValueFactor] = useState("1");
const [rewardCalculatorAddress, setRewardCalculatorAddress] = useState("");
-
- const { coreWalletClient, publicClient } = useWalletStore();
+
+ const { coreWalletClient, publicClient, walletEVMAddress } = useWalletStore();
const viemChain = useViemChainStore();
const { nativeStakingManagerAddress: storedStakingManagerAddress, rewardCalculatorAddress: storedRewardCalculatorAddress } = useToolboxStore();
const { notify } = useConsoleNotifications();
-
+
// Get validator manager details from subnet ID
const {
validatorManagerAddress,
error: validatorManagerError,
isLoading: isLoadingVMCDetails,
} = useValidatorManagerDetails({ subnetId: subnetSelection.subnetId });
-
+
// Extract blockchain ID from subnet data
const blockchainId = subnetSelection.subnet?.blockchains?.[0]?.blockchainId || null;
@@ -78,7 +87,7 @@ export default function InitializeNativeStakingManager() {
async function checkIfInitialized() {
if (!stakingManagerAddressInput) return;
-
+
setIsChecking(true);
try {
// Try to check initialization by reading a setting that would be 0 if not initialized
@@ -87,10 +96,10 @@ export default function InitializeNativeStakingManager() {
abi: NativeTokenStakingManager.abi,
functionName: 'minimumStakeAmount',
});
-
+
const initialized = BigInt(data as string) > 0n;
setIsInitialized(initialized);
-
+
if (initialized) {
// If initialized, get more details
const [settings] = await Promise.all([
@@ -111,14 +120,14 @@ export default function InitializeNativeStakingManager() {
async function handleInitialize() {
if (!stakingManagerAddressInput) return;
-
+
setIsInitializing(true);
try {
if (!coreWalletClient) throw new Error("Wallet not connected");
if (!validatorManagerAddress) throw new Error("Validator Manager address required");
if (!rewardCalculatorAddress) throw new Error("Reward Calculator address required");
if (!blockchainId) throw new Error("Blockchain ID not found. Please select a valid subnet.");
-
+
// Convert blockchain ID from CB58 to hex
let hexBlockchainId: string;
try {
@@ -132,7 +141,7 @@ export default function InitializeNativeStakingManager() {
} catch (error) {
throw new Error(`Failed to convert blockchain ID to hex: ${error instanceof Error ? error.message : 'Unknown error'}`);
}
-
+
// Create settings object
const settings = {
manager: validatorManagerAddress as `0x${string}`,
@@ -152,7 +161,7 @@ export default function InitializeNativeStakingManager() {
abi: NativeTokenStakingManager.abi,
functionName: 'initialize',
args: [settings],
- account: coreWalletClient.account.address,
+ account: walletEVMAddress as `0x${string}`,
});
// Add 20% buffer to gas estimate for safety
@@ -165,6 +174,7 @@ export default function InitializeNativeStakingManager() {
args: [settings],
chain: viemChain,
gas: gasWithBuffer,
+ account: walletEVMAddress as `0x${string}`,
});
notify({
@@ -183,195 +193,190 @@ export default function InitializeNativeStakingManager() {
}
return (
-
-
-
-
- Select L1 Subnet
-
- Choose the L1 subnet where the Native Token Staking Manager will be initialized. The Validator Manager address and blockchain ID will be automatically derived from your selection.
-
-
-
- {subnetSelection.subnet && !subnetSelection.subnet.isL1 && (
-
-
- Note: This subnet has not been converted to an L1 yet. Native Token Staking Manager can only be initialized for L1s.
+ <>
+
+
+ Select L1 Subnet
+
+ Choose the L1 subnet where the Native Token Staking Manager will be initialized. The Validator Manager address and blockchain ID will be automatically derived from your selection.
+
+
+
+ {subnetSelection.subnet && !subnetSelection.subnet.isL1 && (
+
+
+ Note: This subnet has not been converted to an L1 yet. Native Token Staking Manager can only be initialized for L1s.
+
+
+ )}
+
+
+
+ Select Native Token Staking Manager
+
+ Select the Native Token Staking Manager contract you want to initialize.
+
+
+ Initialize function source: initialize() @ {ICM_COMMIT.slice(0, 7)}
+
+
+
+
+
+ Check Status
+
+
+
+
+ Configure Reward Calculator
+
+ Set the Reward Calculator contract address that determines how rewards are distributed to validators. The Validator Manager address and Uptime Blockchain ID are automatically derived from your subnet selection.
+
+
+
+ {validatorManagerAddress && (
+
+
+ Validator Manager Address: {validatorManagerAddress}
+
+
+ Uptime Blockchain ID (CB58): {blockchainId || 'Loading...'}
+ {blockchainId && (
+
+ Uptime Blockchain ID (Hex):
+ {(() => {
+ try {
+ const hex = cb58ToHex(blockchainId);
+ return `0x${hex.padStart(64, '0')}`;
+ } catch {
+ return 'Invalid CB58';
+ }
+ })()}
+
+
+ )}
)}
-
-
-
- Select Native Token Staking Manager
-
- Select the Native Token Staking Manager contract you want to initialize.
-
-
- Initialize function source: initialize() @ {ICM_COMMIT.slice(0, 7)}
-
+
+
-
- Check Status
-
-
-
-
- Configure Reward Calculator
-
- Set the Reward Calculator contract address that determines how rewards are distributed to validators. The Validator Manager address and Uptime Blockchain ID are automatically derived from your subnet selection.
-
-
-
- {validatorManagerAddress && (
-
-
- Validator Manager Address: {validatorManagerAddress}
-
-
- Uptime Blockchain ID (CB58): {blockchainId || 'Loading...'}
-
- {blockchainId && (
-
- Uptime Blockchain ID (Hex):
- {(() => {
- try {
- const hex = cb58ToHex(blockchainId);
- return `0x${hex.padStart(64, '0')}`;
- } catch {
- return 'Invalid CB58';
- }
- })()}
-
-
- )}
-
- )}
-
-
-
-
-
-
- Set Staking Parameters
-
- Configure the staking parameters that define how validators and delegators can participate in securing the network.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+ Set Staking Parameters
+
+ Configure the staking parameters that define how validators and delegators can participate in securing the network.
+
-
- Initialize Contract
-
-
-
-
- {isInitialized === true && (
-
- )}
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Initialize Contract
+
+
+
+
+ {isInitialized === true && (
+
+ )}
+ >
);
}
+export default withConsoleToolMetadata(InitializeNativeStakingManager, metadata);
+
function jsonStringifyWithBigint(value: unknown) {
return JSON.stringify(value, (_, v) =>
typeof v === 'bigint' ? v.toString() : v
, 2);
-}
+}
\ No newline at end of file
From cbe8372854a4131c70ead0d15f804616b2067faa Mon Sep 17 00:00:00 2001
From: Owen
Date: Tue, 21 Oct 2025 23:01:33 -0400
Subject: [PATCH 06/12] fix precompile checker
---
.../toolbox/components/CheckPrecompile.tsx | 21 ++++++++++----
components/toolbox/coreViem/index.ts | 9 +++---
.../coreViem/methods/getActiveRulesAt.ts | 29 ++++++++++++-------
3 files changed, 40 insertions(+), 19 deletions(-)
diff --git a/components/toolbox/components/CheckPrecompile.tsx b/components/toolbox/components/CheckPrecompile.tsx
index ea4ebff9394..c4292a33952 100644
--- a/components/toolbox/components/CheckPrecompile.tsx
+++ b/components/toolbox/components/CheckPrecompile.tsx
@@ -1,6 +1,9 @@
import { useState, useEffect } from "react";
import { useWalletStore } from "../stores/walletStore";
+import { useViemChainStore } from "../stores/toolboxStore";
import { Alert } from "./Alert";
+import { getActiveRulesAt } from "../coreViem";
+import { createPublicClient, http } from "viem";
type PrecompileConfigKey =
| "warpConfig"
@@ -33,7 +36,8 @@ export const CheckPrecompile = ({
docsLink,
docsLinkText = "Learn how to activate this precompile"
}: CheckPrecompileProps) => {
- const { coreWalletClient, walletChainId } = useWalletStore();
+ const { walletChainId } = useWalletStore();
+ const viemChain = useViemChainStore();
const [state, setState] = useState({
isActive: false,
isLoading: false,
@@ -41,13 +45,20 @@ export const CheckPrecompile = ({
});
useEffect(() => {
- if (!coreWalletClient) return;
+ if (!viemChain?.rpcUrls?.default?.http?.[0]) return;
const checkPrecompileStatus = async () => {
setState(prev => ({ ...prev, isLoading: true, error: null }));
try {
- const data = await coreWalletClient.getActiveRulesAt();
+ // Create a dedicated publicClient using the chain's RPC URL
+ // This is necessary because Core wallet provider doesn't support eth_getActiveRulesAt
+ const rpcPublicClient = createPublicClient({
+ transport: http(viemChain.rpcUrls.default.http[0]),
+ chain: viemChain as any,
+ });
+
+ const data = await getActiveRulesAt(rpcPublicClient);
const isActive = Boolean(data.precompiles?.[configKey]?.timestamp);
setState({ isLoading: false, isActive, error: null });
} catch (err) {
@@ -61,7 +72,7 @@ export const CheckPrecompile = ({
};
checkPrecompileStatus();
- }, [coreWalletClient, configKey, walletChainId]);
+ }, [viemChain, configKey, walletChainId]);
if (state.isLoading) {
return (
@@ -103,4 +114,4 @@ export const CheckPrecompile = ({
}
return <>{children}>;
-};
+};
\ No newline at end of file
diff --git a/components/toolbox/coreViem/index.ts b/components/toolbox/coreViem/index.ts
index db55b9d215b..5d6349c76a5 100644
--- a/components/toolbox/coreViem/index.ts
+++ b/components/toolbox/coreViem/index.ts
@@ -19,10 +19,13 @@ import { SetL1ValidatorWeightParams } from './methods/setL1ValidatorWeight'
import { increaseL1ValidatorBalance, IncreaseL1ValidatorBalanceParams } from './methods/increaseL1ValidatorBalance'
import { extractL1ValidatorWeightMessage, ExtractL1ValidatorWeightMessageParams, ExtractL1ValidatorWeightMessageResponse } from './methods/extractL1ValidatorWeightMessage'
import { extractRegisterL1ValidatorMessage, ExtractRegisterL1ValidatorMessageParams, ExtractRegisterL1ValidatorMessageResponse } from './methods/extractRegisterL1ValidatorMessage'
-import { getActiveRulesAt, GetActiveRulesAtResponse } from './methods/getActiveRulesAt'
import { ExtractWarpMessageFromTxResponse } from './methods/extractWarpMessageFromPChainTx'
import { ExtractChainInfoResponse } from './methods/extractChainInfo'
+// Re-export custom Avalanche EVM RPC methods that should be called on publicClient
+export { getActiveRulesAt } from './methods/getActiveRulesAt'
+export type { GetActiveRulesAtResponse } from './methods/getActiveRulesAt'
+
// Type for the Avalanche wallet client with custom methods at root level
export type CoreWalletClientType = Omit & {
// Overridden methods at root level
@@ -41,7 +44,6 @@ export type CoreWalletClientType = Omit & {
extractL1ValidatorWeightMessage: (args: ExtractL1ValidatorWeightMessageParams) => Promise;
extractRegisterL1ValidatorMessage: (args: ExtractRegisterL1ValidatorMessageParams) => Promise;
getEthereumChain: () => Promise;
- getActiveRulesAt: () => Promise;
extractChainInfo: (args: ExtractChainInfoParams) => Promise;
getPChainBalance: () => Promise;
};
@@ -94,10 +96,9 @@ export async function createCoreWalletClient(_account: `0x${string}`): Promise extractL1ValidatorWeightMessage(baseClient, args),
extractRegisterL1ValidatorMessage: (args: ExtractRegisterL1ValidatorMessageParams) => extractRegisterL1ValidatorMessage(baseClient, args),
getEthereumChain: () => getEthereumChain(baseClient),
- getActiveRulesAt: () => getActiveRulesAt(baseClient),
extractChainInfo: (args: ExtractChainInfoParams) => extractChainInfo(baseClient, args),
getPChainBalance: () => getPChainBalance(baseClient),
} as CoreWalletClientType;
return clientWithCustomMethods;
-}
+}
\ No newline at end of file
diff --git a/components/toolbox/coreViem/methods/getActiveRulesAt.ts b/components/toolbox/coreViem/methods/getActiveRulesAt.ts
index 94b19335d55..b56296d7ac3 100644
--- a/components/toolbox/coreViem/methods/getActiveRulesAt.ts
+++ b/components/toolbox/coreViem/methods/getActiveRulesAt.ts
@@ -1,22 +1,31 @@
-import type { AvalancheWalletClient } from "@avalanche-sdk/client";
+import type { Client, Transport, Chain, Account } from "viem";
import type { CoreWalletRpcSchema } from "../rpcSchema";
export type GetActiveRulesAtResponse = Extract['ReturnType'];
-export async function getActiveRulesAt(client: AvalancheWalletClient): Promise {
+export async function getActiveRulesAt(
+ client: Client
+): Promise {
try {
- // Try to call eth_getActiveRulesAt directly through the client
- const result = await client.request<
- Extract
- >({
+ const result = await client.transport.request({
method: 'eth_getActiveRulesAt',
params: [],
- });
+ }) as GetActiveRulesAtResponse;
return result;
} catch (error: any) {
- // If the method doesn't exist, return an empty response
- if (error?.message?.includes('method') || error?.message?.includes('Method') || error?.message?.includes('not supported')) {
+ console.error('eth_getActiveRulesAt error:', error);
+
+ const isMethodNotFound =
+ error?.code === -32601 || // JSON-RPC method not found error code
+ (error?.message && (
+ error.message.toLowerCase().includes('method not found') ||
+ error.message.toLowerCase().includes('does not exist') ||
+ error.message.toLowerCase().includes('is not available')
+ ));
+
+ if (isMethodNotFound) {
+ console.warn('eth_getActiveRulesAt is not supported by this RPC endpoint, returning default (inactive) rules');
return {
ethRules: {
IsHomestead: false,
@@ -40,7 +49,7 @@ export async function getActiveRulesAt(client: AvalancheWalletClient): Promise
Date: Tue, 21 Oct 2025 23:39:15 -0400
Subject: [PATCH 07/12] L1 native staking ROUGH ROUGH DRAFT (DRAFT)
---
app/console/permissionless-l1s/stake/page.tsx | 7 +
components/console/console-sidebar.tsx | 5 +-
.../CompleteValidatorRegistration.tsx | 49 +-
.../InitiateNativeStakeRegistration.tsx | 436 ++++++++++++++++++
.../staking/native/Stake.tsx | 344 ++++++++++++++
5 files changed, 833 insertions(+), 8 deletions(-)
create mode 100644 app/console/permissionless-l1s/stake/page.tsx
create mode 100644 components/toolbox/console/permissionless-l1s/staking/native/InitiateNativeStakeRegistration.tsx
create mode 100644 components/toolbox/console/permissionless-l1s/staking/native/Stake.tsx
diff --git a/app/console/permissionless-l1s/stake/page.tsx b/app/console/permissionless-l1s/stake/page.tsx
new file mode 100644
index 00000000000..b5452013bce
--- /dev/null
+++ b/app/console/permissionless-l1s/stake/page.tsx
@@ -0,0 +1,7 @@
+import Stake from "@/components/toolbox/console/permissionless-l1s/staking/native/Stake";
+
+export default function Page() {
+ return (
+
+ );
+}
\ No newline at end of file
diff --git a/components/console/console-sidebar.tsx b/components/console/console-sidebar.tsx
index 76f24174c94..5d1fae00b72 100644
--- a/components/console/console-sidebar.tsx
+++ b/components/console/console-sidebar.tsx
@@ -236,10 +236,9 @@ const data = {
icon: GitMerge,
},
{
- title: "Stake & Unstake",
- url: "/console/permissionless-l1s/manage-validators",
+ title: "Stake",
+ url: "/console/permissionless-l1s/stake",
icon: Hexagon,
- comingSoon: true,
},
],
},
diff --git a/components/toolbox/console/permissioned-l1s/AddValidator/CompleteValidatorRegistration.tsx b/components/toolbox/console/permissioned-l1s/AddValidator/CompleteValidatorRegistration.tsx
index fed1a58edee..97994ea0499 100644
--- a/components/toolbox/console/permissioned-l1s/AddValidator/CompleteValidatorRegistration.tsx
+++ b/components/toolbox/console/permissioned-l1s/AddValidator/CompleteValidatorRegistration.tsx
@@ -9,6 +9,7 @@ import { packWarpIntoAccessList } from '@/components/toolbox/console/permissione
import { hexToBytes, bytesToHex } from 'viem';
import validatorManagerAbi from '@/contracts/icm-contracts/compiled/ValidatorManager.json';
import poaManagerAbi from '@/contracts/icm-contracts/compiled/PoAManager.json';
+import nativeTokenStakingManagerAbi from '@/contracts/icm-contracts/compiled/NativeTokenStakingManager.json';
import { packL1ValidatorRegistration } from '@/components/toolbox/coreViem/utils/convertWarp';
import { getValidationIdHex } from '@/components/toolbox/coreViem/hooks/getValidationID';
import { useAvalancheSDKChainkit } from '@/components/toolbox/stores/useAvalancheSDKChainkit';
@@ -61,8 +62,18 @@ const CompleteValidatorRegistration: React.FC {
@@ -90,7 +101,7 @@ const CompleteValidatorRegistration: React.FC
{isLoadingOwnership ? 'Checking ownership...' : (isProcessing ? 'Processing...' : 'Sign & Complete Validator Registration')}
diff --git a/components/toolbox/console/permissionless-l1s/staking/native/InitiateNativeStakeRegistration.tsx b/components/toolbox/console/permissionless-l1s/staking/native/InitiateNativeStakeRegistration.tsx
new file mode 100644
index 00000000000..c1f47ee32ce
--- /dev/null
+++ b/components/toolbox/console/permissionless-l1s/staking/native/InitiateNativeStakeRegistration.tsx
@@ -0,0 +1,436 @@
+import React, { useState, useEffect } from 'react';
+import { useViemChainStore } from '@/components/toolbox/stores/toolboxStore';
+import { useWalletStore } from '@/components/toolbox/stores/walletStore';
+import { Button } from '@/components/toolbox/components/Button';
+import { Input } from '@/components/toolbox/components/Input';
+import { ConvertToL1Validator } from '@/components/toolbox/components/ValidatorListInput';
+import { validateStakePercentage } from '@/components/toolbox/coreViem/hooks/getTotalStake';
+import nativeTokenStakingManagerAbi from '@/contracts/icm-contracts/compiled/NativeTokenStakingManager.json';
+import { Success } from '@/components/toolbox/components/Success';
+import { parseNodeID } from '@/components/toolbox/coreViem/utils/ids';
+import { fromBytes, parseEther, formatEther } from 'viem';
+import { utils } from '@avalabs/avalanchejs';
+import useConsoleNotifications from '@/hooks/useConsoleNotifications';
+import { Alert } from '@/components/toolbox/components/Alert';
+
+interface InitiateNativeStakeRegistrationProps {
+ subnetId: string;
+ stakingManagerAddress: string;
+ validators: ConvertToL1Validator[];
+ onSuccess: (data: {
+ txHash: `0x${string}`;
+ nodeId: string;
+ validationId: string;
+ weight: string;
+ unsignedWarpMessage: string;
+ validatorBalance: string;
+ blsProofOfPossession: string;
+ }) => void;
+ onError: (message: string) => void;
+ contractTotalWeight: bigint;
+ l1WeightError: string | null;
+}
+
+const InitiateNativeStakeRegistration: React.FC = ({
+ subnetId,
+ stakingManagerAddress,
+ validators,
+ onSuccess,
+ onError,
+ contractTotalWeight,
+}) => {
+ const { coreWalletClient, publicClient, walletEVMAddress } = useWalletStore();
+ const { notify } = useConsoleNotifications();
+ const viemChain = useViemChainStore();
+ const [isProcessing, setIsProcessing] = useState(false);
+ const [error, setErrorState] = useState(null);
+ const [txSuccess, setTxSuccess] = useState(null);
+
+ // Staking-specific fields
+ const [stakeAmountAVAX, setStakeAmountAVAX] = useState('');
+ const [delegationFeeBips, setDelegationFeeBips] = useState('200'); // 2% default
+ const [minStakeDuration, setMinStakeDuration] = useState('0'); // 0 seconds default
+ const [rewardRecipient, setRewardRecipient] = useState('');
+
+ // Staking manager settings
+ const [stakingSettings, setStakingSettings] = useState<{
+ minimumStakeAmount: bigint;
+ maximumStakeAmount: bigint;
+ minimumStakeDuration: bigint;
+ minimumDelegationFeeBips: number;
+ } | null>(null);
+ const [isLoadingSettings, setIsLoadingSettings] = useState(false);
+
+ // Fetch staking manager settings
+ useEffect(() => {
+ const fetchStakingSettings = async () => {
+ if (!publicClient || !stakingManagerAddress) {
+ setStakingSettings(null);
+ return;
+ }
+
+ setIsLoadingSettings(true);
+ try {
+ const settings = await publicClient.readContract({
+ address: stakingManagerAddress as `0x${string}`,
+ abi: nativeTokenStakingManagerAbi.abi,
+ functionName: 'getStakingManagerSettings',
+ }) as any;
+
+ setStakingSettings({
+ minimumStakeAmount: settings.minimumStakeAmount,
+ maximumStakeAmount: settings.maximumStakeAmount,
+ minimumStakeDuration: settings.minimumStakeDuration,
+ minimumDelegationFeeBips: settings.minimumDelegationFeeBips,
+ });
+
+ // Update defaults based on fetched settings (only if current values are below minimum)
+
+ // Set default stake amount to minimum if not set
+ if (!stakeAmountAVAX) {
+ setStakeAmountAVAX(formatEther(settings.minimumStakeAmount));
+ }
+
+ const currentFeeBips = parseInt(delegationFeeBips) || 0;
+ if (settings.minimumDelegationFeeBips > currentFeeBips) {
+ setDelegationFeeBips(settings.minimumDelegationFeeBips.toString());
+ }
+
+ const currentDuration = BigInt(minStakeDuration || '0');
+ if (settings.minimumStakeDuration > currentDuration) {
+ setMinStakeDuration(settings.minimumStakeDuration.toString());
+ }
+ } catch (err) {
+ console.error('Failed to fetch staking settings:', err);
+ setStakingSettings(null);
+ } finally {
+ setIsLoadingSettings(false);
+ }
+ };
+
+ fetchStakingSettings();
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [publicClient, stakingManagerAddress]);
+
+ // Update reward recipient when wallet address changes
+ useEffect(() => {
+ if (walletEVMAddress && !rewardRecipient) {
+ setRewardRecipient(walletEVMAddress);
+ }
+ }, [walletEVMAddress, rewardRecipient]);
+
+ const validateInputs = (): boolean => {
+ if (validators.length === 0) {
+ setErrorState("Please add a validator to continue");
+ return false;
+ }
+
+ // Validate stake amount
+ const stakeNum = parseFloat(stakeAmountAVAX);
+ if (isNaN(stakeNum) || stakeNum <= 0) {
+ setErrorState("Please enter a valid stake amount");
+ return false;
+ }
+
+ const stakeAmount = parseEther(stakeAmountAVAX);
+
+ // Validate stake amount against staking manager settings
+ if (stakingSettings) {
+ if (stakeAmount < stakingSettings.minimumStakeAmount) {
+ setErrorState(`Stake amount (${formatEther(stakeAmount)} AVAX) is below the minimum required stake (${formatEther(stakingSettings.minimumStakeAmount)} AVAX)`);
+ return false;
+ }
+
+ if (stakeAmount > stakingSettings.maximumStakeAmount) {
+ setErrorState(`Stake amount (${formatEther(stakeAmount)} AVAX) exceeds the maximum allowed stake (${formatEther(stakingSettings.maximumStakeAmount)} AVAX)`);
+ return false;
+ }
+ }
+
+ // Validate delegation fee (0-10000 basis points = 0-100%)
+ const feeBips = parseInt(delegationFeeBips);
+ if (isNaN(feeBips) || feeBips < 0 || feeBips > 10000) {
+ setErrorState("Delegation fee must be between 0 and 10000 basis points (0-100%)");
+ return false;
+ }
+
+ // Validate against minimum delegation fee from staking manager
+ if (stakingSettings && feeBips < stakingSettings.minimumDelegationFeeBips) {
+ setErrorState(`Delegation fee (${feeBips} bips) is below the minimum required (${stakingSettings.minimumDelegationFeeBips} bips)`);
+ return false;
+ }
+
+ // Validate min stake duration
+ const duration = parseInt(minStakeDuration);
+ if (isNaN(duration) || duration < 0) {
+ setErrorState("Minimum stake duration must be a positive number");
+ return false;
+ }
+
+ // Validate against minimum stake duration from staking manager
+ if (stakingSettings && BigInt(duration) < stakingSettings.minimumStakeDuration) {
+ setErrorState(`Minimum stake duration (${duration}s) is below the required minimum (${stakingSettings.minimumStakeDuration.toString()}s)`);
+ return false;
+ }
+
+ // Validate reward recipient address
+ if (!rewardRecipient || !rewardRecipient.match(/^0x[a-fA-F0-9]{40}$/)) {
+ setErrorState("Please provide a valid reward recipient address");
+ return false;
+ }
+
+ return true;
+ };
+
+ const handleInitiateStakingValidatorRegistration = async () => {
+ setErrorState(null);
+ setTxSuccess(null);
+
+ if (!coreWalletClient) {
+ setErrorState("Core wallet not found");
+ return;
+ }
+
+ if (!validateInputs()) {
+ return;
+ }
+
+ if (!stakingManagerAddress) {
+ setErrorState("Staking Manager Address is required. Please select a valid L1 subnet.");
+ return;
+ }
+
+ setIsProcessing(true);
+ try {
+ const validator = validators[0];
+ const [account] = await coreWalletClient.requestAddresses();
+
+ // Process P-Chain Addresses
+ const pChainRemainingBalanceOwnerAddressesHex = validator.remainingBalanceOwner.addresses.map(address => {
+ const addressBytes = utils.bech32ToBytes(address);
+ return fromBytes(addressBytes, "hex");
+ });
+
+ const pChainDisableOwnerAddressesHex = validator.deactivationOwner.addresses.map(address => {
+ const addressBytes = utils.bech32ToBytes(address);
+ return fromBytes(addressBytes, "hex");
+ });
+
+ // Build arguments for staking manager transaction
+ const args = [
+ parseNodeID(validator.nodeID),
+ validator.nodePOP.publicKey,
+ {
+ threshold: validator.remainingBalanceOwner.threshold,
+ addresses: pChainRemainingBalanceOwnerAddressesHex,
+ },
+ {
+ threshold: validator.deactivationOwner.threshold,
+ addresses: pChainDisableOwnerAddressesHex,
+ },
+ parseInt(delegationFeeBips), // delegationFeeBips
+ parseInt(minStakeDuration), // minStakeDuration
+ rewardRecipient as `0x${string}` // rewardRecipient
+ ];
+
+ // Calculate stake amount in wei
+ const stakeAmount = parseEther(stakeAmountAVAX);
+
+ let receipt;
+
+ try {
+ const writePromise = coreWalletClient.writeContract({
+ address: stakingManagerAddress as `0x${string}`,
+ abi: nativeTokenStakingManagerAbi.abi,
+ functionName: "initiateValidatorRegistration",
+ args,
+ value: stakeAmount,
+ account,
+ chain: viemChain
+ });
+
+ notify({
+ type: 'call',
+ name: 'Initiate Staking Validator Registration'
+ }, writePromise, viemChain ?? undefined);
+
+ receipt = await publicClient.waitForTransactionReceipt({ hash: await writePromise });
+
+ if (receipt.status === 'reverted') {
+ setErrorState(`Transaction reverted. Hash: ${receipt.transactionHash}`);
+ onError(`Transaction reverted. Hash: ${receipt.transactionHash}`);
+ return;
+ }
+
+ const unsignedWarpMessage = receipt.logs[0].data ?? "";
+ const validationIdHex = receipt.logs[1].topics[1] ?? "";
+
+ setTxSuccess(`Transaction successful! Hash: ${receipt.transactionHash}`);
+ onSuccess({
+ txHash: receipt.transactionHash as `0x${string}`,
+ nodeId: validator.nodeID,
+ validationId: validationIdHex,
+ weight: '0', // Weight is calculated by staking manager, not needed here
+ unsignedWarpMessage: unsignedWarpMessage,
+ validatorBalance: stakeAmountAVAX, // Use the actual stake amount entered
+ blsProofOfPossession: validator.nodePOP.proofOfPossession,
+ });
+
+ } catch (txError: any) {
+ let message = txError instanceof Error ? txError.message : String(txError);
+
+ if (message.includes('User rejected')) {
+ message = 'Transaction was rejected by user';
+ } else if (message.includes('insufficient funds')) {
+ message = 'Insufficient funds for transaction';
+ } else if (message.includes('execution reverted')) {
+ message = `Transaction reverted: ${message}`;
+ } else if (message.includes('nonce')) {
+ message = 'Transaction nonce error. Please try again.';
+ }
+
+ setErrorState(`Transaction failed: ${message}`);
+ onError(`Transaction failed: ${message}`);
+ }
+ } catch (err: any) {
+ let message = err instanceof Error ? err.message : String(err);
+
+ if (message.includes('User rejected')) {
+ message = 'Transaction was rejected by user';
+ } else if (message.includes('insufficient funds')) {
+ message = 'Insufficient funds for transaction';
+ } else if (message.includes('execution reverted')) {
+ message = `Transaction reverted: ${message}`;
+ } else if (message.includes('nonce')) {
+ message = 'Transaction nonce error. Please try again.';
+ }
+
+ setErrorState(`Transaction failed: ${message}`);
+ onError(`Transaction failed: ${message}`);
+ } finally {
+ setIsProcessing(false);
+ }
+ };
+
+ if (!subnetId) {
+ return (
+
+ Please select an L1 subnet first.
+
+ );
+ }
+
+ if (validators.length === 0) {
+ return (
+
+ Please add a validator in the previous step.
+
+ );
+ }
+
+ return (
+
+ {/* Display staking manager requirements */}
+ {stakingSettings && (
+
+
+ Staking Manager Requirements
+
+
+
Minimum Stake: {formatEther(stakingSettings.minimumStakeAmount)} AVAX
+
Maximum Stake: {formatEther(stakingSettings.maximumStakeAmount)} AVAX
+
Minimum Delegation Fee: {stakingSettings.minimumDelegationFeeBips} bips ({(stakingSettings.minimumDelegationFeeBips / 100).toFixed(2)}%)
+
Minimum Stake Duration: {stakingSettings.minimumStakeDuration.toString()} seconds
+
+
+ )}
+
+
+
+
+ {txSuccess ? 'Transaction Completed' : (isProcessing ? 'Processing...' : 'Initiate Staking Validator Registration')}
+
+
+ {error && (
+
{error}
+ )}
+
+ {txSuccess && (
+
+ )}
+
+ );
+};
+
+export default InitiateNativeStakeRegistration;
+
diff --git a/components/toolbox/console/permissionless-l1s/staking/native/Stake.tsx b/components/toolbox/console/permissionless-l1s/staking/native/Stake.tsx
new file mode 100644
index 00000000000..5f19de74022
--- /dev/null
+++ b/components/toolbox/console/permissionless-l1s/staking/native/Stake.tsx
@@ -0,0 +1,344 @@
+"use client"
+import React, { useState, useEffect } from 'react';
+import Link from 'next/link';
+import { Button } from '@/components/toolbox/components/Button';
+import SelectSubnetId from '@/components/toolbox/components/SelectSubnetId';
+import { ValidatorManagerDetails } from '@/components/toolbox/components/ValidatorManagerDetails';
+import { useValidatorManagerDetails } from '@/components/toolbox/hooks/useValidatorManagerDetails';
+import { Step, Steps } from "fumadocs-ui/components/steps";
+import { Success } from '@/components/toolbox/components/Success';
+
+import InitiateNativeStakeRegistration from '@/components/toolbox/console/permissionless-l1s/staking/native/InitiateNativeStakeRegistration';
+import SubmitPChainTxRegisterL1Validator from '@/components/toolbox/console/permissioned-l1s/AddValidator/SubmitPChainTxRegisterL1Validator';
+import CompleteValidatorRegistration from '@/components/toolbox/console/permissioned-l1s/AddValidator/CompleteValidatorRegistration';
+import { ValidatorListInput, ConvertToL1Validator } from '@/components/toolbox/components/ValidatorListInput';
+import { useCreateChainStore } from '@/components/toolbox/stores/createChainStore';
+import { useWalletStore } from '@/components/toolbox/stores/walletStore';
+import { WalletRequirementsConfigKey } from '@/components/toolbox/hooks/useWalletRequirements';
+import { BaseConsoleToolProps, ConsoleToolMetadata, withConsoleToolMetadata } from '../../../../components/WithConsoleToolMetadata';
+import { Alert } from '@/components/toolbox/components/Alert';
+import { generateConsoleToolGitHubUrl } from "@/components/toolbox/utils/github-url";
+
+// Helper functions for BigInt serialization
+const serializeValidators = (validators: ConvertToL1Validator[]) => {
+ return validators.map(validator => ({
+ ...validator,
+ validatorWeight: validator.validatorWeight.toString(),
+ validatorBalance: validator.validatorBalance.toString(),
+ }));
+};
+
+const deserializeValidators = (serializedValidators: any[]): ConvertToL1Validator[] => {
+ return serializedValidators.map(validator => ({
+ ...validator,
+ validatorWeight: BigInt(validator.validatorWeight),
+ validatorBalance: BigInt(validator.validatorBalance),
+ }));
+};
+
+const STORAGE_KEY = 'stakeValidator_validators';
+
+const metadata: ConsoleToolMetadata = {
+ title: "Stake New Validator",
+ description: "Stake a new validator to your L1 by following these steps in order",
+ toolRequirements: [
+ WalletRequirementsConfigKey.EVMChainBalance,
+ WalletRequirementsConfigKey.PChainBalance
+ ],
+ githubUrl: generateConsoleToolGitHubUrl(import.meta.url)
+};
+
+const StakeValidator: React.FC = ({ onSuccess }) => {
+ const [globalError, setGlobalError] = useState(null);
+ const [globalSuccess, setGlobalSuccess] = useState(null);
+ const [isValidatorManagerDetailsExpanded, setIsValidatorManagerDetailsExpanded] = useState(false);
+
+ // State for passing data between components
+ const [pChainTxId, setPChainTxId] = useState('');
+ const [validatorBalance, setValidatorBalance] = useState('');
+ const [blsProofOfPossession, setBlsProofOfPossession] = useState('');
+ const [evmTxHash, setEvmTxHash] = useState('');
+
+ // Form state with local persistence
+ const { walletEVMAddress, pChainAddress, isTestnet } = useWalletStore();
+ const createChainStoreSubnetId = useCreateChainStore()(state => state.subnetId);
+ const [subnetIdL1, setSubnetIdL1] = useState(createChainStoreSubnetId || "");
+ const [resetKey, setResetKey] = useState(0);
+ const [userPChainBalanceNavax, setUserPChainBalanceNavax] = useState(null);
+
+ // Local validators state with localStorage persistence
+ const [validators, setValidatorsState] = useState(() => {
+ if (typeof window !== 'undefined') {
+ try {
+ const saved = localStorage.getItem(STORAGE_KEY);
+ if (saved) {
+ const serialized = JSON.parse(saved);
+ return deserializeValidators(serialized);
+ }
+ } catch (error) {
+ console.error('Error loading validators from localStorage:', error);
+ }
+ }
+ return [];
+ });
+
+ // Wrapper function to save to localStorage
+ const setValidators = (newValidators: ConvertToL1Validator[]) => {
+ setValidatorsState(newValidators);
+ if (typeof window !== 'undefined') {
+ try {
+ localStorage.setItem(STORAGE_KEY, JSON.stringify(serializeValidators(newValidators)));
+ } catch (error) {
+ console.error('Error saving validators to localStorage:', error);
+ }
+ }
+ };
+
+ const {
+ validatorManagerAddress,
+ error: validatorManagerError,
+ isLoading: isLoadingVMCDetails,
+ blockchainId,
+ contractOwner,
+ isOwnerContract,
+ contractTotalWeight,
+ l1WeightError,
+ signingSubnetId,
+ isLoadingOwnership,
+ isLoadingL1Weight,
+ ownershipError,
+ ownerType,
+ isDetectingOwnerType
+ } = useValidatorManagerDetails({ subnetId: subnetIdL1 });
+
+ // Restore intermediate state from persisted validators data when available
+ useEffect(() => {
+ if (validators.length > 0 && !validatorBalance && !blsProofOfPossession) {
+ const validator = validators[0];
+ setValidatorBalance((Number(validator.validatorBalance) / 1e9).toString());
+ setBlsProofOfPossession(validator.nodePOP.proofOfPossession);
+ } else if (validators.length === 0) {
+ // Clear values when all validators are removed
+ setValidatorBalance('');
+ setBlsProofOfPossession('');
+ }
+ }, [validators, validatorBalance, blsProofOfPossession]);
+
+ // Keep validatorBalance in sync with current validators selection
+ useEffect(() => {
+ if (validators.length > 0) {
+ const validator = validators[0];
+ setValidatorBalance((Number(validator.validatorBalance) / 1e9).toString());
+ } else {
+ setValidatorBalance('');
+ }
+ }, [validators]);
+
+ const handleReset = () => {
+ setGlobalError(null);
+ setGlobalSuccess(null);
+ setPChainTxId('');
+ setValidatorBalance('');
+ setBlsProofOfPossession('');
+ setEvmTxHash('');
+ setSubnetIdL1('');
+ setValidators([]);
+ // Clear localStorage
+ if (typeof window !== 'undefined') {
+ localStorage.removeItem(STORAGE_KEY);
+ }
+ setResetKey(prev => prev + 1); // Force re-render of all child components
+ };
+
+ return (
+ <>
+
+ {globalError && (
+
Error: {globalError}
+ )}
+
+
+
+ Ensure L1 Node is Running
+
+ Before staking a validator, you must have an L1 node set up and running. If you haven't done this yet,
+ visit the L1 Node Setup Tool first.
+ {isTestnet && (
+ <>
+ {' '}On testnet, you can also use our free testnet infrastructure.
+ >
+ )}
+
+
+
+
+ Select L1 Subnet
+
+ Choose the L1 subnet where you want to stake the validator.
+
+
+
+ setIsValidatorManagerDetailsExpanded(!isValidatorManagerDetailsExpanded)}
+ />
+
+
+
+
+ Add Validator Details
+
+ Add the validator details including node credentials and stake amount.
+
+
+
+
+ Note: For staking, the "Consensus Weight" field in the validator form is not used.
+ The actual validator weight will be automatically calculated by the staking manager based on your stake amount
+ using the configured weight-to-value factor. You can leave the weight at its default value.
+
+
+
+ 0n ? contractTotalWeight : null}
+ userPChainBalanceNavax={userPChainBalanceNavax}
+ maxValidators={1}
+ />
+
+
+
+ Initiate Staking Validator Registration
+
+ Call the initiateValidatorRegistration function on the Native Token Staking Manager contract with your stake. This transaction will emit a RegisterL1ValidatorMessage warp message.
+
+
+ {ownerType && ownerType !== 'StakingManager' && (
+
+ This L1 is not using a Staking Manager. The validator manager owner is a {ownerType}.
+ This tool is only for L1s with Native Token Staking Managers.
+
+ )}
+
+ {isLoadingOwnership && (
+
+ Detecting staking manager configuration...
+
+ )}
+
+ {contractOwner && ownerType === 'StakingManager' && (
+
+
+ Staking Manager Found: {contractOwner}
+
+
+ Transactions will be sent to the Staking Manager contract (the owner of the Validator Manager).
+
+
+ )}
+
+ {
+ setValidatorBalance(data.validatorBalance);
+ setBlsProofOfPossession(data.blsProofOfPossession);
+ setEvmTxHash(data.txHash);
+ setGlobalError(null);
+ }}
+ onError={(message) => setGlobalError(message)}
+ />
+
+
+
+ Sign RegisterL1ValidatorMessage & Submit RegisterL1ValidatorTx to P-Chain
+
+ Sign the emitted RegisterL1ValidatorMessage and submit a RegisterL1ValidatorTx to P-Chain. This transaction will emit a L1ValidatorRegistrationMessage warp message.
+
+ {
+ setPChainTxId(pChainTxId);
+ setGlobalError(null);
+ }}
+ onError={(message) => setGlobalError(message)}
+ userPChainBalanceNavax={userPChainBalanceNavax}
+ />
+
+
+
+ Sign L1ValidatorRegistrationMessage & Submit completeValidatorRegistration on Staking Manager contract
+
+ Complete the validator registration by signing the P-Chain L1ValidatorRegistrationMessage and calling the completeValidatorRegistration function on the Staking Manager contract.
+
+ {
+ setGlobalSuccess(message);
+ setGlobalError(null);
+ onSuccess?.();
+ }}
+ onError={(message) => setGlobalError(message)}
+ />
+
+
+
+ {globalSuccess && (
+
+ )}
+
+ {(pChainTxId || globalError || globalSuccess) && (
+
+ Reset All Steps
+
+ )}
+
+ >
+ );
+};
+
+export default withConsoleToolMetadata(StakeValidator, metadata);
+
From 60a429ac6406229278f21817f050a3ac9038a5b9 Mon Sep 17 00:00:00 2001
From: Owen
Date: Wed, 22 Oct 2025 10:57:39 -0400
Subject: [PATCH 08/12] cleanup native stake component
---
.../{stake => stake-native-token}/page.tsx | 0
components/console/console-sidebar.tsx | 4 +-
.../toolbox/components/ValidatorListInput.tsx | 3 +
.../ValidatorListInput/ValidatorItem.tsx | 48 +++++++-------
.../ValidatorListInput/ValidatorsList.tsx | 4 +-
.../InitiateNativeStakeRegistration.tsx | 63 +++++++++----------
.../staking/native/Stake.tsx | 31 +--------
7 files changed, 65 insertions(+), 88 deletions(-)
rename app/console/permissionless-l1s/{stake => stake-native-token}/page.tsx (100%)
diff --git a/app/console/permissionless-l1s/stake/page.tsx b/app/console/permissionless-l1s/stake-native-token/page.tsx
similarity index 100%
rename from app/console/permissionless-l1s/stake/page.tsx
rename to app/console/permissionless-l1s/stake-native-token/page.tsx
diff --git a/components/console/console-sidebar.tsx b/components/console/console-sidebar.tsx
index 5d1fae00b72..37b9976e492 100644
--- a/components/console/console-sidebar.tsx
+++ b/components/console/console-sidebar.tsx
@@ -236,8 +236,8 @@ const data = {
icon: GitMerge,
},
{
- title: "Stake",
- url: "/console/permissionless-l1s/stake",
+ title: "Stake Native Token",
+ url: "/console/permissionless-l1s/stake-native-token",
icon: Hexagon,
},
],
diff --git a/components/toolbox/components/ValidatorListInput.tsx b/components/toolbox/components/ValidatorListInput.tsx
index 417b25f49a9..54e08539ca1 100644
--- a/components/toolbox/components/ValidatorListInput.tsx
+++ b/components/toolbox/components/ValidatorListInput.tsx
@@ -29,6 +29,7 @@ interface ValidatorListInputProps {
maxValidators?: number;
selectedSubnetId?: string | null;
isTestnet?: boolean;
+ hideConsensusWeight?: boolean;
}
export function ValidatorListInput({
@@ -42,6 +43,7 @@ export function ValidatorListInput({
maxValidators,
selectedSubnetId = null,
isTestnet = false,
+ hideConsensusWeight = false,
}: ValidatorListInputProps) {
const [error, setError] = useState(null)
@@ -85,6 +87,7 @@ export function ValidatorListInput({
onChange={onChange}
l1TotalInitializedWeight={l1TotalInitializedWeight}
userPChainBalanceNavax={userPChainBalanceNavax}
+ hideConsensusWeight={hideConsensusWeight}
/>
diff --git a/components/toolbox/components/ValidatorListInput/ValidatorItem.tsx b/components/toolbox/components/ValidatorListInput/ValidatorItem.tsx
index 3e8dacb137e..83e40332901 100644
--- a/components/toolbox/components/ValidatorListInput/ValidatorItem.tsx
+++ b/components/toolbox/components/ValidatorListInput/ValidatorItem.tsx
@@ -14,6 +14,7 @@ interface Props {
onUpdate: (index: number, updated: Partial) => void
l1TotalInitializedWeight?: bigint | null
userPChainBalanceNavax?: bigint | null
+ hideConsensusWeight?: boolean
}
export function ValidatorItem({
@@ -25,6 +26,7 @@ export function ValidatorItem({
onUpdate,
l1TotalInitializedWeight = null,
userPChainBalanceNavax = null,
+ hideConsensusWeight = false,
}: Props) {
let insufficientBalanceError: string | null = null
@@ -89,29 +91,31 @@ export function ValidatorItem({
/>
-
-
-
- Consensus Weight
-
-
onUpdate(index, { validatorWeight: BigInt(e.target.value || 0) })}
- className={cn(
- "w-full rounded p-2",
- "bg-zinc-50 dark:bg-zinc-900",
- "border border-zinc-200 dark:border-zinc-700",
- "text-zinc-900 dark:text-zinc-100",
- "shadow-sm focus:ring focus:ring-primary/30 focus:ring-opacity-50",
+
+ {!hideConsensusWeight && (
+
+
+ Consensus Weight
+
+
onUpdate(index, { validatorWeight: BigInt(e.target.value || 0) })}
+ className={cn(
+ "w-full rounded p-2",
+ "bg-zinc-50 dark:bg-zinc-900",
+ "border border-zinc-200 dark:border-zinc-700",
+ "text-zinc-900 dark:text-zinc-100",
+ "shadow-sm focus:ring focus:ring-primary/30 focus:ring-opacity-50",
+ )}
+ />
+ {hasWeightError && (
+
+ Warning: This validator's weight is 20% or more of the current L1 total stake ({ Number(validator.validatorWeight * 10000n / l1TotalInitializedWeight / 100n).toFixed(2) }%). Recommended to be less than 20%.
+
)}
- />
- {hasWeightError && (
-
- Warning: This validator's weight is 20% or more of the current L1 total stake ({ Number(validator.validatorWeight * 10000n / l1TotalInitializedWeight / 100n).toFixed(2) }%). Recommended to be less than 20%.
-
- )}
-
+
+ )}
Validator Balance (P-Chain AVAX)
diff --git a/components/toolbox/components/ValidatorListInput/ValidatorsList.tsx b/components/toolbox/components/ValidatorListInput/ValidatorsList.tsx
index 5723724724e..c63e052214a 100644
--- a/components/toolbox/components/ValidatorListInput/ValidatorsList.tsx
+++ b/components/toolbox/components/ValidatorListInput/ValidatorsList.tsx
@@ -9,9 +9,10 @@ interface Props {
onChange: (validators: ConvertToL1Validator[]) => void
l1TotalInitializedWeight?: bigint | null
userPChainBalanceNavax?: bigint | null
+ hideConsensusWeight?: boolean
}
-export function ValidatorsList({ validators, onChange, l1TotalInitializedWeight = null, userPChainBalanceNavax = null }: Props) {
+export function ValidatorsList({ validators, onChange, l1TotalInitializedWeight = null, userPChainBalanceNavax = null, hideConsensusWeight = false }: Props) {
const [expandedIndex, setExpandedIndex] = useState(null)
const toggleExpand = (index: number) => {
@@ -45,6 +46,7 @@ export function ValidatorsList({ validators, onChange, l1TotalInitializedWeight
onUpdate={updateValidator}
l1TotalInitializedWeight={l1TotalInitializedWeight}
userPChainBalanceNavax={userPChainBalanceNavax}
+ hideConsensusWeight={hideConsensusWeight}
/>
))}
diff --git a/components/toolbox/console/permissionless-l1s/staking/native/InitiateNativeStakeRegistration.tsx b/components/toolbox/console/permissionless-l1s/staking/native/InitiateNativeStakeRegistration.tsx
index c1f47ee32ce..ec2f26720d1 100644
--- a/components/toolbox/console/permissionless-l1s/staking/native/InitiateNativeStakeRegistration.tsx
+++ b/components/toolbox/console/permissionless-l1s/staking/native/InitiateNativeStakeRegistration.tsx
@@ -1,6 +1,7 @@
-import React, { useState, useEffect } from 'react';
+import React, { useState, useEffect, useMemo } from 'react';
import { useViemChainStore } from '@/components/toolbox/stores/toolboxStore';
import { useWalletStore } from '@/components/toolbox/stores/walletStore';
+import { useL1ListStore } from '@/components/toolbox/stores/l1ListStore';
import { Button } from '@/components/toolbox/components/Button';
import { Input } from '@/components/toolbox/components/Input';
import { ConvertToL1Validator } from '@/components/toolbox/components/ValidatorListInput';
@@ -39,15 +40,22 @@ const InitiateNativeStakeRegistration: React.FC
{
- const { coreWalletClient, publicClient, walletEVMAddress } = useWalletStore();
+ const { coreWalletClient, publicClient, walletEVMAddress, walletChainId } = useWalletStore();
const { notify } = useConsoleNotifications();
const viemChain = useViemChainStore();
+ const l1List = useL1ListStore()((state: any) => state.l1List);
+
+ const tokenSymbol = useMemo(() => {
+ const currentL1 = l1List.find((l1: any) => l1.evmChainId === walletChainId);
+ return currentL1?.coinName || 'AVAX';
+ }, [l1List, walletChainId]);
+
const [isProcessing, setIsProcessing] = useState(false);
const [error, setErrorState] = useState(null);
const [txSuccess, setTxSuccess] = useState(null);
// Staking-specific fields
- const [stakeAmountAVAX, setStakeAmountAVAX] = useState('');
+ const [stakeAmount, setStakeAmount] = useState('');
const [delegationFeeBips, setDelegationFeeBips] = useState('200'); // 2% default
const [minStakeDuration, setMinStakeDuration] = useState('0'); // 0 seconds default
const [rewardRecipient, setRewardRecipient] = useState('');
@@ -87,8 +95,8 @@ const InitiateNativeStakeRegistration: React.FC stakingSettings.maximumStakeAmount) {
- setErrorState(`Stake amount (${formatEther(stakeAmount)} AVAX) exceeds the maximum allowed stake (${formatEther(stakingSettings.maximumStakeAmount)} AVAX)`);
+ if (stakeAmountWei > stakingSettings.maximumStakeAmount) {
+ setErrorState(`Stake amount (${formatEther(stakeAmountWei)} ${tokenSymbol}) exceeds the maximum allowed stake (${formatEther(stakingSettings.maximumStakeAmount)} ${tokenSymbol})`);
return false;
}
}
@@ -234,7 +242,7 @@ const InitiateNativeStakeRegistration: React.FC
- {/* Display staking manager requirements */}
- {stakingSettings && (
-
-
- Staking Manager Requirements
-
-
-
Minimum Stake: {formatEther(stakingSettings.minimumStakeAmount)} AVAX
-
Maximum Stake: {formatEther(stakingSettings.maximumStakeAmount)} AVAX
-
Minimum Delegation Fee: {stakingSettings.minimumDelegationFeeBips} bips ({(stakingSettings.minimumDelegationFeeBips / 100).toFixed(2)}%)
-
Minimum Stake Duration: {stakingSettings.minimumStakeDuration.toString()} seconds
-
-
- )}
-
Staking Parameters
@@ -352,14 +345,14 @@ const InitiateNativeStakeRegistration: React.FC
@@ -405,7 +398,7 @@ const InitiateNativeStakeRegistration: React.FC = ({ onSuccess }) => {
Add Validator Details
- Add the validator details including node credentials and stake amount.
+ Add the validator details including node credentials. Your stake amount will be entered in the next step.
-
-
-
- Note: For staking, the "Consensus Weight" field in the validator form is not used.
- The actual validator weight will be automatically calculated by the staking manager based on your stake amount
- using the configured weight-to-value factor. You can leave the weight at its default value.
-
-
= ({ onSuccess }) => {
l1TotalInitializedWeight={!l1WeightError && contractTotalWeight > 0n ? contractTotalWeight : null}
userPChainBalanceNavax={userPChainBalanceNavax}
maxValidators={1}
+ hideConsensusWeight={true}
/>
@@ -238,28 +231,10 @@ const StakeValidator: React.FC = ({ onSuccess }) => {
{ownerType && ownerType !== 'StakingManager' && (
- This L1 is not using a Staking Manager. The validator manager owner is a {ownerType}.
- This tool is only for L1s with Native Token Staking Managers.
-
- )}
-
- {isLoadingOwnership && (
-
- Detecting staking manager configuration...
+ This L1 is not using a Staking Manager. This tool is only for L1s with Native Token Staking Managers.
)}
- {contractOwner && ownerType === 'StakingManager' && (
-
-
- Staking Manager Found: {contractOwner}
-
-
- Transactions will be sent to the Staking Manager contract (the owner of the Validator Manager).
-
-
- )}
-
Date: Wed, 22 Oct 2025 11:06:32 -0400
Subject: [PATCH 09/12] fix initialize check call on NativeStakingManager
---
.../native/InitializeNativeStakingManager.tsx | 36 +++++++++++--------
1 file changed, 21 insertions(+), 15 deletions(-)
diff --git a/components/toolbox/console/permissionless-l1s/setup/native/InitializeNativeStakingManager.tsx b/components/toolbox/console/permissionless-l1s/setup/native/InitializeNativeStakingManager.tsx
index 17ffe49f9e1..b3a024b2106 100644
--- a/components/toolbox/console/permissionless-l1s/setup/native/InitializeNativeStakingManager.tsx
+++ b/components/toolbox/console/permissionless-l1s/setup/native/InitializeNativeStakingManager.tsx
@@ -18,6 +18,7 @@ import { parseEther } from "viem";
import versions from '@/scripts/versions.json';
import { cb58ToHex } from '@/components/toolbox/console/utilities/format-converter/FormatConverter';
import useConsoleNotifications from '@/hooks/useConsoleNotifications';
+import { toast } from 'sonner';
const ICM_COMMIT = versions["ava-labs/icm-contracts"];
const INITIALIZE_FUNCTION_SOURCE_URL = `https://github.com/ava-labs/icm-contracts/blob/main/contracts/validator-manager/NativeTokenStakingManager.sol#L43`;
@@ -86,33 +87,38 @@ function InitializeNativeStakingManager() {
}, [storedRewardCalculatorAddress, rewardCalculatorAddress]);
async function checkIfInitialized() {
- if (!stakingManagerAddressInput) return;
+ if (!stakingManagerAddressInput) {
+ toast.error('Please enter a staking manager address');
+ return;
+ }
+
+ if (!publicClient) {
+ toast.error('Wallet not connected or public client not available');
+ return;
+ }
setIsChecking(true);
try {
- // Try to check initialization by reading a setting that would be 0 if not initialized
- const data = await publicClient.readContract({
+ // Try to check initialization by reading the settings
+ const settings = await publicClient.readContract({
address: stakingManagerAddressInput as `0x${string}`,
abi: NativeTokenStakingManager.abi,
- functionName: 'minimumStakeAmount',
- });
+ functionName: 'getStakingManagerSettings',
+ }) as any;
- const initialized = BigInt(data as string) > 0n;
+ const initialized = BigInt(settings.minimumStakeAmount) > 0n;
setIsInitialized(initialized);
if (initialized) {
- // If initialized, get more details
- const [settings] = await Promise.all([
- publicClient.readContract({
- address: stakingManagerAddressInput as `0x${string}`,
- abi: NativeTokenStakingManager.abi,
- functionName: 'minimumStakeAmount',
- })
- ]);
- setInitEvent({ minimumStakeAmount: settings });
+ setInitEvent({ settings });
+ toast.success('Contract is already initialized');
+ } else {
+ toast.info('Contract is not initialized yet');
}
} catch (error) {
+ console.error('Error checking initialization status:', error);
setIsInitialized(false);
+ toast.error(error instanceof Error ? error.message : 'Failed to check initialization status');
} finally {
setIsChecking(false);
}
From cc083f8a45c4183fd1e2170c108ecc941596a182 Mon Sep 17 00:00:00 2001
From: Owen
Date: Wed, 22 Oct 2025 11:19:54 -0400
Subject: [PATCH 10/12] prefill StakingManager in enable native minter
---
components/toolbox/components/AllowListComponents.tsx | 7 ++++++-
.../setup/native/EnableStakingManagerMinting.tsx | 8 +-------
2 files changed, 7 insertions(+), 8 deletions(-)
diff --git a/components/toolbox/components/AllowListComponents.tsx b/components/toolbox/components/AllowListComponents.tsx
index 96dfae1d963..06baae4ec0c 100644
--- a/components/toolbox/components/AllowListComponents.tsx
+++ b/components/toolbox/components/AllowListComponents.tsx
@@ -15,18 +15,20 @@ function SetEnabledComponent({
precompileType = "precompiled contract",
abi = allowListAbi.abi,
onSuccess,
+ defaultAddress,
}: {
precompileAddress: string;
precompileType?: string;
abi?: any;
onSuccess?: () => void;
+ defaultAddress?: string;
}) {
const { publicClient, walletEVMAddress, walletChainId } =
useWalletStore();
const { coreWalletClient } = useConnectedWallet();
const viemChain = useViemChainStore();
const [isProcessing, setIsProcessing] = useState(false);
- const [enabledAddress, setEnabledAddress] = useState("");
+ const [enabledAddress, setEnabledAddress] = useState(defaultAddress || "");
const [txHash, setTxHash] = useState(null);
const [error, setError] = useState(null);
@@ -523,11 +525,13 @@ export function AllowlistComponent({
precompileType = "precompiled contract",
abi = allowListAbi.abi,
onSuccess,
+ defaultEnabledAddress,
}: {
precompileAddress: string;
precompileType?: string;
abi?: any;
onSuccess?: () => void;
+ defaultEnabledAddress?: string;
}) {
return (
@@ -538,6 +542,7 @@ export function AllowlistComponent({
precompileType={precompileType}
abi={abi}
onSuccess={onSuccess}
+ defaultAddress={defaultEnabledAddress}
/>
-
- Skip this step if using ERC20 Token Staking
- This step is only required for Native Token Staking Manager. If you deployed an ERC20 Token Staking Manager,
- you can skip this step as the ERC20 token should handle its own minting permissions.
-
-
{!nativeStakingManagerAddress && (
No native staking manager address found. Please deploy and initialize a Native Token Staking Manager first.
@@ -74,6 +67,7 @@ function EnableStakingManagerMinting() {
);
From 57a16edf5e7b99b544f283de2d48fefeae05d3d1 Mon Sep 17 00:00:00 2001
From: Owen
Date: Wed, 22 Oct 2025 11:37:35 -0400
Subject: [PATCH 11/12] prefill stakingManager on tranfer ownership, remove old
step flow for setup
---
.../native-staking-manager-setup/steps.ts | 4 +-
.../[step]/client-page.tsx | 15 ------
.../staking-manager-setup/[step]/page.tsx | 8 ---
.../staking-manager-setup/page.tsx | 7 ---
.../staking-manager-setup/steps.ts | 34 ------------
.../multisig-setup/TransferOwnership.tsx | 16 +++++-
.../TransferOwnershipToStakingManager.tsx | 53 +++++++++++++++++++
7 files changed, 69 insertions(+), 68 deletions(-)
delete mode 100644 app/console/permissionless-l1s/staking-manager-setup/[step]/client-page.tsx
delete mode 100644 app/console/permissionless-l1s/staking-manager-setup/[step]/page.tsx
delete mode 100644 app/console/permissionless-l1s/staking-manager-setup/page.tsx
delete mode 100644 app/console/permissionless-l1s/staking-manager-setup/steps.ts
create mode 100644 components/toolbox/console/permissionless-l1s/setup/TransferOwnershipToStakingManager.tsx
diff --git a/app/console/permissionless-l1s/native-staking-manager-setup/steps.ts b/app/console/permissionless-l1s/native-staking-manager-setup/steps.ts
index 656240fc699..b7aa35c8e0f 100644
--- a/app/console/permissionless-l1s/native-staking-manager-setup/steps.ts
+++ b/app/console/permissionless-l1s/native-staking-manager-setup/steps.ts
@@ -5,7 +5,7 @@ import InitializeNativeTokenStakingManager from "@/components/toolbox/console/pe
import DeployERC20StakingManager from "@/components/toolbox/console/permissionless-l1s/setup/erc20/DeployERC20StakingManager";
import InitializeERC20StakingManager from "@/components/toolbox/console/permissionless-l1s/setup/erc20/InitializeERC20StakingManager";
import DeployExampleRewardCalculator from "@/components/toolbox/console/permissionless-l1s/setup/DeployExampleRewardCalculator";
-import TransferOwnership from "@/components/toolbox/console/permissioned-l1s/multisig-setup/TransferOwnership";
+import TransferOwnershipToStakingManager from "@/components/toolbox/console/permissionless-l1s/setup/TransferOwnershipToStakingManager";
import EnableStakingManagerMinting from "@/components/toolbox/console/permissionless-l1s/setup/native/EnableStakingManagerMinting";
export const steps: StepDefinition[] = [
@@ -23,6 +23,6 @@ export const steps: StepDefinition[] = [
component: InitializeNativeTokenStakingManager,
},
{ type: "single", key: "enable-staking-minting", title: "Enable StakingManager in Native Minter", component: EnableStakingManagerMinting },
- { type: "single", key: "transfer-ownership", title: "Transfer Ownership", component: TransferOwnership },
+ { type: "single", key: "transfer-ownership", title: "Transfer Ownership to Staking Manager", component: TransferOwnershipToStakingManager },
{ type: "single", key: "read-contract", title: "Read Contract", component: ReadContract },
];
diff --git a/app/console/permissionless-l1s/staking-manager-setup/[step]/client-page.tsx b/app/console/permissionless-l1s/staking-manager-setup/[step]/client-page.tsx
deleted file mode 100644
index 4dcb8ccec3f..00000000000
--- a/app/console/permissionless-l1s/staking-manager-setup/[step]/client-page.tsx
+++ /dev/null
@@ -1,15 +0,0 @@
-"use client";
-
-import StepFlow from "@/components/console/step-flow";
-import { steps } from "../steps";
-
-export default function StakingManagerSetupClientPage({ currentStepKey }: { currentStepKey: string }) {
- const basePath = "/console/permissionless-l1s/staking-manager-setup";
- return (
-
- );
-}
diff --git a/app/console/permissionless-l1s/staking-manager-setup/[step]/page.tsx b/app/console/permissionless-l1s/staking-manager-setup/[step]/page.tsx
deleted file mode 100644
index fe2a1590cea..00000000000
--- a/app/console/permissionless-l1s/staking-manager-setup/[step]/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-import StakingManagerSetupClientPage from "./client-page";
-
-export default async function Page({ params }: { params: Promise<{ step: string }> }) {
- const { step } = await params;
- return (
-
- );
-}
diff --git a/app/console/permissionless-l1s/staking-manager-setup/page.tsx b/app/console/permissionless-l1s/staking-manager-setup/page.tsx
deleted file mode 100644
index 574f8cd168d..00000000000
--- a/app/console/permissionless-l1s/staking-manager-setup/page.tsx
+++ /dev/null
@@ -1,7 +0,0 @@
-import { redirect } from "next/navigation";
-
-export default function Page() {
- redirect("/console/permissionless-l1s/staking-manager-setup/deploy-native-token-staking-manager");
-}
-
-
diff --git a/app/console/permissionless-l1s/staking-manager-setup/steps.ts b/app/console/permissionless-l1s/staking-manager-setup/steps.ts
deleted file mode 100644
index 4cc3279d57c..00000000000
--- a/app/console/permissionless-l1s/staking-manager-setup/steps.ts
+++ /dev/null
@@ -1,34 +0,0 @@
-import { type StepDefinition } from "@/components/console/step-flow";
-import ReadContract from "@/components/toolbox/console/permissioned-l1s/validator-manager-setup/ReadContract";
-import DeployNativeTokenStakingManager from "@/components/toolbox/console/permissionless-l1s/setup/native/DeployNativeStakingManager";
-import InitializeNativeTokenStakingManager from "@/components/toolbox/console/permissionless-l1s/setup/native/InitializeNativeStakingManager";
-import DeployERC20StakingManager from "@/components/toolbox/console/permissionless-l1s/setup/erc20/DeployERC20StakingManager";
-import InitializeERC20StakingManager from "@/components/toolbox/console/permissionless-l1s/setup/erc20/InitializeERC20StakingManager";
-import DeployExampleRewardCalculator from "@/components/toolbox/console/permissionless-l1s/setup/DeployExampleRewardCalculator";
-import TransferOwnership from "@/components/toolbox/console/permissioned-l1s/multisig-setup/TransferOwnership";
-import EnableStakingManagerMinting from "@/components/toolbox/console/permissionless-l1s/setup/native/EnableStakingManagerMinting";
-
-export const steps: StepDefinition[] = [
- {
- type: "branch",
- key: "deploy-staking-manager",
- title: "Deploy Staking Manager",
- options: [
- { key: "deploy-native-token-staking-manager", label: "Deploy Native Token Staking Manager", component: DeployNativeTokenStakingManager },
- { key: "deploy-erc20-staking-manager", label: "Deploy ERC20 Token Staking Manager", component: DeployERC20StakingManager },
- ],
- },
- { type: "single", key: "deploy-example-reward-calculator", title: "Deploy Example Reward Calculator", component: DeployExampleRewardCalculator },
- {
- type: "branch",
- key: "initialize-staking-manager",
- title: "Initialize Staking Manager",
- options: [
- { key: "initialize-native-staking-manager", label: "Initialize Native Token Staking Manager", component: InitializeNativeTokenStakingManager },
- { key: "initialize-erc20-staking-manager", label: "Initialize ERC20 Token Staking Manager", component: InitializeERC20StakingManager },
- ],
- },
- { type: "single", key: "enable-staking-minting", title: "Enable Staking Manager Minting", component: EnableStakingManagerMinting, optional: true },
- { type: "single", key: "transfer-ownership", title: "Transfer Ownership", component: TransferOwnership },
- { type: "single", key: "read-contract", title: "Read Contract", component: ReadContract },
-];
diff --git a/components/toolbox/console/permissioned-l1s/multisig-setup/TransferOwnership.tsx b/components/toolbox/console/permissioned-l1s/multisig-setup/TransferOwnership.tsx
index 3fbe67a17e0..d4fcb7b803b 100644
--- a/components/toolbox/console/permissioned-l1s/multisig-setup/TransferOwnership.tsx
+++ b/components/toolbox/console/permissioned-l1s/multisig-setup/TransferOwnership.tsx
@@ -28,19 +28,30 @@ const metadata: ConsoleToolMetadata = {
githubUrl: generateConsoleToolGitHubUrl(import.meta.url)
};
-function TransferOwnership({ onSuccess }: BaseConsoleToolProps) {
+export interface TransferOwnershipProps extends BaseConsoleToolProps {
+ defaultNewOwnerAddress?: string;
+}
+
+function TransferOwnership({ onSuccess, defaultNewOwnerAddress }: TransferOwnershipProps) {
const [criticalError, setCriticalError] = useState(null);
const { publicClient, walletEVMAddress } = useWalletStore();
const { coreWalletClient } = useConnectedWallet();
const [isTransferring, setIsTransferring] = useState(false);
const [selectedSubnetId, setSelectedSubnetId] = useState('');
- const [newOwnerAddress, setNewOwnerAddress] = useState('');
+ const [newOwnerAddress, setNewOwnerAddress] = useState(defaultNewOwnerAddress || '');
const [receipt, setReceipt] = useState(null);
const [isDetailsExpanded, setIsDetailsExpanded] = useState(true);
const [isNewOwnerContract, setIsNewOwnerContract] = useState(false);
const [isCheckingNewOwner, setIsCheckingNewOwner] = useState(false);
const viemChain = useViemChainStore();
+ // Update newOwnerAddress when defaultNewOwnerAddress prop changes
+ useEffect(() => {
+ if (defaultNewOwnerAddress && !newOwnerAddress) {
+ setNewOwnerAddress(defaultNewOwnerAddress);
+ }
+ }, [defaultNewOwnerAddress, newOwnerAddress]);
+
// Throw critical errors during render
if (criticalError) {
throw criticalError;
@@ -228,5 +239,6 @@ function TransferOwnership({ onSuccess }: BaseConsoleToolProps) {
);
}
+export { TransferOwnership };
export default withConsoleToolMetadata(TransferOwnership, metadata);
diff --git a/components/toolbox/console/permissionless-l1s/setup/TransferOwnershipToStakingManager.tsx b/components/toolbox/console/permissionless-l1s/setup/TransferOwnershipToStakingManager.tsx
new file mode 100644
index 00000000000..80b5ac0ab28
--- /dev/null
+++ b/components/toolbox/console/permissionless-l1s/setup/TransferOwnershipToStakingManager.tsx
@@ -0,0 +1,53 @@
+"use client";
+
+import { useToolboxStore } from "@/components/toolbox/stores/toolboxStore";
+import { TransferOwnership } from "@/components/toolbox/console/permissioned-l1s/multisig-setup/TransferOwnership";
+import { ConsoleToolMetadata, withConsoleToolMetadata, BaseConsoleToolProps } from '../../../components/WithConsoleToolMetadata';
+import { generateConsoleToolGitHubUrl } from "@/components/toolbox/utils/github-url";
+import { WalletRequirementsConfigKey } from "@/components/toolbox/hooks/useWalletRequirements";
+import { Callout } from "fumadocs-ui/components/callout";
+
+const metadata: ConsoleToolMetadata = {
+ title: "Transfer Ownership to Staking Manager",
+ description: "Transfer the ownership of the Validator Manager to your deployed Staking Manager",
+ toolRequirements: [
+ WalletRequirementsConfigKey.EVMChainBalance,
+ ],
+ githubUrl: generateConsoleToolGitHubUrl(import.meta.url)
+};
+
+function TransferOwnershipToStakingManager({ onSuccess }: BaseConsoleToolProps) {
+ const { nativeStakingManagerAddress, erc20StakingManagerAddress } = useToolboxStore();
+
+ // Prefer the address that's available (native or ERC20)
+ const stakingManagerAddress = nativeStakingManagerAddress || erc20StakingManagerAddress;
+
+ return (
+ <>
+ {stakingManagerAddress && (
+
+ Staking Manager Detected
+ Your Staking Manager address has been automatically filled in below:
+
+ {stakingManagerAddress}
+
+
+ )}
+
+ {!stakingManagerAddress && (
+
+ No Staking Manager Found
+ No staking manager address found. Please deploy and initialize a Staking Manager first, or manually enter the address below.
+
+ )}
+
+
+ >
+ );
+}
+
+export default withConsoleToolMetadata(TransferOwnershipToStakingManager, metadata);
+
From 09c3639e56503f8f8f6ee94644751056990e4942 Mon Sep 17 00:00:00 2001
From: Owen
Date: Wed, 29 Oct 2025 11:43:07 -0400
Subject: [PATCH 12/12] delegate native token
---
.../delegate-native-token/page.tsx | 6 +
components/console/console-sidebar.tsx | 5 +
.../native/CompleteDelegatorRegistration.tsx | 200 ++++++++++
.../delegate/native/Delegate.tsx | 235 ++++++++++++
.../native/InitiateNativeDelegation.tsx | 362 ++++++++++++++++++
.../SubmitPChainTxDelegationWeightChange.tsx | 292 ++++++++++++++
6 files changed, 1100 insertions(+)
create mode 100644 app/console/permissionless-l1s/delegate-native-token/page.tsx
create mode 100644 components/toolbox/console/permissionless-l1s/delegate/native/CompleteDelegatorRegistration.tsx
create mode 100644 components/toolbox/console/permissionless-l1s/delegate/native/Delegate.tsx
create mode 100644 components/toolbox/console/permissionless-l1s/delegate/native/InitiateNativeDelegation.tsx
create mode 100644 components/toolbox/console/permissionless-l1s/delegate/native/SubmitPChainTxDelegationWeightChange.tsx
diff --git a/app/console/permissionless-l1s/delegate-native-token/page.tsx b/app/console/permissionless-l1s/delegate-native-token/page.tsx
new file mode 100644
index 00000000000..2132da4972c
--- /dev/null
+++ b/app/console/permissionless-l1s/delegate-native-token/page.tsx
@@ -0,0 +1,6 @@
+import DelegateToValidator from '@/components/toolbox/console/permissionless-l1s/delegate/native/Delegate';
+
+export default function DelegateNativeTokenPage() {
+ return ;
+}
+
diff --git a/components/console/console-sidebar.tsx b/components/console/console-sidebar.tsx
index 37b9976e492..cc84eecb3fd 100644
--- a/components/console/console-sidebar.tsx
+++ b/components/console/console-sidebar.tsx
@@ -240,6 +240,11 @@ const data = {
url: "/console/permissionless-l1s/stake-native-token",
icon: Hexagon,
},
+ {
+ title: "Delegate Native Token",
+ url: "/console/permissionless-l1s/delegate-native-token",
+ icon: HandCoins,
+ }
],
},
{
diff --git a/components/toolbox/console/permissionless-l1s/delegate/native/CompleteDelegatorRegistration.tsx b/components/toolbox/console/permissionless-l1s/delegate/native/CompleteDelegatorRegistration.tsx
new file mode 100644
index 00000000000..bd8315468a1
--- /dev/null
+++ b/components/toolbox/console/permissionless-l1s/delegate/native/CompleteDelegatorRegistration.tsx
@@ -0,0 +1,200 @@
+import React, { useState, useEffect } from 'react';
+import { useWalletStore } from '@/components/toolbox/stores/walletStore';
+import { useViemChainStore } from '@/components/toolbox/stores/toolboxStore';
+import { Button } from '@/components/toolbox/components/Button';
+import { Input } from '@/components/toolbox/components/Input';
+import { Success } from '@/components/toolbox/components/Success';
+import { Alert } from '@/components/toolbox/components/Alert';
+import { bytesToHex, hexToBytes } from 'viem';
+import nativeTokenStakingManagerAbi from '@/contracts/icm-contracts/compiled/NativeTokenStakingManager.json';
+import { GetRegistrationJustification } from '@/components/toolbox/console/permissioned-l1s/ValidatorManager/justification';
+import { packL1ValidatorWeightMessage } from '@/components/toolbox/coreViem/utils/convertWarp';
+import { packWarpIntoAccessList } from '@/components/toolbox/console/permissioned-l1s/ValidatorManager/packWarp';
+import { useAvalancheSDKChainkit } from '@/components/toolbox/stores/useAvalancheSDKChainkit';
+import useConsoleNotifications from '@/hooks/useConsoleNotifications';
+
+interface CompleteDelegatorRegistrationProps {
+ subnetIdL1: string;
+ delegationID: string;
+ pChainTxId: string;
+ stakingManagerAddress: string;
+ signingSubnetId: string;
+ onSuccess: (message: string) => void;
+ onError: (message: string) => void;
+}
+
+const CompleteDelegatorRegistration: React.FC = ({
+ subnetIdL1,
+ delegationID,
+ pChainTxId,
+ stakingManagerAddress,
+ signingSubnetId,
+ onSuccess,
+ onError,
+}) => {
+ const { coreWalletClient, publicClient, avalancheNetworkID, walletEVMAddress } = useWalletStore();
+ const { aggregateSignature } = useAvalancheSDKChainkit();
+ const { notify } = useConsoleNotifications();
+ const viemChain = useViemChainStore();
+
+ const [isProcessing, setIsProcessing] = useState(false);
+ const [error, setErrorState] = useState(null);
+ const [successMessage, setSuccessMessage] = useState(null);
+ const [transactionHash, setTransactionHash] = useState(null);
+
+ const handleCompleteDelegation = async () => {
+ setErrorState(null);
+ setSuccessMessage(null);
+
+ if (!pChainTxId.trim()) {
+ setErrorState("P-Chain transaction ID is required.");
+ onError("P-Chain transaction ID is required.");
+ return;
+ }
+
+ if (!delegationID || delegationID === '0x0000000000000000000000000000000000000000000000000000000000000000') {
+ setErrorState("Valid delegation ID is required.");
+ onError("Valid delegation ID is required.");
+ return;
+ }
+
+ if (!subnetIdL1) {
+ setErrorState("L1 Subnet ID is required. Please select a subnet first.");
+ onError("L1 Subnet ID is required. Please select a subnet first.");
+ return;
+ }
+
+ if (!stakingManagerAddress) {
+ setErrorState("Staking Manager address is not set. Check L1 Subnet selection.");
+ onError("Staking Manager address is not set. Check L1 Subnet selection.");
+ return;
+ }
+
+ if (!coreWalletClient || !publicClient || !viemChain) {
+ setErrorState("Wallet or chain configuration is not properly initialized.");
+ onError("Wallet or chain configuration is not properly initialized.");
+ return;
+ }
+
+ setIsProcessing(true);
+ try {
+ // Step 1: Extract L1ValidatorWeightMessage from P-Chain transaction
+ const weightMessageData = await coreWalletClient.extractL1ValidatorWeightMessage({
+ txId: pChainTxId
+ });
+
+ // Step 2: Get justification for the validation (using the extracted validation ID)
+ const justification = await GetRegistrationJustification(
+ weightMessageData.validationID,
+ subnetIdL1,
+ publicClient
+ );
+
+ if (!justification) {
+ throw new Error("No justification logs found for this validation ID");
+ }
+
+ // Step 3: Create P-Chain warp signature using the extracted weight message data
+ const warpValidationID = hexToBytes(weightMessageData.validationID as `0x${string}`);
+ const warpNonce = weightMessageData.nonce;
+ const warpWeight = weightMessageData.weight;
+
+ const weightMessage = packL1ValidatorWeightMessage(
+ {
+ validationID: warpValidationID,
+ nonce: warpNonce,
+ weight: warpWeight,
+ },
+ avalancheNetworkID,
+ "11111111111111111111111111111111LpoYY" // always use P-Chain ID
+ );
+
+ const aggregateSignaturePromise = aggregateSignature({
+ message: bytesToHex(weightMessage),
+ justification: bytesToHex(justification),
+ signingSubnetId: signingSubnetId || subnetIdL1,
+ quorumPercentage: 67,
+ });
+ notify({
+ type: 'local',
+ name: 'Aggregate Signatures'
+ }, aggregateSignaturePromise);
+ const signature = await aggregateSignaturePromise;
+
+ // Step 4: Complete the delegator registration on EVM
+ const signedPChainWarpMsgBytes = hexToBytes(`0x${signature.signedMessage}`);
+ const accessList = packWarpIntoAccessList(signedPChainWarpMsgBytes);
+
+ const writePromise = coreWalletClient.writeContract({
+ address: stakingManagerAddress as `0x${string}`,
+ abi: nativeTokenStakingManagerAbi.abi,
+ functionName: "completeDelegatorRegistration",
+ args: [delegationID as `0x${string}`, 0], // delegationID and messageIndex (0)
+ accessList,
+ account: walletEVMAddress as `0x${string}`,
+ chain: viemChain,
+ });
+
+ notify({
+ type: 'call',
+ name: 'Complete Delegator Registration'
+ }, writePromise, viemChain ?? undefined);
+
+ const hash = await writePromise;
+ const finalReceipt = await publicClient.waitForTransactionReceipt({ hash });
+ if (finalReceipt.status !== 'success') {
+ throw new Error(`Transaction failed with status: ${finalReceipt.status}`);
+ }
+
+ setTransactionHash(hash);
+ const successMsg = `Delegator registration completed successfully.`;
+ setSuccessMessage(successMsg);
+ onSuccess(successMsg);
+ } catch (err: any) {
+ const message = err instanceof Error ? err.message : String(err);
+ setErrorState(`Failed to complete delegator registration: ${message}`);
+ onError(`Failed to complete delegator registration: ${message}`);
+ } finally {
+ setIsProcessing(false);
+ }
+ };
+
+ // Don't render if no subnet is selected
+ if (!subnetIdL1) {
+ return (
+
+ Please select an L1 subnet first.
+
+ );
+ }
+
+ return (
+
+ {error && (
+
{error}
+ )}
+
+
+
Delegation ID: {delegationID}
+
P-Chain Tx ID: {pChainTxId}
+
+
+
+ {isProcessing ? 'Processing...' : 'Sign & Complete Delegator Registration'}
+
+
+ {transactionHash && (
+
+ )}
+
+ );
+};
+
+export default CompleteDelegatorRegistration;
+
diff --git a/components/toolbox/console/permissionless-l1s/delegate/native/Delegate.tsx b/components/toolbox/console/permissionless-l1s/delegate/native/Delegate.tsx
new file mode 100644
index 00000000000..967fb31a01a
--- /dev/null
+++ b/components/toolbox/console/permissionless-l1s/delegate/native/Delegate.tsx
@@ -0,0 +1,235 @@
+"use client"
+import React, { useState } from 'react';
+import Link from 'next/link';
+import { Button } from '@/components/toolbox/components/Button';
+import SelectSubnetId from '@/components/toolbox/components/SelectSubnetId';
+import { ValidatorManagerDetails } from '@/components/toolbox/components/ValidatorManagerDetails';
+import { useValidatorManagerDetails } from '@/components/toolbox/hooks/useValidatorManagerDetails';
+import { Step, Steps } from "fumadocs-ui/components/steps";
+import { Success } from '@/components/toolbox/components/Success';
+import SelectValidationID, { ValidationSelection } from '@/components/toolbox/components/SelectValidationID';
+
+import InitiateNativeDelegation from '@/components/toolbox/console/permissionless-l1s/delegate/native/InitiateNativeDelegation';
+import SubmitPChainTxDelegationWeightChange from '@/components/toolbox/console/permissionless-l1s/delegate/native/SubmitPChainTxDelegationWeightChange';
+import CompleteDelegatorRegistration from '@/components/toolbox/console/permissionless-l1s/delegate/native/CompleteDelegatorRegistration';
+import { useCreateChainStore } from '@/components/toolbox/stores/createChainStore';
+import { useWalletStore } from '@/components/toolbox/stores/walletStore';
+import { WalletRequirementsConfigKey } from '@/components/toolbox/hooks/useWalletRequirements';
+import { BaseConsoleToolProps, ConsoleToolMetadata, withConsoleToolMetadata } from '../../../../components/WithConsoleToolMetadata';
+import { Alert } from '@/components/toolbox/components/Alert';
+import { generateConsoleToolGitHubUrl } from "@/components/toolbox/utils/github-url";
+
+const metadata: ConsoleToolMetadata = {
+ title: "Delegate to Validator",
+ description: "Delegate your native tokens to an existing validator on your L1",
+ toolRequirements: [
+ WalletRequirementsConfigKey.EVMChainBalance,
+ WalletRequirementsConfigKey.PChainBalance
+ ],
+ githubUrl: generateConsoleToolGitHubUrl(import.meta.url)
+};
+
+const DelegateToValidator: React.FC = ({ onSuccess }) => {
+ const [globalError, setGlobalError] = useState(null);
+ const [globalSuccess, setGlobalSuccess] = useState(null);
+ const [isValidatorManagerDetailsExpanded, setIsValidatorManagerDetailsExpanded] = useState(false);
+
+ // State for passing data between components
+ const [validationSelection, setValidationSelection] = useState({
+ validationId: '',
+ nodeId: ''
+ });
+ const [delegationID, setDelegationID] = useState('');
+ const [pChainTxId, setPChainTxId] = useState('');
+ const [evmTxHash, setEvmTxHash] = useState('');
+ const [eventData, setEventData] = useState<{
+ validationID: `0x${string}`;
+ nonce: bigint;
+ weight: bigint;
+ messageID: `0x${string}`;
+ } | null>(null);
+
+ // Form state
+ const { isTestnet } = useWalletStore();
+ const createChainStoreSubnetId = useCreateChainStore()(state => state.subnetId);
+ const [subnetIdL1, setSubnetIdL1] = useState(createChainStoreSubnetId || "");
+ const [resetKey, setResetKey] = useState(0);
+ const [userPChainBalanceNavax, setUserPChainBalanceNavax] = useState(null);
+
+ const {
+ validatorManagerAddress,
+ error: validatorManagerError,
+ isLoading: isLoadingVMCDetails,
+ blockchainId,
+ contractOwner,
+ isOwnerContract,
+ contractTotalWeight,
+ l1WeightError,
+ signingSubnetId,
+ isLoadingOwnership,
+ isLoadingL1Weight,
+ ownershipError,
+ ownerType,
+ isDetectingOwnerType
+ } = useValidatorManagerDetails({ subnetId: subnetIdL1 });
+
+ const handleReset = () => {
+ setGlobalError(null);
+ setGlobalSuccess(null);
+ setValidationSelection({ validationId: '', nodeId: '' });
+ setDelegationID('');
+ setPChainTxId('');
+ setEvmTxHash('');
+ setEventData(null);
+ setSubnetIdL1('');
+ setResetKey(prev => prev + 1); // Force re-render of all child components
+ };
+
+ return (
+ <>
+
+ {globalError && (
+
Error: {globalError}
+ )}
+
+
+
+ Select L1 Subnet
+
+ Choose the L1 subnet where you want to delegate to a validator.
+
+
+
+ setIsValidatorManagerDetailsExpanded(!isValidatorManagerDetailsExpanded)}
+ />
+
+
+
+
+ Select Validator to Delegate To
+
+ Select the validator you want to delegate to. The dropdown shows all active validators with their weights and remaining balances.
+
+
+ {ownerType && ownerType !== 'StakingManager' && (
+
+ This L1 is not using a Staking Manager. This tool is only for L1s with Native Token Staking Managers that support delegation.
+
+ )}
+
+
+
+ {validationSelection.nodeId && (
+
+
Selected Validator Node ID: {validationSelection.nodeId}
+
+ )}
+
+
+
+ Initiate Delegation
+
+ Call the initiateDelegatorRegistration function on the Native Token Staking Manager contract with your delegation amount. This transaction will emit a warp message for P-Chain registration.
+
+
+ {
+ setDelegationID(data.delegationID);
+ setEvmTxHash(data.txHash);
+ setGlobalError(null);
+ }}
+ onError={(message) => setGlobalError(message)}
+ />
+
+
+
+ Submit SetL1ValidatorWeightTx to P-Chain
+
+ Sign the emitted warp message and submit a SetL1ValidatorWeightTx to P-Chain. This transaction will update the validator's weight to include your delegation.
+
+ {
+ setPChainTxId(pChainTxId);
+ setEventData(data);
+ setGlobalError(null);
+ }}
+ onError={(message) => setGlobalError(message)}
+ />
+
+
+
+ Complete Delegator Registration
+
+ Complete the delegator registration by signing the P-Chain L1ValidatorRegistrationMessage and calling the completeDelegatorRegistration function on the Staking Manager contract.
+
+ {
+ setGlobalSuccess(message);
+ setGlobalError(null);
+ onSuccess?.();
+ }}
+ onError={(message) => setGlobalError(message)}
+ />
+
+
+
+ {globalSuccess && (
+
+ )}
+
+ {(pChainTxId || globalError || globalSuccess) && (
+
+ Reset All Steps
+
+ )}
+
+ >
+ );
+};
+
+export default withConsoleToolMetadata(DelegateToValidator, metadata);
+
diff --git a/components/toolbox/console/permissionless-l1s/delegate/native/InitiateNativeDelegation.tsx b/components/toolbox/console/permissionless-l1s/delegate/native/InitiateNativeDelegation.tsx
new file mode 100644
index 00000000000..658ed694da2
--- /dev/null
+++ b/components/toolbox/console/permissionless-l1s/delegate/native/InitiateNativeDelegation.tsx
@@ -0,0 +1,362 @@
+import React, { useState, useEffect } from 'react';
+import { useWalletStore } from '@/components/toolbox/stores/walletStore';
+import { useViemChainStore } from '@/components/toolbox/stores/toolboxStore';
+import { Button } from '@/components/toolbox/components/Button';
+import { Input } from '@/components/toolbox/components/Input';
+import { Success } from '@/components/toolbox/components/Success';
+import { Alert } from '@/components/toolbox/components/Alert';
+import nativeTokenStakingManagerAbi from '@/contracts/icm-contracts/compiled/NativeTokenStakingManager.json';
+import { parseEther, formatEther } from 'viem';
+import useConsoleNotifications from '@/hooks/useConsoleNotifications';
+
+interface InitiateNativeDelegationProps {
+ subnetId: string;
+ stakingManagerAddress: string;
+ validationID: string;
+ onSuccess: (data: { delegationID: string; txHash: string }) => void;
+ onError: (message: string) => void;
+}
+
+const InitiateNativeDelegation: React.FC = ({
+ subnetId,
+ stakingManagerAddress,
+ validationID,
+ onSuccess,
+ onError,
+}) => {
+ const { coreWalletClient, publicClient, walletEVMAddress } = useWalletStore();
+ const { notify } = useConsoleNotifications();
+ const viemChain = useViemChainStore();
+
+ const [delegationAmount, setDelegationAmount] = useState('');
+ const [rewardRecipient, setRewardRecipient] = useState('');
+ const [isProcessing, setIsProcessing] = useState(false);
+ const [error, setErrorState] = useState(null);
+ const [txHash, setTxHash] = useState(null);
+ const [delegationID, setDelegationID] = useState(null);
+ const [isLoadingExisting, setIsLoadingExisting] = useState(false);
+ const [existingDelegations, setExistingDelegations] = useState([]);
+
+ // Set default reward recipient to connected wallet
+ useEffect(() => {
+ if (walletEVMAddress && !rewardRecipient) {
+ setRewardRecipient(walletEVMAddress);
+ }
+ }, [walletEVMAddress]);
+
+ // Check for existing delegations when validation ID or wallet changes
+ useEffect(() => {
+ const checkExistingDelegations = async () => {
+ if (!publicClient || !stakingManagerAddress || !validationID || !walletEVMAddress) {
+ setExistingDelegations([]);
+ return;
+ }
+
+ setIsLoadingExisting(true);
+ try {
+ // Query InitiatedDelegatorRegistration events for this validator and delegator
+ const logs = await publicClient.getLogs({
+ address: stakingManagerAddress as `0x${string}`,
+ event: {
+ type: 'event',
+ name: 'InitiatedDelegatorRegistration',
+ inputs: [
+ { name: 'delegationID', type: 'bytes32', indexed: true },
+ { name: 'validationID', type: 'bytes32', indexed: true },
+ { name: 'delegatorAddress', type: 'address', indexed: true },
+ { name: 'nonce', type: 'uint64', indexed: false },
+ { name: 'validatorWeight', type: 'uint64', indexed: false },
+ { name: 'delegatorWeight', type: 'uint64', indexed: false },
+ { name: 'setWeightMessageID', type: 'bytes32', indexed: false },
+ { name: 'rewardRecipient', type: 'address', indexed: false },
+ ],
+ },
+ args: {
+ validationID: validationID as `0x${string}`,
+ delegatorAddress: walletEVMAddress as `0x${string}`,
+ },
+ fromBlock: 'earliest',
+ toBlock: 'latest',
+ });
+
+ const delegationIDs = logs.map(log => log.topics[1] as string).filter(Boolean);
+ setExistingDelegations(delegationIDs);
+ } catch (err) {
+ console.error('Error checking existing delegations:', err);
+ setExistingDelegations([]);
+ } finally {
+ setIsLoadingExisting(false);
+ }
+ };
+
+ checkExistingDelegations();
+ }, [publicClient, stakingManagerAddress, validationID, walletEVMAddress]);
+
+ const handleResendDelegation = async (delegationIdToResend: string) => {
+ setErrorState(null);
+ setTxHash(null);
+
+ if (!coreWalletClient || !publicClient || !viemChain) {
+ setErrorState("Wallet or chain configuration is not properly initialized.");
+ return;
+ }
+
+ if (!stakingManagerAddress) {
+ setErrorState("Staking Manager address is required.");
+ return;
+ }
+
+ setIsProcessing(true);
+ try {
+ // Call resendUpdateDelegator to re-emit the warp message
+ const writePromise = coreWalletClient.writeContract({
+ address: stakingManagerAddress as `0x${string}`,
+ abi: nativeTokenStakingManagerAbi.abi,
+ functionName: "resendUpdateDelegator",
+ args: [delegationIdToResend as `0x${string}`],
+ account: walletEVMAddress as `0x${string}`,
+ chain: viemChain,
+ });
+
+ notify({
+ type: 'call',
+ name: 'Resend Delegator Update'
+ }, writePromise, viemChain ?? undefined);
+
+ const hash = await writePromise;
+ setTxHash(hash);
+ setDelegationID(delegationIdToResend);
+
+ // Wait for confirmation
+ const receipt = await publicClient.waitForTransactionReceipt({ hash });
+ if (receipt.status !== 'success') {
+ throw new Error(`Transaction failed with status: ${receipt.status}`);
+ }
+
+ onSuccess({
+ delegationID: delegationIdToResend,
+ txHash: hash,
+ });
+ } catch (err: any) {
+ const message = err instanceof Error ? err.message : String(err);
+ setErrorState(`Failed to resend delegation: ${message}`);
+ } finally {
+ setIsProcessing(false);
+ }
+ };
+
+ const handleInitiateDelegation = async () => {
+ setErrorState(null);
+ setTxHash(null);
+ setDelegationID(null);
+
+ if (!coreWalletClient || !publicClient || !viemChain) {
+ setErrorState("Wallet or chain configuration is not properly initialized.");
+ onError("Wallet or chain configuration is not properly initialized.");
+ return;
+ }
+
+ if (!stakingManagerAddress) {
+ setErrorState("Staking Manager address is required.");
+ onError("Staking Manager address is required.");
+ return;
+ }
+
+ if (!validationID || validationID === '0x0000000000000000000000000000000000000000000000000000000000000000') {
+ setErrorState("Valid validation ID is required.");
+ onError("Valid validation ID is required.");
+ return;
+ }
+
+ if (!delegationAmount || parseFloat(delegationAmount) <= 0) {
+ setErrorState("Delegation amount must be greater than 0.");
+ onError("Delegation amount must be greater than 0.");
+ return;
+ }
+
+ if (!rewardRecipient || !rewardRecipient.startsWith('0x')) {
+ setErrorState("Valid reward recipient address is required.");
+ onError("Valid reward recipient address is required.");
+ return;
+ }
+
+ setIsProcessing(true);
+ try {
+ const delegationAmountWei = parseEther(delegationAmount);
+
+ // Read minimum stake amount from contract
+ const minStakeAmount = await publicClient.readContract({
+ address: stakingManagerAddress as `0x${string}`,
+ abi: nativeTokenStakingManagerAbi.abi,
+ functionName: "getStakingManagerSettings",
+ }) as any;
+
+ if (delegationAmountWei < minStakeAmount.minimumStakeAmount) {
+ const minFormatted = formatEther(minStakeAmount.minimumStakeAmount);
+ throw new Error(`Delegation amount must be at least ${minFormatted} tokens`);
+ }
+
+ // Call initiateDelegatorRegistration
+ const writePromise = coreWalletClient.writeContract({
+ address: stakingManagerAddress as `0x${string}`,
+ abi: nativeTokenStakingManagerAbi.abi,
+ functionName: "initiateDelegatorRegistration",
+ args: [validationID as `0x${string}`, rewardRecipient as `0x${string}`],
+ value: delegationAmountWei,
+ account: walletEVMAddress as `0x${string}`,
+ chain: viemChain,
+ });
+
+ notify({
+ type: 'call',
+ name: 'Initiate Delegator Registration'
+ }, writePromise, viemChain ?? undefined);
+
+ const hash = await writePromise;
+ setTxHash(hash);
+
+ // Wait for transaction receipt
+ const receipt = await publicClient.waitForTransactionReceipt({ hash });
+ if (receipt.status !== 'success') {
+ throw new Error(`Transaction failed with status: ${receipt.status}`);
+ }
+
+ // Extract delegationID from logs
+ const initiateDelegatorRegistrationTopic = "0x77499a5603260ef2b34698d88b31f7b1acf28c7b134ad4e3fa636501e6064d77";
+ const delegationLog = receipt.logs.find((log) =>
+ log.topics[0]?.toLowerCase() === initiateDelegatorRegistrationTopic.toLowerCase()
+ );
+
+ if (!delegationLog || !delegationLog.topics[1]) {
+ throw new Error("Failed to extract delegation ID from transaction receipt");
+ }
+
+ const extractedDelegationID = delegationLog.topics[1];
+ setDelegationID(extractedDelegationID);
+
+ onSuccess({
+ delegationID: extractedDelegationID,
+ txHash: hash,
+ });
+ } catch (err: any) {
+ let message = err instanceof Error ? err.message : String(err);
+
+ // Provide more helpful error messages
+ if (message.includes('Unable to calculate gas limit')) {
+ message = 'Transaction would fail. Possible reasons:\n' +
+ '- The validation ID is not a valid PoS validator\n' +
+ '- The validator has reached maximum delegation capacity\n' +
+ '- The validator minimum stake duration has not been met\n' +
+ 'Please verify the validation ID and try again.';
+ } else if (message.includes('InvalidValidationStatus')) {
+ message = 'This validator is not accepting delegations. The validator may not be active or registered yet.';
+ } else if (message.includes('InvalidDelegationID')) {
+ message = 'Invalid validation ID provided. Please check the validation ID and try again.';
+ } else if (message.includes('MaxWeightExceeded')) {
+ message = 'This delegation would exceed the maximum allowed weight for this validator.';
+ }
+
+ setErrorState(`Failed to initiate delegation: ${message}`);
+ onError(`Failed to initiate delegation: ${message}`);
+ } finally {
+ setIsProcessing(false);
+ }
+ };
+
+ return (
+
+ {error && (
+
{error}
+ )}
+
+ {isLoadingExisting && (
+
+ Checking for existing delegations...
+
+ )}
+
+ {existingDelegations.length > 0 && !txHash && (
+
+
+
Found {existingDelegations.length} existing delegation(s) to this validator:
+
+ {existingDelegations.map((delId, index) => (
+
+ {delId}
+ handleResendDelegation(delId)}
+ disabled={isProcessing}
+ size="sm"
+ >
+ Resend Warp Message
+
+
+ ))}
+
+
+
+ )}
+
+ {!txHash && (
+ <>
+
{}} // Read-only, set by parent
+ placeholder="Validation ID of the validator to delegate to"
+ disabled={true}
+ />
+
+
+
+
+
+
+ {isProcessing ? 'Processing...' : 'Initiate New Delegation'}
+
+ >
+ )}
+
+ {txHash && (
+ <>
+
+
+ {delegationID && (
+
+ )}
+ >
+ )}
+
+ );
+};
+
+export default InitiateNativeDelegation;
+
diff --git a/components/toolbox/console/permissionless-l1s/delegate/native/SubmitPChainTxDelegationWeightChange.tsx b/components/toolbox/console/permissionless-l1s/delegate/native/SubmitPChainTxDelegationWeightChange.tsx
new file mode 100644
index 00000000000..ef22c6f489f
--- /dev/null
+++ b/components/toolbox/console/permissionless-l1s/delegate/native/SubmitPChainTxDelegationWeightChange.tsx
@@ -0,0 +1,292 @@
+import React, { useState, useEffect } from 'react';
+import { useWalletStore } from '@/components/toolbox/stores/walletStore';
+import { Button } from '@/components/toolbox/components/Button';
+import { Input } from '@/components/toolbox/components/Input';
+import { Success } from '@/components/toolbox/components/Success';
+import { Alert } from '@/components/toolbox/components/Alert';
+import { useAvalancheSDKChainkit } from '@/components/toolbox/stores/useAvalancheSDKChainkit';
+import useConsoleNotifications from '@/hooks/useConsoleNotifications';
+
+interface SubmitPChainTxDelegationWeightChangeProps {
+ subnetIdL1: string;
+ initialEvmTxHash?: string;
+ signingSubnetId: string;
+ onSuccess: (pChainTxId: string, eventData: {
+ validationID: `0x${string}`;
+ nonce: bigint;
+ weight: bigint;
+ messageID: `0x${string}`;
+ }) => void;
+ onError: (message: string) => void;
+}
+
+const SubmitPChainTxDelegationWeightChange: React.FC = ({
+ subnetIdL1,
+ initialEvmTxHash,
+ signingSubnetId,
+ onSuccess,
+ onError,
+}) => {
+ const { coreWalletClient, pChainAddress, publicClient } = useWalletStore();
+ const { aggregateSignature } = useAvalancheSDKChainkit();
+ const { notify } = useConsoleNotifications();
+ const [evmTxHash, setEvmTxHash] = useState(initialEvmTxHash || '');
+ const [isProcessing, setIsProcessing] = useState(false);
+ const [error, setErrorState] = useState(null);
+ const [txSuccess, setTxSuccess] = useState(null);
+ const [unsignedWarpMessage, setUnsignedWarpMessage] = useState(null);
+ const [signedWarpMessage, setSignedWarpMessage] = useState(null);
+ const [eventData, setEventData] = useState<{
+ validationID: `0x${string}`;
+ nonce: bigint;
+ weight: bigint;
+ messageID: `0x${string}`;
+ } | null>(null);
+
+ // Update evmTxHash when initialEvmTxHash prop changes
+ useEffect(() => {
+ if (initialEvmTxHash && initialEvmTxHash !== evmTxHash) {
+ setEvmTxHash(initialEvmTxHash);
+ }
+ }, [initialEvmTxHash]);
+
+ const validateAndCleanTxHash = (hash: string): `0x${string}` | null => {
+ if (!hash) return null;
+ const cleanHash = hash.trim().toLowerCase();
+ if (!cleanHash.startsWith('0x')) return null;
+ if (cleanHash.length !== 66) return null;
+ return cleanHash as `0x${string}`;
+ };
+
+ // Extract warp message and event data when transaction hash changes
+ useEffect(() => {
+ const extractWarpMessage = async () => {
+ const validTxHash = validateAndCleanTxHash(evmTxHash);
+ if (!publicClient || !validTxHash) {
+ setUnsignedWarpMessage(null);
+ setEventData(null);
+ setSignedWarpMessage(null);
+ return;
+ }
+
+ try {
+ const receipt = await publicClient.waitForTransactionReceipt({ hash: validTxHash });
+ if (!receipt.logs || receipt.logs.length === 0) {
+ throw new Error("Failed to get warp message from transaction receipt.");
+ }
+
+ console.log("[WarpExtract] Transaction receipt:", receipt);
+ console.log("[WarpExtract] Number of logs:", receipt.logs.length);
+
+ // Log all transaction logs for debugging
+ receipt.logs.forEach((log, index) => {
+ console.log(`[WarpExtract] Log #${index}:`, {
+ address: log.address,
+ topics: log.topics,
+ data: log.data?.substring(0, 100) + "...",
+ logIndex: log.logIndex,
+ transactionIndex: log.transactionIndex,
+ });
+ });
+
+ // Look for warp message
+ let unsignedWarpMessage: string | null = null;
+ const warpMessageTopic = "0x56600c567728a800c0aa927500f831cb451df66a7af570eb4df4dfbf4674887d";
+ const warpPrecompileAddress = "0x0200000000000000000000000000000000000005";
+
+ const warpEventLog = receipt.logs.find((log) => {
+ return log && log.address && log.address.toLowerCase() === warpPrecompileAddress.toLowerCase() &&
+ log.topics && log.topics[0] && log.topics[0].toLowerCase() === warpMessageTopic.toLowerCase();
+ });
+
+ if (warpEventLog && warpEventLog.data) {
+ console.log("[WarpExtract] Found warp message from precompile event");
+ unsignedWarpMessage = warpEventLog.data;
+ } else {
+ if (receipt.logs.length > 1 && receipt.logs[1].data) {
+ console.log("[WarpExtract] Using receipt.logs[1].data for potential multisig transaction");
+ unsignedWarpMessage = receipt.logs[1].data;
+ } else if (receipt.logs[0].data) {
+ console.log("[WarpExtract] Using receipt.logs[0].data as fallback");
+ unsignedWarpMessage = receipt.logs[0].data;
+ }
+ }
+
+ if (!unsignedWarpMessage) {
+ throw new Error("Could not extract warp message from any log in the transaction receipt.");
+ }
+
+ console.log("[WarpExtract] Extracted warp message:", unsignedWarpMessage.substring(0, 60) + "...");
+ setUnsignedWarpMessage(unsignedWarpMessage);
+
+ // Extract event data from InitiatedDelegatorRegistration event
+ const delegationTopic = "0x77499a5603260ef2b34698d88b31f7b1acf28c7b134ad4e3fa636501e6064d77";
+ const eventLog = receipt.logs.find((log) => {
+ return log && log.topics && log.topics[0] && log.topics[0].toLowerCase() === delegationTopic.toLowerCase();
+ });
+
+ if (!eventLog) {
+ throw new Error("Failed to find InitiatedDelegatorRegistration event log.");
+ }
+
+ const dataWithoutPrefix = eventLog.data.slice(2);
+ const nonce = BigInt("0x" + dataWithoutPrefix.slice(0, 64));
+ const validatorWeight = BigInt("0x" + dataWithoutPrefix.slice(64, 128));
+ const delegatorWeight = BigInt("0x" + dataWithoutPrefix.slice(128, 192));
+ const messageID = "0x" + dataWithoutPrefix.slice(192, 256);
+
+ const parsedEventData = {
+ validationID: eventLog.topics[2] as `0x${string}`, // validationID is topics[2] for delegation
+ nonce,
+ messageID: messageID as `0x${string}`,
+ weight: validatorWeight, // Use validator weight (includes delegation)
+ };
+ setEventData(parsedEventData);
+ setErrorState(null);
+ } catch (err: any) {
+ const message = err instanceof Error ? err.message : String(err);
+ setErrorState(`Failed to extract warp message: ${message}`);
+ setUnsignedWarpMessage(null);
+ setEventData(null);
+ setSignedWarpMessage(null);
+ }
+ };
+
+ extractWarpMessage();
+ }, [evmTxHash, publicClient]);
+
+ const handleSubmitPChainTx = async () => {
+ setErrorState(null);
+ setTxSuccess(null);
+
+ if (!coreWalletClient) {
+ setErrorState("Core wallet not found");
+ return;
+ }
+
+ if (!evmTxHash.trim()) {
+ setErrorState("EVM transaction hash is required.");
+ onError("EVM transaction hash is required.");
+ return;
+ }
+ if (!subnetIdL1) {
+ setErrorState("L1 Subnet ID is required. Please select a subnet first.");
+ onError("L1 Subnet ID is required. Please select a subnet first.");
+ return;
+ }
+ if (!unsignedWarpMessage) {
+ setErrorState("Unsigned warp message not found. Check the transaction hash.");
+ onError("Unsigned warp message not found. Check the transaction hash.");
+ return;
+ }
+ if (!eventData) {
+ setErrorState("Event data not found. Check the transaction hash.");
+ onError("Event data not found. Check the transaction hash.");
+ return;
+ }
+ if (typeof window === 'undefined' || !window.avalanche) {
+ setErrorState("Core wallet not found. Please ensure Core is installed and active.");
+ onError("Core wallet not found. Please ensure Core is installed and active.");
+ return;
+ }
+ if (!pChainAddress) {
+ setErrorState("P-Chain address is missing from wallet. Please connect your wallet properly.");
+ onError("P-Chain address is missing from wallet. Please connect your wallet properly.");
+ return;
+ }
+
+ setIsProcessing(true);
+ try {
+ // Step 1: Sign the warp message
+ const aggregateSignaturePromise = aggregateSignature({
+ message: unsignedWarpMessage,
+ signingSubnetId: signingSubnetId || subnetIdL1,
+ quorumPercentage: 67,
+ });
+ notify({
+ type: 'local',
+ name: 'Aggregate Signatures'
+ }, aggregateSignaturePromise);
+ const { signedMessage } = await aggregateSignaturePromise;
+
+ setSignedWarpMessage(signedMessage);
+
+ // Step 2: Submit to P-Chain
+ const pChainTxIdPromise = coreWalletClient.setL1ValidatorWeight({
+ signedWarpMessage: signedMessage,
+ });
+ notify('setL1ValidatorWeight', pChainTxIdPromise);
+ const pChainTxId = await pChainTxIdPromise;
+ setTxSuccess(`P-Chain transaction successful! ID: ${pChainTxId}`);
+ onSuccess(pChainTxId, eventData);
+ } catch (err: any) {
+ let message = err instanceof Error ? err.message : String(err);
+
+ // Handle specific error types
+ if (message.includes('User rejected')) {
+ message = 'Transaction was rejected by user';
+ } else if (message.includes('insufficient funds')) {
+ message = 'Insufficient funds for transaction';
+ } else if (message.includes('execution reverted')) {
+ message = `Transaction reverted: ${message}`;
+ } else if (message.includes('nonce')) {
+ message = 'Transaction nonce error. Please try again.';
+ }
+
+ setErrorState(`P-Chain transaction failed: ${message}`);
+ onError(`P-Chain transaction failed: ${message}`);
+ } finally {
+ setIsProcessing(false);
+ }
+ };
+
+ const handleTxHashChange = (value: string) => {
+ setEvmTxHash(value);
+ setErrorState(null);
+ setTxSuccess(null);
+ setSignedWarpMessage(null);
+ };
+
+ // Don't render if no subnet is selected
+ if (!subnetIdL1) {
+ return (
+
+ Please select an L1 subnet first.
+
+ );
+ }
+
+ return (
+
+
+
+
+ {isProcessing ? 'Processing...' : 'Sign & Submit to P-Chain'}
+
+
+ {error && (
+
{error}
+ )}
+
+ {txSuccess && (
+
+ )}
+
+ );
+};
+
+export default SubmitPChainTxDelegationWeightChange;
+
+