From 8777f8817d8aacb2be976655d0ba678eea0906c7 Mon Sep 17 00:00:00 2001 From: Arran Schlosberg Date: Tue, 6 Aug 2024 20:12:22 +0100 Subject: [PATCH 01/27] perf: `SetSubnetValidatorWeightMessage` (un)packing gas reductions --- contracts/staking/StakingMessages.sol | 130 ++++---- .../staking/tests/ManualStakingMessages.sol | 289 ++++++++++++++++++ contracts/staking/tests/StakingMessages.t.sol | 72 +++++ 3 files changed, 422 insertions(+), 69 deletions(-) create mode 100644 contracts/staking/tests/ManualStakingMessages.sol create mode 100644 contracts/staking/tests/StakingMessages.t.sol diff --git a/contracts/staking/StakingMessages.sol b/contracts/staking/StakingMessages.sol index 3d6698b89..7b3bad372 100644 --- a/contracts/staking/StakingMessages.sol +++ b/contracts/staking/StakingMessages.sol @@ -48,18 +48,23 @@ library StakingMessages { * | 148 bytes | * +-----------+ */ - function packRegisterSubnetValidatorMessage(ValidationInfo memory valiationInfo) - internal - pure - returns (bytes32, bytes memory) - { - (bytes32 validationID, bytes memory serializedValidationInfo) = - packValidationInfo(valiationInfo); + function packRegisterSubnetValidatorMessage( + ValidationInfo memory valiationInfo + ) internal pure returns (bytes32, bytes memory) { + ( + bytes32 validationID, + bytes memory serializedValidationInfo + ) = packValidationInfo(valiationInfo); bytes memory res = new bytes(148); // Pack the message type for (uint256 i; i < 4; ++i) { - res[i] = bytes1(uint8(SUBNET_VALIDATOR_REGISTRATION_MESSAGE_TYPE_ID >> (8 * (3 - i)))); + res[i] = bytes1( + uint8( + SUBNET_VALIDATOR_REGISTRATION_MESSAGE_TYPE_ID >> + (8 * (3 - i)) + ) + ); } // Pack the validation info for (uint256 i; i < 144; ++i) { @@ -84,11 +89,9 @@ library StakingMessages { * @return The validationID and whether or the validation period was registered * or is not a validator and never will be a validator to do the expiry time passing. */ - function unpackSubnetValidatorRegistrationMessage(bytes memory input) - internal - pure - returns (bytes32, bool) - { + function unpackSubnetValidatorRegistrationMessage( + bytes memory input + ) internal pure returns (bytes32, bool) { require(input.length == 37, "StakingMessages: Invalid message length"); // Unpack the type ID @@ -104,7 +107,9 @@ library StakingMessages { // Unpack the validation ID. bytes32 validationID; for (uint256 i; i < 32; ++i) { - validationID |= bytes32(uint256(uint8(input[i + 4])) << (8 * (31 - i))); + validationID |= bytes32( + uint256(uint8(input[i + 4])) << (8 * (31 - i)) + ); } // Unpack the validity @@ -133,63 +138,42 @@ library StakingMessages { uint64 nonce, uint64 weight ) internal pure returns (bytes memory) { - bytes memory res = new bytes(52); - // Pack the type ID. - for (uint256 i; i < 4; ++i) { - res[i] = bytes1(uint8(SET_SUBNET_VALIDATOR_WEIGHT_MESSAGE_TYPE_ID >> (8 * (3 - i)))); - } - // Pack the validation ID. - for (uint256 i; i < 32; ++i) { - res[i + 4] = bytes1(uint8(uint256(validationID >> (8 * (31 - i))))); - } - // Pack the nonce. - for (uint256 i; i < 8; ++i) { - res[i + 36] = bytes1(uint8(nonce >> (8 * (7 - i)))); - } - // Pack the weight. - for (uint256 i; i < 8; ++i) { - res[i + 44] = bytes1(uint8(weight >> (8 * (7 - i)))); - } - return res; + return + abi.encodePacked( + StakingMessages.SET_SUBNET_VALIDATOR_WEIGHT_MESSAGE_TYPE_ID, + validationID, + nonce, + weight + ); } /** * @notice Unpacks a byte array as a SetSubnetValidatorWeight message. * The message format specification is the same as the one used in above for packing. */ - function unpackSetSubnetValidatorWeightMessage(bytes memory input) - internal - pure - returns (bytes32, uint64, uint64) - { + function unpackSetSubnetValidatorWeightMessage( + bytes memory input + ) internal pure returns (bytes32, uint64, uint64) { require(input.length == 52, "StakingMessages: Invalid message length"); - // Unpack the type ID. uint32 typeID; - for (uint256 i; i < 4; ++i) { - typeID |= uint32(uint8(input[i])) << uint32((8 * (3 - i))); + assembly ("memory-safe") { + typeID := shr(224, mload(add(input, 0x20))) } require( - typeID == SET_SUBNET_VALIDATOR_WEIGHT_MESSAGE_TYPE_ID, + typeID == + StakingMessages.SET_SUBNET_VALIDATOR_WEIGHT_MESSAGE_TYPE_ID, "StakingMessages: Invalid message type" ); - // Unpack the validation ID. bytes32 validationID; - for (uint256 i; i < 32; ++i) { - validationID |= bytes32(uint256(uint8(input[i + 4])) << (8 * (31 - i))); - } - - // Unpack the nonce. uint64 nonce; - for (uint256 i; i < 8; ++i) { - nonce |= uint64(uint8(input[i + 36])) << uint64((8 * (7 - i))); - } - - // Unpack the weight. uint64 weight; - for (uint256 i; i < 8; ++i) { - weight |= uint64(uint8(input[i + 44])) << uint64((8 * (7 - i))); + assembly ("memory-safe") { + validationID := mload(add(input, 0x24)) + let rest := mload(add(input, 0x44)) // only the first 128 bits are valid + nonce := shr(192, rest) + weight := shr(192, shl(64, rest)) // shl(64, ) wipes the nonce } return (validationID, nonce, weight); @@ -208,11 +192,9 @@ library StakingMessages { * | 44 bytes | * +----------+ */ - function unpackValidationUptimeMessage(bytes memory input) - internal - pure - returns (bytes32, uint64) - { + function unpackValidationUptimeMessage( + bytes memory input + ) internal pure returns (bytes32, uint64) { require(input.length == 44, "StakingMessages: Invalid message length"); // Unpack the type ID. @@ -221,13 +203,16 @@ library StakingMessages { typeID |= uint32(uint8(input[i])) << uint32((8 * (3 - i))); } require( - typeID == VALIDATION_UPTIME_MESSAGE_TYPE_ID, "StakingMessages: Invalid message type" + typeID == VALIDATION_UPTIME_MESSAGE_TYPE_ID, + "StakingMessages: Invalid message type" ); // Unpack the validation ID. bytes32 validationID; for (uint256 i; i < 32; ++i) { - validationID |= bytes32(uint256(uint8(input[i + 4])) << (8 * (31 - i))); + validationID |= bytes32( + uint256(uint8(input[i + 4])) << (8 * (31 - i)) + ); } // Unpack the uptime. @@ -257,12 +242,13 @@ library StakingMessages { * | 144 bytes | * +-----------+ */ - function packValidationInfo(ValidationInfo memory validationInfo) - internal - pure - returns (bytes32, bytes memory) - { - require(validationInfo.signature.length == 64, "StakingMessages: Invalid signature length"); + function packValidationInfo( + ValidationInfo memory validationInfo + ) internal pure returns (bytes32, bytes memory) { + require( + validationInfo.signature.length == 64, + "StakingMessages: Invalid signature length" + ); bytes memory res = new bytes(144); // Pack the subnetID for (uint256 i; i < 32; ++i) { @@ -274,11 +260,17 @@ library StakingMessages { } // Pack the weight for (uint256 i; i < 8; ++i) { - res[i + 64] = bytes1(uint8(validationInfo.weight >> uint8((8 * (7 - i))))); + res[i + 64] = bytes1( + uint8(validationInfo.weight >> uint8((8 * (7 - i)))) + ); } // Pack the registration expiry for (uint256 i; i < 8; ++i) { - res[i + 72] = bytes1(uint8(validationInfo.registrationExpiry >> uint64((8 * (7 - i))))); + res[i + 72] = bytes1( + uint8( + validationInfo.registrationExpiry >> uint64((8 * (7 - i))) + ) + ); } // Pack the signature for (uint256 i; i < 64; ++i) { diff --git a/contracts/staking/tests/ManualStakingMessages.sol b/contracts/staking/tests/ManualStakingMessages.sol new file mode 100644 index 000000000..3d6698b89 --- /dev/null +++ b/contracts/staking/tests/ManualStakingMessages.sol @@ -0,0 +1,289 @@ +// (c) 2023, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +// SPDX-License-Identifier: Ecosystem +pragma solidity 0.8.25; + +library StakingMessages { + // The information that uniquely identifies a subnet validation period. + // The SHA-256 hash of the concatenation of these field is the validationID. + struct ValidationInfo { + bytes32 subnetID; + bytes32 nodeID; + uint64 weight; + uint64 registrationExpiry; + bytes signature; + } + + // Subnets send a RegisterSubnetValidator message to the P-Chain to register a validator. + // The P-Chain responds with a RegisterSubnetValidator message indicating whether the registration was successful + // for the given validation ID. + uint32 internal constant SUBNET_VALIDATOR_REGISTRATION_MESSAGE_TYPE_ID = 1; + // Subnets can send a SetSubnetValidatorWeight message to the P-Chain to update a validator's weight. + // The P-Chain responds with a SetSubnetValidatorWeight message acknowledging the weight update. + uint32 internal constant SET_SUBNET_VALIDATOR_WEIGHT_MESSAGE_TYPE_ID = 2; + // The Subnet will self-sign a ValidationUptimeMessage to be provided when a validator is initiating + // the end of their validation period. + uint32 internal constant VALIDATION_UPTIME_MESSAGE_TYPE_ID = 3; + + // TODO: The implemenation of these packing and unpacking functions is neither tested or optimzied at all. + // Full test coverage should be provided, and the implementation should be optimized for gas efficiency. + + /** + * @notice Packs a RegisterSubnetValidator message into a byte array. + * The message format specification is: + * +-----------+----------+-----------+ + * | typeID : uint32 | 4 bytes | + * +-----------+----------+-----------+ + * | subnetID : [32]byte | 32 bytes | + * +-----------+----------+-----------+ + * | nodeID : [32]byte | 32 bytes | + * +-----------+----------+-----------+ + * | weight : uint64 | 8 bytes | + * +-----------+----------+-----------+ + * | expiry : uint64 | 8 bytes | + * +-----------+----------+-----------+ + * | signature : [64]byte | 64 bytes | + * +-----------+----------+-----------+ + * | 148 bytes | + * +-----------+ + */ + function packRegisterSubnetValidatorMessage(ValidationInfo memory valiationInfo) + internal + pure + returns (bytes32, bytes memory) + { + (bytes32 validationID, bytes memory serializedValidationInfo) = + packValidationInfo(valiationInfo); + + bytes memory res = new bytes(148); + // Pack the message type + for (uint256 i; i < 4; ++i) { + res[i] = bytes1(uint8(SUBNET_VALIDATOR_REGISTRATION_MESSAGE_TYPE_ID >> (8 * (3 - i)))); + } + // Pack the validation info + for (uint256 i; i < 144; ++i) { + res[i + 4] = serializedValidationInfo[i]; + } + + return (validationID, res); + } + + /** + * @notice Unpacks a byte array as a RegisterSubnetValidator message. + * The message format specification is: + * +--------------+----------+----------+ + * | typeID : uint32 | 4 bytes | + * +--------------+----------+----------+ + * | validationID : [32]byte | 32 bytes | + * +--------------+----------+----------+ + * | valid : bool + 1 byte | + * +--------------+----------+----------+ + * | 37 bytes | + * +----------+ + * @return The validationID and whether or the validation period was registered + * or is not a validator and never will be a validator to do the expiry time passing. + */ + function unpackSubnetValidatorRegistrationMessage(bytes memory input) + internal + pure + returns (bytes32, bool) + { + require(input.length == 37, "StakingMessages: Invalid message length"); + + // Unpack the type ID + uint32 typeID; + for (uint256 i; i < 4; ++i) { + typeID |= uint32(uint8(input[i])) << uint32((8 * (3 - i))); + } + require( + typeID == SUBNET_VALIDATOR_REGISTRATION_MESSAGE_TYPE_ID, + "StakingMessages: Invalid message type" + ); + + // Unpack the validation ID. + bytes32 validationID; + for (uint256 i; i < 32; ++i) { + validationID |= bytes32(uint256(uint8(input[i + 4])) << (8 * (31 - i))); + } + + // Unpack the validity + bool valid = input[36] != 0; + + return (validationID, valid); + } + + /** + * @notice Packs a SetSubnetValidatorWeight message into a byte array. + * The message format specification is: + * +--------------+----------+----------+ + * | typeID : uint32 | 4 bytes | + * +--------------+----------+----------+ + * | validationID : [32]byte | 32 bytes | + * +--------------+----------+----------+ + * | nonce : uint64 | 8 bytes | + * +--------------+----------+----------+ + * | weight : uint64 | 8 bytes | + * +--------------+----------+----------+ + * | 52 bytes | + * +----------+ + */ + function packSetSubnetValidatorWeightMessage( + bytes32 validationID, + uint64 nonce, + uint64 weight + ) internal pure returns (bytes memory) { + bytes memory res = new bytes(52); + // Pack the type ID. + for (uint256 i; i < 4; ++i) { + res[i] = bytes1(uint8(SET_SUBNET_VALIDATOR_WEIGHT_MESSAGE_TYPE_ID >> (8 * (3 - i)))); + } + // Pack the validation ID. + for (uint256 i; i < 32; ++i) { + res[i + 4] = bytes1(uint8(uint256(validationID >> (8 * (31 - i))))); + } + // Pack the nonce. + for (uint256 i; i < 8; ++i) { + res[i + 36] = bytes1(uint8(nonce >> (8 * (7 - i)))); + } + // Pack the weight. + for (uint256 i; i < 8; ++i) { + res[i + 44] = bytes1(uint8(weight >> (8 * (7 - i)))); + } + return res; + } + + /** + * @notice Unpacks a byte array as a SetSubnetValidatorWeight message. + * The message format specification is the same as the one used in above for packing. + */ + function unpackSetSubnetValidatorWeightMessage(bytes memory input) + internal + pure + returns (bytes32, uint64, uint64) + { + require(input.length == 52, "StakingMessages: Invalid message length"); + + // Unpack the type ID. + uint32 typeID; + for (uint256 i; i < 4; ++i) { + typeID |= uint32(uint8(input[i])) << uint32((8 * (3 - i))); + } + require( + typeID == SET_SUBNET_VALIDATOR_WEIGHT_MESSAGE_TYPE_ID, + "StakingMessages: Invalid message type" + ); + + // Unpack the validation ID. + bytes32 validationID; + for (uint256 i; i < 32; ++i) { + validationID |= bytes32(uint256(uint8(input[i + 4])) << (8 * (31 - i))); + } + + // Unpack the nonce. + uint64 nonce; + for (uint256 i; i < 8; ++i) { + nonce |= uint64(uint8(input[i + 36])) << uint64((8 * (7 - i))); + } + + // Unpack the weight. + uint64 weight; + for (uint256 i; i < 8; ++i) { + weight |= uint64(uint8(input[i + 44])) << uint64((8 * (7 - i))); + } + + return (validationID, nonce, weight); + } + + /** + * @notice Unpacks a byte array as a ValidationUptimeMessage. + * The message format specification is: + * +--------------+----------+----------+ + * | typeID : uint32 | 4 bytes | + * +--------------+----------+----------+ + * | validationID : [32]byte | 32 bytes | + * +--------------+----------+----------+ + * | uptime : uint64 | 8 bytes | + * +--------------+----------+----------+ + * | 44 bytes | + * +----------+ + */ + function unpackValidationUptimeMessage(bytes memory input) + internal + pure + returns (bytes32, uint64) + { + require(input.length == 44, "StakingMessages: Invalid message length"); + + // Unpack the type ID. + uint32 typeID; + for (uint256 i; i < 4; ++i) { + typeID |= uint32(uint8(input[i])) << uint32((8 * (3 - i))); + } + require( + typeID == VALIDATION_UPTIME_MESSAGE_TYPE_ID, "StakingMessages: Invalid message type" + ); + + // Unpack the validation ID. + bytes32 validationID; + for (uint256 i; i < 32; ++i) { + validationID |= bytes32(uint256(uint8(input[i + 4])) << (8 * (31 - i))); + } + + // Unpack the uptime. + uint64 uptime; + for (uint256 i; i < 8; ++i) { + uptime |= uint64(uint8(input[i + 36])) << uint64((8 * (7 - i))); + } + + return (validationID, uptime); + } + + /** + * @notice Packs all of the information pertaining to a validation period into a byte array. + * The packed data is used to calculate the validationID as the SHA-256 hash of the packed data. + * The specification of the packed data is: + * +-----------+----------+-----------+ + * | subnetID : [32]byte | 32 bytes | + * +-----------+----------+-----------+ + * | nodeID : [32]byte | 32 bytes | + * +-----------+----------+-----------+ + * | weight : uint64 | 8 bytes | + * +-----------+----------+-----------+ + * | expiry : uint64 | 8 bytes | + * +-----------+----------+-----------+ + * | signature : [64]byte | 64 bytes | + * +-----------+----------+-----------+ + * | 144 bytes | + * +-----------+ + */ + function packValidationInfo(ValidationInfo memory validationInfo) + internal + pure + returns (bytes32, bytes memory) + { + require(validationInfo.signature.length == 64, "StakingMessages: Invalid signature length"); + bytes memory res = new bytes(144); + // Pack the subnetID + for (uint256 i; i < 32; ++i) { + res[i] = validationInfo.subnetID[i]; + } + // Pack the nodeID + for (uint256 i; i < 32; ++i) { + res[i + 32] = validationInfo.nodeID[i]; + } + // Pack the weight + for (uint256 i; i < 8; ++i) { + res[i + 64] = bytes1(uint8(validationInfo.weight >> uint8((8 * (7 - i))))); + } + // Pack the registration expiry + for (uint256 i; i < 8; ++i) { + res[i + 72] = bytes1(uint8(validationInfo.registrationExpiry >> uint64((8 * (7 - i))))); + } + // Pack the signature + for (uint256 i; i < 64; ++i) { + res[i + 80] = validationInfo.signature[i]; + } + return (sha256(res), res); + } +} diff --git a/contracts/staking/tests/StakingMessages.t.sol b/contracts/staking/tests/StakingMessages.t.sol new file mode 100644 index 000000000..be771e76f --- /dev/null +++ b/contracts/staking/tests/StakingMessages.t.sol @@ -0,0 +1,72 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.25; + +import {Test} from "@forge-std/Test.sol"; +import {StakingMessages} from "../StakingMessages.sol"; +import {StakingMessages as Original} from "./ManualStakingMessages.sol"; + +contract StakingMessagesTest is Test { + function testSubnetValidatorWeightPackRoundTrip( + bytes32 validationID, + uint64 nonce, + uint64 weight + ) public view { + uint256 startGas; + uint256 endGas; + + startGas = gasleft(); + bytes memory original = Original.packSetSubnetValidatorWeightMessage( + validationID, + nonce, + weight + ); + endGas = gasleft(); + uint256 originalGas = startGas - endGas; + + startGas = gasleft(); + bytes memory packed = StakingMessages + .packSetSubnetValidatorWeightMessage(validationID, nonce, weight); + endGas = gasleft(); + // Doing this after the original will actually penalise it because + // memory expansion is quadratic, so the gas saving is higher than the + // test suggests. + uint256 gas = startGas - endGas; + + assertEq(original, packed, "same data"); + assertGe(originalGas - gas, 19_500, "gas saving"); + + ( + bytes32 gotValidationID, + uint64 gotNonce, + uint64 gotWeight + ) = StakingMessages.unpackSetSubnetValidatorWeightMessage(packed); + + assertEq(validationID, gotValidationID, "validation ID"); + assertEq(nonce, gotNonce, "nonce"); + assertEq(weight, gotWeight, "weight"); + } + + function testUnpackSubnetValidatorWeightGas( + bytes32 validationID, + uint64 nonce, + uint64 weight + ) public view { + bytes memory buffer = StakingMessages + .packSetSubnetValidatorWeightMessage(validationID, nonce, weight); + + uint256 startGas; + uint256 endGas; + + startGas = gasleft(); + StakingMessages.unpackSetSubnetValidatorWeightMessage(buffer); + endGas = gasleft(); + uint256 gas = startGas - endGas; + + startGas = gasleft(); + Original.unpackSetSubnetValidatorWeightMessage(buffer); + endGas = gasleft(); + uint256 originalGas = startGas - endGas; + + assertGe(originalGas - gas, 18_000, "gas saving"); + } +} From 8b0557a6485af5dcb6b4d0ddf3f1cda2fd533e3d Mon Sep 17 00:00:00 2001 From: Arran Schlosberg Date: Tue, 6 Aug 2024 20:19:04 +0100 Subject: [PATCH 02/27] chore: `forge fmt` --- contracts/staking/StakingMessages.sol | 92 ++++++++----------- contracts/staking/tests/StakingMessages.t.sol | 22 ++--- 2 files changed, 46 insertions(+), 68 deletions(-) diff --git a/contracts/staking/StakingMessages.sol b/contracts/staking/StakingMessages.sol index 7b3bad372..bc6a560f9 100644 --- a/contracts/staking/StakingMessages.sol +++ b/contracts/staking/StakingMessages.sol @@ -48,23 +48,18 @@ library StakingMessages { * | 148 bytes | * +-----------+ */ - function packRegisterSubnetValidatorMessage( - ValidationInfo memory valiationInfo - ) internal pure returns (bytes32, bytes memory) { - ( - bytes32 validationID, - bytes memory serializedValidationInfo - ) = packValidationInfo(valiationInfo); + function packRegisterSubnetValidatorMessage(ValidationInfo memory valiationInfo) + internal + pure + returns (bytes32, bytes memory) + { + (bytes32 validationID, bytes memory serializedValidationInfo) = + packValidationInfo(valiationInfo); bytes memory res = new bytes(148); // Pack the message type for (uint256 i; i < 4; ++i) { - res[i] = bytes1( - uint8( - SUBNET_VALIDATOR_REGISTRATION_MESSAGE_TYPE_ID >> - (8 * (3 - i)) - ) - ); + res[i] = bytes1(uint8(SUBNET_VALIDATOR_REGISTRATION_MESSAGE_TYPE_ID >> (8 * (3 - i)))); } // Pack the validation info for (uint256 i; i < 144; ++i) { @@ -89,9 +84,11 @@ library StakingMessages { * @return The validationID and whether or the validation period was registered * or is not a validator and never will be a validator to do the expiry time passing. */ - function unpackSubnetValidatorRegistrationMessage( - bytes memory input - ) internal pure returns (bytes32, bool) { + function unpackSubnetValidatorRegistrationMessage(bytes memory input) + internal + pure + returns (bytes32, bool) + { require(input.length == 37, "StakingMessages: Invalid message length"); // Unpack the type ID @@ -107,9 +104,7 @@ library StakingMessages { // Unpack the validation ID. bytes32 validationID; for (uint256 i; i < 32; ++i) { - validationID |= bytes32( - uint256(uint8(input[i + 4])) << (8 * (31 - i)) - ); + validationID |= bytes32(uint256(uint8(input[i + 4])) << (8 * (31 - i))); } // Unpack the validity @@ -138,22 +133,20 @@ library StakingMessages { uint64 nonce, uint64 weight ) internal pure returns (bytes memory) { - return - abi.encodePacked( - StakingMessages.SET_SUBNET_VALIDATOR_WEIGHT_MESSAGE_TYPE_ID, - validationID, - nonce, - weight - ); + return abi.encodePacked( + StakingMessages.SET_SUBNET_VALIDATOR_WEIGHT_MESSAGE_TYPE_ID, validationID, nonce, weight + ); } /** * @notice Unpacks a byte array as a SetSubnetValidatorWeight message. * The message format specification is the same as the one used in above for packing. */ - function unpackSetSubnetValidatorWeightMessage( - bytes memory input - ) internal pure returns (bytes32, uint64, uint64) { + function unpackSetSubnetValidatorWeightMessage(bytes memory input) + internal + pure + returns (bytes32, uint64, uint64) + { require(input.length == 52, "StakingMessages: Invalid message length"); uint32 typeID; @@ -161,8 +154,7 @@ library StakingMessages { typeID := shr(224, mload(add(input, 0x20))) } require( - typeID == - StakingMessages.SET_SUBNET_VALIDATOR_WEIGHT_MESSAGE_TYPE_ID, + typeID == StakingMessages.SET_SUBNET_VALIDATOR_WEIGHT_MESSAGE_TYPE_ID, "StakingMessages: Invalid message type" ); @@ -192,9 +184,11 @@ library StakingMessages { * | 44 bytes | * +----------+ */ - function unpackValidationUptimeMessage( - bytes memory input - ) internal pure returns (bytes32, uint64) { + function unpackValidationUptimeMessage(bytes memory input) + internal + pure + returns (bytes32, uint64) + { require(input.length == 44, "StakingMessages: Invalid message length"); // Unpack the type ID. @@ -203,16 +197,13 @@ library StakingMessages { typeID |= uint32(uint8(input[i])) << uint32((8 * (3 - i))); } require( - typeID == VALIDATION_UPTIME_MESSAGE_TYPE_ID, - "StakingMessages: Invalid message type" + typeID == VALIDATION_UPTIME_MESSAGE_TYPE_ID, "StakingMessages: Invalid message type" ); // Unpack the validation ID. bytes32 validationID; for (uint256 i; i < 32; ++i) { - validationID |= bytes32( - uint256(uint8(input[i + 4])) << (8 * (31 - i)) - ); + validationID |= bytes32(uint256(uint8(input[i + 4])) << (8 * (31 - i))); } // Unpack the uptime. @@ -242,13 +233,12 @@ library StakingMessages { * | 144 bytes | * +-----------+ */ - function packValidationInfo( - ValidationInfo memory validationInfo - ) internal pure returns (bytes32, bytes memory) { - require( - validationInfo.signature.length == 64, - "StakingMessages: Invalid signature length" - ); + function packValidationInfo(ValidationInfo memory validationInfo) + internal + pure + returns (bytes32, bytes memory) + { + require(validationInfo.signature.length == 64, "StakingMessages: Invalid signature length"); bytes memory res = new bytes(144); // Pack the subnetID for (uint256 i; i < 32; ++i) { @@ -260,17 +250,11 @@ library StakingMessages { } // Pack the weight for (uint256 i; i < 8; ++i) { - res[i + 64] = bytes1( - uint8(validationInfo.weight >> uint8((8 * (7 - i)))) - ); + res[i + 64] = bytes1(uint8(validationInfo.weight >> uint8((8 * (7 - i))))); } // Pack the registration expiry for (uint256 i; i < 8; ++i) { - res[i + 72] = bytes1( - uint8( - validationInfo.registrationExpiry >> uint64((8 * (7 - i))) - ) - ); + res[i + 72] = bytes1(uint8(validationInfo.registrationExpiry >> uint64((8 * (7 - i))))); } // Pack the signature for (uint256 i; i < 64; ++i) { diff --git a/contracts/staking/tests/StakingMessages.t.sol b/contracts/staking/tests/StakingMessages.t.sol index be771e76f..6e63d8b26 100644 --- a/contracts/staking/tests/StakingMessages.t.sol +++ b/contracts/staking/tests/StakingMessages.t.sol @@ -15,17 +15,14 @@ contract StakingMessagesTest is Test { uint256 endGas; startGas = gasleft(); - bytes memory original = Original.packSetSubnetValidatorWeightMessage( - validationID, - nonce, - weight - ); + bytes memory original = + Original.packSetSubnetValidatorWeightMessage(validationID, nonce, weight); endGas = gasleft(); uint256 originalGas = startGas - endGas; startGas = gasleft(); - bytes memory packed = StakingMessages - .packSetSubnetValidatorWeightMessage(validationID, nonce, weight); + bytes memory packed = + StakingMessages.packSetSubnetValidatorWeightMessage(validationID, nonce, weight); endGas = gasleft(); // Doing this after the original will actually penalise it because // memory expansion is quadratic, so the gas saving is higher than the @@ -35,11 +32,8 @@ contract StakingMessagesTest is Test { assertEq(original, packed, "same data"); assertGe(originalGas - gas, 19_500, "gas saving"); - ( - bytes32 gotValidationID, - uint64 gotNonce, - uint64 gotWeight - ) = StakingMessages.unpackSetSubnetValidatorWeightMessage(packed); + (bytes32 gotValidationID, uint64 gotNonce, uint64 gotWeight) = + StakingMessages.unpackSetSubnetValidatorWeightMessage(packed); assertEq(validationID, gotValidationID, "validation ID"); assertEq(nonce, gotNonce, "nonce"); @@ -51,8 +45,8 @@ contract StakingMessagesTest is Test { uint64 nonce, uint64 weight ) public view { - bytes memory buffer = StakingMessages - .packSetSubnetValidatorWeightMessage(validationID, nonce, weight); + bytes memory buffer = + StakingMessages.packSetSubnetValidatorWeightMessage(validationID, nonce, weight); uint256 startGas; uint256 endGas; From d5f52daa101c41bf24ca168a4ed14a230a1dbd3f Mon Sep 17 00:00:00 2001 From: Arran Schlosberg Date: Tue, 6 Aug 2024 20:29:15 +0100 Subject: [PATCH 03/27] chore: `solhint-disable` assembly checks + some commentary --- contracts/staking/StakingMessages.sol | 15 +++++++++++++-- contracts/staking/tests/StakingMessages.t.sol | 2 ++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/contracts/staking/StakingMessages.sol b/contracts/staking/StakingMessages.sol index bc6a560f9..8dea31738 100644 --- a/contracts/staking/StakingMessages.sol +++ b/contracts/staking/StakingMessages.sol @@ -134,7 +134,7 @@ library StakingMessages { uint64 weight ) internal pure returns (bytes memory) { return abi.encodePacked( - StakingMessages.SET_SUBNET_VALIDATOR_WEIGHT_MESSAGE_TYPE_ID, validationID, nonce, weight + SET_SUBNET_VALIDATOR_WEIGHT_MESSAGE_TYPE_ID, validationID, nonce, weight ); } @@ -147,14 +147,20 @@ library StakingMessages { pure returns (bytes32, uint64, uint64) { + /* solhint-disable no-inline-assembly */ require(input.length == 52, "StakingMessages: Invalid message length"); + // A `bytes memory` is stored as one word representing the length and + // then the buffer of said length. Using the variable name in assembly + // is equivalent to a pointer to the length, and `add(input, 0x20)` + // points to the first word of the buffer. + uint32 typeID; assembly ("memory-safe") { typeID := shr(224, mload(add(input, 0x20))) } require( - typeID == StakingMessages.SET_SUBNET_VALIDATOR_WEIGHT_MESSAGE_TYPE_ID, + typeID == SET_SUBNET_VALIDATOR_WEIGHT_MESSAGE_TYPE_ID, "StakingMessages: Invalid message type" ); @@ -162,6 +168,10 @@ library StakingMessages { uint64 nonce; uint64 weight; assembly ("memory-safe") { + // Although we could achieve the entire unpacking with only two + // MLOADs, we'd have to stitch the `validationID` together and make + // everything less readable. It may even require _more_ gas because + // the MLOAD is so cheap. validationID := mload(add(input, 0x24)) let rest := mload(add(input, 0x44)) // only the first 128 bits are valid nonce := shr(192, rest) @@ -169,6 +179,7 @@ library StakingMessages { } return (validationID, nonce, weight); + /* solhint-enable no-inline-assembly */ } /** diff --git a/contracts/staking/tests/StakingMessages.t.sol b/contracts/staking/tests/StakingMessages.t.sol index 6e63d8b26..90a12c8af 100644 --- a/contracts/staking/tests/StakingMessages.t.sol +++ b/contracts/staking/tests/StakingMessages.t.sol @@ -31,6 +31,7 @@ contract StakingMessagesTest is Test { assertEq(original, packed, "same data"); assertGe(originalGas - gas, 19_500, "gas saving"); + assertLe(gas, 250, "gas cost"); (bytes32 gotValidationID, uint64 gotNonce, uint64 gotWeight) = StakingMessages.unpackSetSubnetValidatorWeightMessage(packed); @@ -62,5 +63,6 @@ contract StakingMessagesTest is Test { uint256 originalGas = startGas - endGas; assertGe(originalGas - gas, 18_000, "gas saving"); + assertLe(gas, 200, "gas cost"); } } From 1c94c271044f98c79319583141d7bc6249f00572 Mon Sep 17 00:00:00 2001 From: Arran Schlosberg Date: Fri, 9 Aug 2024 12:51:59 +0100 Subject: [PATCH 04/27] feat: generated code for `abi.encodePacked()` inversion --- contracts/staking/StakingMessages.sol | 138 ++------- contracts/staking/Unpack.sol | 143 +++++++++ contracts/staking/tests/StakingMessages.t.sol | 2 +- contracts/staking/tests/Unpack.t.sol | 83 +++++ contracts/staking/unpackgen.go | 3 + go.mod | 2 +- utils/unpack/Unpack.sol.gotmpl | 69 +++++ utils/unpack/Unpack.t.sol.gotmpl | 25 ++ utils/unpack/unpack.go | 284 ++++++++++++++++++ utils/unpack/unpackgen/unpackgen.go | 104 +++++++ 10 files changed, 742 insertions(+), 111 deletions(-) create mode 100644 contracts/staking/Unpack.sol create mode 100644 contracts/staking/tests/Unpack.t.sol create mode 100644 contracts/staking/unpackgen.go create mode 100644 utils/unpack/Unpack.sol.gotmpl create mode 100644 utils/unpack/Unpack.t.sol.gotmpl create mode 100644 utils/unpack/unpack.go create mode 100644 utils/unpack/unpackgen/unpackgen.go diff --git a/contracts/staking/StakingMessages.sol b/contracts/staking/StakingMessages.sol index 8dea31738..096d4f646 100644 --- a/contracts/staking/StakingMessages.sol +++ b/contracts/staking/StakingMessages.sol @@ -4,6 +4,8 @@ // SPDX-License-Identifier: Ecosystem pragma solidity 0.8.25; +import {Unpack} from "./Unpack.sol"; + library StakingMessages { // The information that uniquely identifies a subnet validation period. // The SHA-256 hash of the concatenation of these field is the validationID. @@ -48,25 +50,16 @@ library StakingMessages { * | 148 bytes | * +-----------+ */ - function packRegisterSubnetValidatorMessage(ValidationInfo memory valiationInfo) + function packRegisterSubnetValidatorMessage(ValidationInfo memory validationInfo) internal pure returns (bytes32, bytes memory) { - (bytes32 validationID, bytes memory serializedValidationInfo) = - packValidationInfo(valiationInfo); - - bytes memory res = new bytes(148); - // Pack the message type - for (uint256 i; i < 4; ++i) { - res[i] = bytes1(uint8(SUBNET_VALIDATOR_REGISTRATION_MESSAGE_TYPE_ID >> (8 * (3 - i)))); - } - // Pack the validation info - for (uint256 i; i < 144; ++i) { - res[i + 4] = serializedValidationInfo[i]; - } - - return (validationID, res); + (bytes32 validationID, bytes memory serialized) = packAndHashValidationInfo(validationInfo); + return ( + validationID, + abi.encodePacked(SUBNET_VALIDATOR_REGISTRATION_MESSAGE_TYPE_ID, serialized) + ); } /** @@ -89,28 +82,12 @@ library StakingMessages { pure returns (bytes32, bool) { - require(input.length == 37, "StakingMessages: Invalid message length"); - - // Unpack the type ID - uint32 typeID; - for (uint256 i; i < 4; ++i) { - typeID |= uint32(uint8(input[i])) << uint32((8 * (3 - i))); - } + (bytes4 typeID, bytes32 validationID, bytes1 valid) = Unpack.unpack_4_32_1(input); require( - typeID == SUBNET_VALIDATOR_REGISTRATION_MESSAGE_TYPE_ID, + uint32(typeID) == SUBNET_VALIDATOR_REGISTRATION_MESSAGE_TYPE_ID, "StakingMessages: Invalid message type" ); - - // Unpack the validation ID. - bytes32 validationID; - for (uint256 i; i < 32; ++i) { - validationID |= bytes32(uint256(uint8(input[i + 4])) << (8 * (31 - i))); - } - - // Unpack the validity - bool valid = input[36] != 0; - - return (validationID, valid); + return (validationID, uint8(valid) != 0); } /** @@ -147,39 +124,13 @@ library StakingMessages { pure returns (bytes32, uint64, uint64) { - /* solhint-disable no-inline-assembly */ - require(input.length == 52, "StakingMessages: Invalid message length"); - - // A `bytes memory` is stored as one word representing the length and - // then the buffer of said length. Using the variable name in assembly - // is equivalent to a pointer to the length, and `add(input, 0x20)` - // points to the first word of the buffer. - - uint32 typeID; - assembly ("memory-safe") { - typeID := shr(224, mload(add(input, 0x20))) - } + (bytes4 typeID, bytes32 validationID, bytes8 nonce, bytes8 weight) = + Unpack.unpack_4_32_8_8(input); require( - typeID == SET_SUBNET_VALIDATOR_WEIGHT_MESSAGE_TYPE_ID, + uint32(typeID) == SET_SUBNET_VALIDATOR_WEIGHT_MESSAGE_TYPE_ID, "StakingMessages: Invalid message type" ); - - bytes32 validationID; - uint64 nonce; - uint64 weight; - assembly ("memory-safe") { - // Although we could achieve the entire unpacking with only two - // MLOADs, we'd have to stitch the `validationID` together and make - // everything less readable. It may even require _more_ gas because - // the MLOAD is so cheap. - validationID := mload(add(input, 0x24)) - let rest := mload(add(input, 0x44)) // only the first 128 bits are valid - nonce := shr(192, rest) - weight := shr(192, shl(64, rest)) // shl(64, ) wipes the nonce - } - - return (validationID, nonce, weight); - /* solhint-enable no-inline-assembly */ + return (validationID, uint64(nonce), uint64(weight)); } /** @@ -200,30 +151,12 @@ library StakingMessages { pure returns (bytes32, uint64) { - require(input.length == 44, "StakingMessages: Invalid message length"); - - // Unpack the type ID. - uint32 typeID; - for (uint256 i; i < 4; ++i) { - typeID |= uint32(uint8(input[i])) << uint32((8 * (3 - i))); - } + (bytes4 typeID, bytes32 validationID, bytes8 uptime) = Unpack.unpack_4_32_8(input); require( - typeID == VALIDATION_UPTIME_MESSAGE_TYPE_ID, "StakingMessages: Invalid message type" + uint32(typeID) == VALIDATION_UPTIME_MESSAGE_TYPE_ID, + "StakingMessages: Invalid message type" ); - - // Unpack the validation ID. - bytes32 validationID; - for (uint256 i; i < 32; ++i) { - validationID |= bytes32(uint256(uint8(input[i + 4])) << (8 * (31 - i))); - } - - // Unpack the uptime. - uint64 uptime; - for (uint256 i; i < 8; ++i) { - uptime |= uint64(uint8(input[i + 36])) << uint64((8 * (7 - i))); - } - - return (validationID, uptime); + return (validationID, uint64(uptime)); } /** @@ -244,33 +177,20 @@ library StakingMessages { * | 144 bytes | * +-----------+ */ - function packValidationInfo(ValidationInfo memory validationInfo) + function packValidationInfo(ValidationInfo memory info) internal pure returns (bytes memory) { + require(info.signature.length == 64, "StakingMessages: Invalid signature length"); + return abi.encodePacked( + info.subnetID, info.nodeID, info.weight, info.registrationExpiry, info.signature + ); + } + + /// @dev Equivalent to returning `packValidationInfo(info)` and the SHA256 hash thereof. + function packAndHashValidationInfo(ValidationInfo memory info) internal pure returns (bytes32, bytes memory) { - require(validationInfo.signature.length == 64, "StakingMessages: Invalid signature length"); - bytes memory res = new bytes(144); - // Pack the subnetID - for (uint256 i; i < 32; ++i) { - res[i] = validationInfo.subnetID[i]; - } - // Pack the nodeID - for (uint256 i; i < 32; ++i) { - res[i + 32] = validationInfo.nodeID[i]; - } - // Pack the weight - for (uint256 i; i < 8; ++i) { - res[i + 64] = bytes1(uint8(validationInfo.weight >> uint8((8 * (7 - i))))); - } - // Pack the registration expiry - for (uint256 i; i < 8; ++i) { - res[i + 72] = bytes1(uint8(validationInfo.registrationExpiry >> uint64((8 * (7 - i))))); - } - // Pack the signature - for (uint256 i; i < 64; ++i) { - res[i + 80] = validationInfo.signature[i]; - } + bytes memory res = packValidationInfo(info); return (sha256(res), res); } } diff --git a/contracts/staking/Unpack.sol b/contracts/staking/Unpack.sol new file mode 100644 index 000000000..0286d1679 --- /dev/null +++ b/contracts/staking/Unpack.sol @@ -0,0 +1,143 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.0; + +// GENERATED CODE - Do not edit + +/* solhint-disable no-inline-assembly */ +/* solhint-disable func-name-mixedcase */ + +library Unpack { + /// @dev Thrown if the input buffer to an unpack function is of the wrong length. + error IncorrectInputLength(uint256 expected, uint256 actual); + + /// @dev Thrown if the input buffer to an unpack function with dynamically sized output is too short. + error InsufficientInputLength(uint256 min, uint256 actual); + + /** + * @notice Inverts `abi.encodePacked()` for the specific return types. + * @dev The originally packed inputs MUST be of the same types as those returned by this function, in the precise + * order, otherwise the output is undefined. + * @dev This function takes ownership of and corrupts the `input` parameter to avoid memory expansion for the + * returned `bytes memory`. The returned array is owned by the caller. + * @param input Buffer returned by `abi.encodePacked()` + */ + function unpack_4_32_32_8_8_Dyn_Destructive(bytes memory input) + internal + pure + returns (bytes4 v0, bytes32 v1, bytes32 v2, bytes8 v3, bytes8 v4, bytes memory v5) + { + if (input.length < 84) { + revert InsufficientInputLength(84, input.length); + } + + assembly ("memory-safe") { + v0 := mload(add(input, 0x20)) + v1 := mload(add(input, 0x24)) + v2 := mload(add(input, 0x44)) + v3 := mload(add(input, 0x64)) + v4 := mload(add(input, 0x6c)) + let length := mload(input) + let dynLength := sub(length, 84) + v5 := add(input, 84) + mstore(v5, dynLength) + let end := add(input, add(length, 0x20)) + } + } + + /** + * @notice Inverts `abi.encodePacked()` for the specific return types. + * @dev The originally packed inputs MUST be of the same types as those returned by this function, in the precise + * order, otherwise the output is undefined. + * @param input Buffer returned by `abi.encodePacked()` + */ + function unpack_4_32_1(bytes memory input) + internal + pure + returns (bytes4 v0, bytes32 v1, bytes1 v2) + { + if (input.length != 37) { + revert IncorrectInputLength(input.length, 37); + } + + assembly ("memory-safe") { + v0 := mload(add(input, 0x20)) + v1 := mload(add(input, 0x24)) + v2 := mload(add(input, 0x44)) + } + } + + /** + * @notice Inverts `abi.encodePacked()` for the specific return types. + * @dev The originally packed inputs MUST be of the same types as those returned by this function, in the precise + * order, otherwise the output is undefined. + * @param input Buffer returned by `abi.encodePacked()` + */ + function unpack_4_32_8_8(bytes memory input) + internal + pure + returns (bytes4 v0, bytes32 v1, bytes8 v2, bytes8 v3) + { + if (input.length != 52) { + revert IncorrectInputLength(input.length, 52); + } + + assembly ("memory-safe") { + v0 := mload(add(input, 0x20)) + v1 := mload(add(input, 0x24)) + v2 := mload(add(input, 0x44)) + v3 := mload(add(input, 0x4c)) + } + } + + /** + * @notice Inverts `abi.encodePacked()` for the specific return types. + * @dev The originally packed inputs MUST be of the same types as those returned by this function, in the precise + * order, otherwise the output is undefined. + * @param input Buffer returned by `abi.encodePacked()` + */ + function unpack_4_32_8(bytes memory input) + internal + pure + returns (bytes4 v0, bytes32 v1, bytes8 v2) + { + if (input.length != 44) { + revert IncorrectInputLength(input.length, 44); + } + + assembly ("memory-safe") { + v0 := mload(add(input, 0x20)) + v1 := mload(add(input, 0x24)) + v2 := mload(add(input, 0x44)) + } + } + + /** + * @notice Inverts `abi.encodePacked()` for the specific return types. + * @dev The originally packed inputs MUST be of the same types as those returned by this function, in the precise + * order, otherwise the output is undefined. + * @dev This function takes ownership of and corrupts the `input` parameter to avoid memory expansion for the + * returned `bytes memory`. The returned array is owned by the caller. + * @param input Buffer returned by `abi.encodePacked()` + */ + function unpack_32_32_8_8_Dyn_Destructive(bytes memory input) + internal + pure + returns (bytes32 v0, bytes32 v1, bytes8 v2, bytes8 v3, bytes memory v4) + { + if (input.length < 80) { + revert InsufficientInputLength(80, input.length); + } + + assembly ("memory-safe") { + v0 := mload(add(input, 0x20)) + v1 := mload(add(input, 0x40)) + v2 := mload(add(input, 0x60)) + v3 := mload(add(input, 0x68)) + let length := mload(input) + let dynLength := sub(length, 80) + v4 := add(input, 80) + mstore(v4, dynLength) + let end := add(input, add(length, 0x20)) + } + } +} diff --git a/contracts/staking/tests/StakingMessages.t.sol b/contracts/staking/tests/StakingMessages.t.sol index 90a12c8af..46c18616a 100644 --- a/contracts/staking/tests/StakingMessages.t.sol +++ b/contracts/staking/tests/StakingMessages.t.sol @@ -63,6 +63,6 @@ contract StakingMessagesTest is Test { uint256 originalGas = startGas - endGas; assertGe(originalGas - gas, 18_000, "gas saving"); - assertLe(gas, 200, "gas cost"); + assertLe(gas, 350, "gas cost"); } } diff --git a/contracts/staking/tests/Unpack.t.sol b/contracts/staking/tests/Unpack.t.sol new file mode 100644 index 000000000..eae08ddc1 --- /dev/null +++ b/contracts/staking/tests/Unpack.t.sol @@ -0,0 +1,83 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.0; + +// GENERATED CODE - Do not edit + +import {Test} from "@forge-std/Test.sol"; +import {console} from "@forge-std/console.sol"; +import {Unpack} from "../Unpack.sol"; + +/* solhint-disable func-name-mixedcase */ + +contract UnpackTest is Test { + function testUnpack_4_32_32_8_8_Dyn_Destructive( + bytes4 v0, + bytes32 v1, + bytes32 v2, + bytes8 v3, + bytes8 v4, + bytes memory v5 + ) external pure { + bytes memory packed = abi.encodePacked(v0, v1, v2, v3, v4, v5); + console.logBytes(packed); + + (bytes4 got0, bytes32 got1, bytes32 got2, bytes8 got3, bytes8 got4, bytes memory got5) = + Unpack.unpack_4_32_32_8_8_Dyn_Destructive(packed); + assertEq(v0, got0, "output[0] bytes4"); + assertEq(v1, got1, "output[1] bytes32"); + assertEq(v2, got2, "output[2] bytes32"); + assertEq(v3, got3, "output[3] bytes8"); + assertEq(v4, got4, "output[4] bytes8"); + assertEq(v5, got5, "output[5] bytes memory"); + } + + function testUnpack_4_32_1(bytes4 v0, bytes32 v1, bytes1 v2) external pure { + bytes memory packed = abi.encodePacked(v0, v1, v2); + console.logBytes(packed); + + (bytes4 got0, bytes32 got1, bytes1 got2) = Unpack.unpack_4_32_1(packed); + assertEq(v0, got0, "output[0] bytes4"); + assertEq(v1, got1, "output[1] bytes32"); + assertEq(v2, got2, "output[2] bytes1"); + } + + function testUnpack_4_32_8_8(bytes4 v0, bytes32 v1, bytes8 v2, bytes8 v3) external pure { + bytes memory packed = abi.encodePacked(v0, v1, v2, v3); + console.logBytes(packed); + + (bytes4 got0, bytes32 got1, bytes8 got2, bytes8 got3) = Unpack.unpack_4_32_8_8(packed); + assertEq(v0, got0, "output[0] bytes4"); + assertEq(v1, got1, "output[1] bytes32"); + assertEq(v2, got2, "output[2] bytes8"); + assertEq(v3, got3, "output[3] bytes8"); + } + + function testUnpack_4_32_8(bytes4 v0, bytes32 v1, bytes8 v2) external pure { + bytes memory packed = abi.encodePacked(v0, v1, v2); + console.logBytes(packed); + + (bytes4 got0, bytes32 got1, bytes8 got2) = Unpack.unpack_4_32_8(packed); + assertEq(v0, got0, "output[0] bytes4"); + assertEq(v1, got1, "output[1] bytes32"); + assertEq(v2, got2, "output[2] bytes8"); + } + + function testUnpack_32_32_8_8_Dyn_Destructive( + bytes32 v0, + bytes32 v1, + bytes8 v2, + bytes8 v3, + bytes memory v4 + ) external pure { + bytes memory packed = abi.encodePacked(v0, v1, v2, v3, v4); + console.logBytes(packed); + + (bytes32 got0, bytes32 got1, bytes8 got2, bytes8 got3, bytes memory got4) = + Unpack.unpack_32_32_8_8_Dyn_Destructive(packed); + assertEq(v0, got0, "output[0] bytes32"); + assertEq(v1, got1, "output[1] bytes32"); + assertEq(v2, got2, "output[2] bytes8"); + assertEq(v3, got3, "output[3] bytes8"); + assertEq(v4, got4, "output[4] bytes memory"); + } +} diff --git a/contracts/staking/unpackgen.go b/contracts/staking/unpackgen.go new file mode 100644 index 000000000..57ab6fe9d --- /dev/null +++ b/contracts/staking/unpackgen.go @@ -0,0 +1,3 @@ +package staking + +//go:generate go run ../../utils/unpack/unpackgen --out=./Unpack.sol --test_out=./tests/Unpack.t.sol --byte_sizes=4,32,32,8,8,0;4,32,1;4,32,8,8;4,32,8;32,32,8,8,0 diff --git a/go.mod b/go.mod index 315e1f355..1f443f063 100644 --- a/go.mod +++ b/go.mod @@ -14,6 +14,7 @@ require ( github.com/onsi/gomega v1.34.1 github.com/pkg/errors v0.9.1 github.com/spf13/cobra v1.8.1 + github.com/spf13/pflag v1.0.5 github.com/stretchr/testify v1.9.0 go.uber.org/zap v1.27.0 ) @@ -108,7 +109,6 @@ require ( github.com/spf13/afero v1.9.5 // indirect github.com/spf13/cast v1.5.1 // indirect github.com/spf13/jwalterweatherman v1.1.0 // indirect - github.com/spf13/pflag v1.0.5 // indirect github.com/spf13/viper v1.16.0 // indirect github.com/status-im/keycard-go v0.2.0 // indirect github.com/subosito/gotenv v1.4.2 // indirect diff --git a/utils/unpack/Unpack.sol.gotmpl b/utils/unpack/Unpack.sol.gotmpl new file mode 100644 index 000000000..a8bf9d0d9 --- /dev/null +++ b/utils/unpack/Unpack.sol.gotmpl @@ -0,0 +1,69 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^{{if false}}0.8.25{{else}}0.8.0{{end}}; + +// GENERATED CODE - Do not edit + +/* solhint-disable no-inline-assembly */ +/* solhint-disable func-name-mixedcase */ + +library Unpack { + /// @dev Thrown if the input buffer to an unpack function is of the wrong length. + error IncorrectInputLength(uint256 expected, uint256 actual); + + /// @dev Thrown if the input buffer to an unpack function with dynamically sized output is too short. + error InsufficientInputLength(uint256 min, uint256 actual); + {{- range .Unpackers}} + + /** + * @notice Inverts `abi.encodePacked()` for the specific return types. + * @dev The originally packed inputs MUST be of the same types as those returned by this function, in the precise + * order, otherwise the output is undefined. + {{- if .HasDynamic}} + {{- if .UseMCopy}} + * @dev The returned `bytes memory` is freshly allocated, resulting in a memory expansion. + {{- else}} + * @dev This function takes ownership of and corrupts the `input` parameter to avoid memory expansion for the + * returned `bytes memory`. The returned array is owned by the caller. + {{- end}} + {{- end}} + * @param input Buffer returned by `abi.encodePacked()` + */ + function unpack_{{.FuncNameSuffix}}(bytes memory input) internal pure returns ({{.Returns}}) { + {{- $unpacker := .}} + {{- if .HasDynamic}} + if (input.length < {{.MinLength}}) { + revert InsufficientInputLength({{.MinLength}}, input.length); + } + {{- else}} + if (input.length != {{.BytesUntilDynamic}}) { + revert IncorrectInputLength(input.length, {{.Bytes}}); + } + {{- end}} + + assembly ("memory-safe") { + {{- range $i, $v := .Vars}} + {{- if .Dynamic}} + let length := mload(input) + let dynLength := sub(length, {{$unpacker.MinLength}}) + {{- if $unpacker.UseMCopy}} + v{{$i}} := mload(0x40) + mstore(0x40, add(v{{$i}}, add(0x20, dynLength))) + mstore(v{{$i}}, dynLength) + mcopy(add(v{{$i}}, 0x20), add(input, {{.OffsetHex}}), dynLength) + {{- else}} + v{{$i}} := add(input, {{.Offset}}) + mstore(v{{$i}}, dynLength) + {{- end}} + let end := add(input, add(length, 0x20)) + {{- else}} + {{- if .Front}} + v{{$i}} := mload(add(input, {{.OffsetHex}})) + {{- else}} + v{{$i}} := mload(sub(end, {{.OffsetHex}})) + {{- end}} + {{- end}} + {{- end}} + } + } + {{- end}} +} diff --git a/utils/unpack/Unpack.t.sol.gotmpl b/utils/unpack/Unpack.t.sol.gotmpl new file mode 100644 index 000000000..2b2bf6148 --- /dev/null +++ b/utils/unpack/Unpack.t.sol.gotmpl @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^{{if false}}0.8.25{{else}}0.8.0{{end}}; + +// GENERATED CODE - Do not edit + +import {Test} from "@forge-std/Test.sol"; +import {console} from "@forge-std/console.sol"; +import {Unpack} from "{{.RelPathFromTestToImpl}}"; + +/* solhint-disable func-name-mixedcase */ + +contract UnpackTest is Test { + {{- range .Unpackers}} + + function testUnpack_{{.FuncNameSuffix}}({{.Returns}}) external pure { + bytes memory packed = abi.encodePacked({{.EncodePackedArgs}}); + console.logBytes(packed); + + ({{.TestVars}}) = Unpack.unpack_{{.FuncNameSuffix}}(packed); + {{- range $i, $v := .Vars}} + assertEq(v{{$i}}, got{{$i}}, "output[{{$i}}] {{.Type}}"); + {{- end}} + } + {{- end}} +} diff --git a/utils/unpack/unpack.go b/utils/unpack/unpack.go new file mode 100644 index 000000000..b13d92da4 --- /dev/null +++ b/utils/unpack/unpack.go @@ -0,0 +1,284 @@ +// Package unpack generates Solidity code to invert `abi.encodePacked()` for +// known, unambiguous output sizes. +package unpack + +import ( + "errors" + "fmt" + "io" + "math" + "strings" + "text/template" + + _ "embed" +) + +var ( + //go:embed Unpack.sol.gotmpl + solTmplRaw string + //go:embed Unpack.t.sol.gotmpl + solTestTmplRaw string + solTmpl, solTestTmpl *template.Template +) + +func init() { + solTmpl = template.Must(template.New("sol").Parse(solTmplRaw)) + solTestTmpl = template.Must(template.New("solTest").Parse(solTestTmplRaw)) +} + +// Errors returned by [Generate]. +var ( + ErrZeroBytes = errors.New("zero bytes") + ErrMax32Bytes = errors.New("max 32 bytes") + ErrMultipleDynamic = errors.New("multiple unsized inputs") +) + +// Dynamic is a sentinel value, used instead of a number of bytes, indicating +// that an unpacked type has dynamic length. At most one Dynamic value can be +// used per generated unpack function. +const Dynamic = math.MaxUint + +// Generate generates implementations and tests for unpacking Solidity values +// encoded with `abi.encodePacked()`. Each slice of `[]uint` results in the +// generation of one `unpack_...()` function and MAY have at most one [Dynamic] +// size. +func Generate(impl, test io.Writer, relPathFromTestToImpl string, bytes ...[]uint) error { + us := make([]*unpacker, len(bytes)) + for i, bs := range bytes { + u, err := newUnpacker(bs...) + if err != nil { + return err + } + us[i] = u + } + + data := tmplData{ + RelPathFromTestToImpl: relPathFromTestToImpl, + Unpackers: us, + } + return errors.Join( + solTmpl.Execute(impl, data), + solTestTmpl.Execute(test, data), + ) +} + +type tmplData struct { + RelPathFromTestToImpl string + Unpackers []*unpacker +} + +// An unpacker defines all values required to generate a single `unpack_...()` +// function. +type unpacker struct { + Vars []output + HasDynamic bool + UseMCopy bool +} + +// An output defines a single output returned by an `unpack_...()` function. +type output struct { + end end + Offset uint // relative to `end` + Len uint // non-zero if `!Dynamic` + Dynamic bool +} + +type end uint + +const ( + front end = iota + 1 + back +) + +func newUnpacker(bytes ...uint) (*unpacker, error) { + u := &unpacker{ + Vars: make([]output, len(bytes)), + } + + for i, b := range bytes { + switch { + case b == 0: + return nil, ErrZeroBytes + case b == Dynamic: + if u.HasDynamic { + return nil, ErrMultipleDynamic + } + u.HasDynamic = true + case b > 32: + return nil, ErrMax32Bytes + } + + v := &u.Vars[i] + switch { + case b == Dynamic: + v.end = front + v.Offset = u.BytesUntilDynamic() + v.Dynamic = true + + case !u.HasDynamic: + v.end = front + v.Offset = u.BytesUntilDynamic() + + case u.HasDynamic: + v.end = back + + } + v.Len = b + } + if !u.HasDynamic { + return u, nil + } + + // Once a dynamically sized output exists, we can no longer calculate + // offsets from the front. + var offset uint + for i := len(u.Vars) - 1; i >= 0; i-- { + v := &u.Vars[i] + if v.Dynamic { + break + } + offset += v.Len + v.Offset = offset + } + return u, nil +} + +// UsesMCopy returns whether at least one unpack function uses the MCOPY op +// code. +func (d *tmplData) UsesMCopy() bool { + for _, u := range d.Unpackers { + if u.UseMCopy { + return true + } + } + return false +} + +// BytesUntilDynamic returns the total number of bytes before the first +// dynamically sized output, or until the end of the input buffer if all sizes +// are known in advance. +// +// While an `unpacker` is being constructed, this function returns only the +// already-parsed output sizes, which can be used for setting the offset of the +// next value. +func (u *unpacker) BytesUntilDynamic() uint { + var l uint + for _, v := range u.Vars { + if v.Dynamic { + break + } + l += v.Len + } + return l +} + +// Bytes is an alias of [BytesUntilDynamic] to aid in readability of the +// template. +func (u *unpacker) Bytes() uint { + return u.BytesUntilDynamic() +} + +// MinLength returns the minimum number of bytes that an input buffer MUST have +// to be unpacked. This is the sum of all non-dynamically sized outputs. +func (u *unpacker) MinLength() uint { + var n uint + for _, v := range u.Vars { + if !v.Dynamic { + n += v.Len + } + } + return n +} + +// mapVar maps u.Vars -> []string. +func (u *unpacker) mapVars(fn func(int, output) string) []string { + out := make([]string, len(u.Vars)) + for i, v := range u.Vars { + out[i] = fn(i, v) + } + return out +} + +// FuncNameSuffix returns the suffix appended to `unpack_` when naming the +// generated function. It concatenates all byte sizes, using the keyword "Dyn" +// for dynamically sized outputs. +// +// If the generated code doesn't use MCOPY it takes ownership of the input +// buffer in a destructive fashion. All such functions have the "_Destructive" +// suffix appended. +func (u *unpacker) FuncNameSuffix() string { + base := strings.Join( + u.mapVars(func(_ int, o output) string { + if o.Dynamic { + return "Dyn" + } + return fmt.Sprintf("%d", o.Len) + }), + "_", + ) + if !u.HasDynamic || u.UseMCopy { + return base + } + return fmt.Sprintf("%s_Destructive", base) +} + +// varPrefix is the prefix of all numerically identified variables in the +// generated code; i.e. for prefix v, the variables are v0, v1, v2... +const varPrefix = "v" + +// EncodePackedArgs returns the arguments to be passed to `abi.encodePacked()` +// in the generated test. +func (u *unpacker) EncodePackedArgs() string { + return strings.Join( + u.mapVars(func(i int, _ output) string { + return fmt.Sprintf("%s%d", varPrefix, i) + }), + ", ", + ) +} + +// Returns returns the return values of the generated unpack function. +func (u *unpacker) Returns() string { + return u.typedVars(varPrefix) +} + +// TestVars returns the variables under test in the generated test function. +func (u *unpacker) TestVars() string { + return u.typedVars("got") +} + +func (u *unpacker) typedVars(prefix string) string { + return strings.Join( + u.mapVars(func(i int, o output) string { + return fmt.Sprintf("%s %s%d", o.Type(), prefix, i) + }), + ", ", + ) +} + +// Type returns the Solidity type of the output variable. +func (o *output) Type() string { + if o.Dynamic { + return "bytes memory" + } + return fmt.Sprintf("bytes%d", o.Len) +} + +func (o *output) Front() bool { + switch o.end { + case front: + return true + case back: + return false + default: + panic(fmt.Sprintf("BUG: %T.end not set", o)) + } +} + +func (o *output) OffsetHex() string { + off := o.Offset + if o.end == front { + off += 32 + } + return fmt.Sprintf("%#02x", off) +} diff --git a/utils/unpack/unpackgen/unpackgen.go b/utils/unpack/unpackgen/unpackgen.go new file mode 100644 index 000000000..bf3dec327 --- /dev/null +++ b/utils/unpack/unpackgen/unpackgen.go @@ -0,0 +1,104 @@ +// The unpackgen binary generates Solidity code to invert `abi.encodePacked()` +// for known, unambiguous output sizes. See the [unpack] package for details. +package main + +import ( + "errors" + "fmt" + "os" + "path/filepath" + "strconv" + "strings" + + "github.com/spf13/pflag" + + "github.com/ava-labs/teleporter/utils/unpack" +) + +func main() { + implPath := pflag.String("out", "./Unpack.sol", "Output path to which the Solidity implementations are written") + testPath := pflag.String("test_out", "./Unpack.t.sol", "Output path to which the Solidity tests are written") + bytes := new(bytesFlag) + pflag.Var(bytes, "byte_sizes", "Semicolon-delimited list of groups of comma-delimited byte sizes. Use 0 for (at most one) dynamically sized byte array per group.") + + pflag.Parse() + + if err := run(*implPath, *testPath, bytes.val); err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } +} + +// run creates files at both paths and then calls `unpack.Generate()`. +func run(implPath, testPath string, bytes [][]uint) error { + impl, err := os.Create(implPath) + if err != nil { + return err + } + test, err := os.Create(testPath) + if err != nil { + return err + } + + rel, err := filepath.Rel(filepath.Dir(testPath), implPath) + if err != nil { + return fmt.Errorf("determine path from test to implementation: %v", err) + } + + if err := unpack.Generate(impl, test, rel, bytes...); err != nil { + return err + } + return errors.Join(impl.Close(), test.Close()) +} + +type bytesFlag struct { + val [][]uint +} + +var _ pflag.Value = (*bytesFlag)(nil) + +// Set splits `s` by semicolons then splits each result by commas, parsing all +// resulting values as uints. It trims whitespace. If a parsed value is 0 it is +// replaced with unpack.Dynamic. +func (f *bytesFlag) Set(s string) error { + groups := strings.Split(s, ";") + var val [][]uint + + for _, g := range groups { + var bytes []uint + for _, bStr := range strings.Split(g, ",") { + b, err := strconv.ParseUint(strings.TrimSpace(bStr), 10, 32) + if err != nil { + return err + } + if b == 0 { + b = unpack.Dynamic + } + bytes = append(bytes, uint(b)) + } + val = append(val, bytes) + } + + f.val = val + return nil +} + +// String is the inverse of `bytesFlag.Set()`. +func (f *bytesFlag) String() string { + var parts []string + for _, grp := range f.val { + var vs []string + for _, v := range grp { + if v == unpack.Dynamic { + v = 0 + } + vs = append(vs, fmt.Sprintf("%d", v)) + } + parts = append(parts, strings.Join(vs, ",")) + } + return strings.Join(parts, ";") +} + +func (f *bytesFlag) Type() string { + return fmt.Sprintf("%T", *f) +} From c89bd4aaad5ffe2ca97700773a465ef88aeb9a43 Mon Sep 17 00:00:00 2001 From: Arran Schlosberg Date: Fri, 9 Aug 2024 13:45:32 +0100 Subject: [PATCH 05/27] fix: `solc` pragma `^0.8.0` unless using `mcopy` then `^0.8.25` --- utils/unpack/Unpack.sol.gotmpl | 2 +- utils/unpack/Unpack.t.sol.gotmpl | 2 +- utils/unpack/unpack.go | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/utils/unpack/Unpack.sol.gotmpl b/utils/unpack/Unpack.sol.gotmpl index a8bf9d0d9..76dd1ae0d 100644 --- a/utils/unpack/Unpack.sol.gotmpl +++ b/utils/unpack/Unpack.sol.gotmpl @@ -1,5 +1,5 @@ // SPDX-License-Identifier: UNLICENSED -pragma solidity ^{{if false}}0.8.25{{else}}0.8.0{{end}}; +pragma solidity ^{{if .UsesMCopy}}0.8.25{{else}}0.8.0{{end}}; // GENERATED CODE - Do not edit diff --git a/utils/unpack/Unpack.t.sol.gotmpl b/utils/unpack/Unpack.t.sol.gotmpl index 2b2bf6148..1501c0ef7 100644 --- a/utils/unpack/Unpack.t.sol.gotmpl +++ b/utils/unpack/Unpack.t.sol.gotmpl @@ -1,5 +1,5 @@ // SPDX-License-Identifier: UNLICENSED -pragma solidity ^{{if false}}0.8.25{{else}}0.8.0{{end}}; +pragma solidity ^{{if .UsesMCopy}}0.8.25{{else}}0.8.0{{end}}; // GENERATED CODE - Do not edit diff --git a/utils/unpack/unpack.go b/utils/unpack/unpack.go index b13d92da4..8a4f86824 100644 --- a/utils/unpack/unpack.go +++ b/utils/unpack/unpack.go @@ -52,7 +52,7 @@ func Generate(impl, test io.Writer, relPathFromTestToImpl string, bytes ...[]uin us[i] = u } - data := tmplData{ + data := &tmplData{ RelPathFromTestToImpl: relPathFromTestToImpl, Unpackers: us, } From dac07fc112650695ac184e4264533f6af79264a4 Mon Sep 17 00:00:00 2001 From: Arran Schlosberg Date: Fri, 9 Aug 2024 13:50:52 +0100 Subject: [PATCH 06/27] fix: remove unused variable when dynamically sized at end --- contracts/staking/Unpack.sol | 2 -- utils/unpack/Unpack.sol.gotmpl | 2 ++ utils/unpack/unpack.go | 4 ++++ 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/contracts/staking/Unpack.sol b/contracts/staking/Unpack.sol index 0286d1679..adbf8b83e 100644 --- a/contracts/staking/Unpack.sol +++ b/contracts/staking/Unpack.sol @@ -40,7 +40,6 @@ library Unpack { let dynLength := sub(length, 84) v5 := add(input, 84) mstore(v5, dynLength) - let end := add(input, add(length, 0x20)) } } @@ -137,7 +136,6 @@ library Unpack { let dynLength := sub(length, 80) v4 := add(input, 80) mstore(v4, dynLength) - let end := add(input, add(length, 0x20)) } } } diff --git a/utils/unpack/Unpack.sol.gotmpl b/utils/unpack/Unpack.sol.gotmpl index 76dd1ae0d..76058fad9 100644 --- a/utils/unpack/Unpack.sol.gotmpl +++ b/utils/unpack/Unpack.sol.gotmpl @@ -54,7 +54,9 @@ library Unpack { v{{$i}} := add(input, {{.Offset}}) mstore(v{{$i}}, dynLength) {{- end}} + {{- if not ($unpacker.IsLastVar $i)}} let end := add(input, add(length, 0x20)) + {{- end}} {{- else}} {{- if .Front}} v{{$i}} := mload(add(input, {{.OffsetHex}})) diff --git a/utils/unpack/unpack.go b/utils/unpack/unpack.go index 8a4f86824..e3bb64993 100644 --- a/utils/unpack/unpack.go +++ b/utils/unpack/unpack.go @@ -222,6 +222,10 @@ func (u *unpacker) FuncNameSuffix() string { return fmt.Sprintf("%s_Destructive", base) } +func (u *unpacker) IsLastVar(i int) bool { + return i >= len(u.Vars)-1 +} + // varPrefix is the prefix of all numerically identified variables in the // generated code; i.e. for prefix v, the variables are v0, v1, v2... const varPrefix = "v" From c3ac02ac5206709c40b39e2d46daeb2e7d655890 Mon Sep 17 00:00:00 2001 From: Arran Schlosberg Date: Fri, 9 Aug 2024 13:52:40 +0100 Subject: [PATCH 07/27] chore: add copyright notices --- contracts/staking/Unpack.sol | 2 ++ contracts/staking/tests/Unpack.t.sol | 2 ++ utils/unpack/Unpack.sol.gotmpl | 2 ++ utils/unpack/Unpack.t.sol.gotmpl | 2 ++ utils/unpack/unpack.go | 3 +++ utils/unpack/unpackgen/unpackgen.go | 3 +++ 6 files changed, 14 insertions(+) diff --git a/contracts/staking/Unpack.sol b/contracts/staking/Unpack.sol index adbf8b83e..773286398 100644 --- a/contracts/staking/Unpack.sol +++ b/contracts/staking/Unpack.sol @@ -1,3 +1,5 @@ +// (c) 2024, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. // SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.0; diff --git a/contracts/staking/tests/Unpack.t.sol b/contracts/staking/tests/Unpack.t.sol index eae08ddc1..1d89d3e93 100644 --- a/contracts/staking/tests/Unpack.t.sol +++ b/contracts/staking/tests/Unpack.t.sol @@ -1,3 +1,5 @@ +// (c) 2024, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. // SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.0; diff --git a/utils/unpack/Unpack.sol.gotmpl b/utils/unpack/Unpack.sol.gotmpl index 76058fad9..ca7384c5e 100644 --- a/utils/unpack/Unpack.sol.gotmpl +++ b/utils/unpack/Unpack.sol.gotmpl @@ -1,3 +1,5 @@ +// (c) 2024, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. // SPDX-License-Identifier: UNLICENSED pragma solidity ^{{if .UsesMCopy}}0.8.25{{else}}0.8.0{{end}}; diff --git a/utils/unpack/Unpack.t.sol.gotmpl b/utils/unpack/Unpack.t.sol.gotmpl index 1501c0ef7..70915712d 100644 --- a/utils/unpack/Unpack.t.sol.gotmpl +++ b/utils/unpack/Unpack.t.sol.gotmpl @@ -1,3 +1,5 @@ +// (c) 2024, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. // SPDX-License-Identifier: UNLICENSED pragma solidity ^{{if .UsesMCopy}}0.8.25{{else}}0.8.0{{end}}; diff --git a/utils/unpack/unpack.go b/utils/unpack/unpack.go index e3bb64993..b8d1710e8 100644 --- a/utils/unpack/unpack.go +++ b/utils/unpack/unpack.go @@ -1,3 +1,6 @@ +// (c) 2024, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. +// // Package unpack generates Solidity code to invert `abi.encodePacked()` for // known, unambiguous output sizes. package unpack diff --git a/utils/unpack/unpackgen/unpackgen.go b/utils/unpack/unpackgen/unpackgen.go index bf3dec327..c2127f405 100644 --- a/utils/unpack/unpackgen/unpackgen.go +++ b/utils/unpack/unpackgen/unpackgen.go @@ -1,3 +1,6 @@ +// (c) 2024, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. +// // The unpackgen binary generates Solidity code to invert `abi.encodePacked()` // for known, unambiguous output sizes. See the [unpack] package for details. package main From e2645723a71a42c584717874c1212fb2e4f71c72 Mon Sep 17 00:00:00 2001 From: Arran Schlosberg Date: Fri, 9 Aug 2024 14:20:02 +0100 Subject: [PATCH 08/27] chore: placate the linters... ssshhhhh --- contracts/staking/Unpack.sol | 7 ++++--- contracts/staking/tests/Unpack.t.sol | 8 +++++--- utils/unpack/Unpack.sol.gotmpl | 7 ++++--- utils/unpack/Unpack.t.sol.gotmpl | 8 +++++--- utils/unpack/unpack.go | 1 - 5 files changed, 18 insertions(+), 13 deletions(-) diff --git a/contracts/staking/Unpack.sol b/contracts/staking/Unpack.sol index 773286398..e427dd023 100644 --- a/contracts/staking/Unpack.sol +++ b/contracts/staking/Unpack.sol @@ -1,12 +1,13 @@ // (c) 2024, Ava Labs, Inc. All rights reserved. // See the file LICENSE for licensing terms. // SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.8.0; +pragma solidity ^0.8.0; // solhint-disable-line compiler-version // GENERATED CODE - Do not edit -/* solhint-disable no-inline-assembly */ -/* solhint-disable func-name-mixedcase */ +// solhint-disable no-inline-assembly +// Mixed-case can't apply to numbers and an underscore is the most natural separator +// solhint-disable func-name-mixedcase library Unpack { /// @dev Thrown if the input buffer to an unpack function is of the wrong length. diff --git a/contracts/staking/tests/Unpack.t.sol b/contracts/staking/tests/Unpack.t.sol index 1d89d3e93..08fa62838 100644 --- a/contracts/staking/tests/Unpack.t.sol +++ b/contracts/staking/tests/Unpack.t.sol @@ -1,16 +1,18 @@ // (c) 2024, Ava Labs, Inc. All rights reserved. // See the file LICENSE for licensing terms. // SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.8.0; +pragma solidity ^0.8.0; // solhint-disable-line compiler-version // GENERATED CODE - Do not edit +// Console logging is useful for debug information in _tests_. +// solhint-disable no-console +// solhint-disable func-name-mixedcase + import {Test} from "@forge-std/Test.sol"; import {console} from "@forge-std/console.sol"; import {Unpack} from "../Unpack.sol"; -/* solhint-disable func-name-mixedcase */ - contract UnpackTest is Test { function testUnpack_4_32_32_8_8_Dyn_Destructive( bytes4 v0, diff --git a/utils/unpack/Unpack.sol.gotmpl b/utils/unpack/Unpack.sol.gotmpl index ca7384c5e..298e38957 100644 --- a/utils/unpack/Unpack.sol.gotmpl +++ b/utils/unpack/Unpack.sol.gotmpl @@ -1,12 +1,13 @@ // (c) 2024, Ava Labs, Inc. All rights reserved. // See the file LICENSE for licensing terms. // SPDX-License-Identifier: UNLICENSED -pragma solidity ^{{if .UsesMCopy}}0.8.25{{else}}0.8.0{{end}}; +pragma solidity ^{{if .UsesMCopy}}0.8.25{{else}}0.8.0{{end}}; // solhint-disable-line compiler-version // GENERATED CODE - Do not edit -/* solhint-disable no-inline-assembly */ -/* solhint-disable func-name-mixedcase */ +// solhint-disable no-inline-assembly +// Mixed-case can't apply to numbers and an underscore is the most natural separator +// solhint-disable func-name-mixedcase library Unpack { /// @dev Thrown if the input buffer to an unpack function is of the wrong length. diff --git a/utils/unpack/Unpack.t.sol.gotmpl b/utils/unpack/Unpack.t.sol.gotmpl index 70915712d..47f3f3657 100644 --- a/utils/unpack/Unpack.t.sol.gotmpl +++ b/utils/unpack/Unpack.t.sol.gotmpl @@ -1,16 +1,18 @@ // (c) 2024, Ava Labs, Inc. All rights reserved. // See the file LICENSE for licensing terms. // SPDX-License-Identifier: UNLICENSED -pragma solidity ^{{if .UsesMCopy}}0.8.25{{else}}0.8.0{{end}}; +pragma solidity ^{{if .UsesMCopy}}0.8.25{{else}}0.8.0{{end}}; // solhint-disable-line compiler-version // GENERATED CODE - Do not edit +// Console logging is useful for debug information in _tests_. +// solhint-disable no-console +// solhint-disable func-name-mixedcase + import {Test} from "@forge-std/Test.sol"; import {console} from "@forge-std/console.sol"; import {Unpack} from "{{.RelPathFromTestToImpl}}"; -/* solhint-disable func-name-mixedcase */ - contract UnpackTest is Test { {{- range .Unpackers}} diff --git a/utils/unpack/unpack.go b/utils/unpack/unpack.go index b8d1710e8..07162c341 100644 --- a/utils/unpack/unpack.go +++ b/utils/unpack/unpack.go @@ -124,7 +124,6 @@ func newUnpacker(bytes ...uint) (*unpacker, error) { case u.HasDynamic: v.end = back - } v.Len = b } From 7f0bd2e7120e089abd4e3b4624ae638ac65619a9 Mon Sep 17 00:00:00 2001 From: Arran Schlosberg Date: Tue, 6 Aug 2024 20:12:22 +0100 Subject: [PATCH 09/27] perf: `SetSubnetValidatorWeightMessage` (un)packing gas reductions --- contracts/staking/StakingMessages.sol | 130 ++++---- .../staking/tests/ManualStakingMessages.sol | 289 ++++++++++++++++++ contracts/staking/tests/StakingMessages.t.sol | 72 +++++ 3 files changed, 422 insertions(+), 69 deletions(-) create mode 100644 contracts/staking/tests/ManualStakingMessages.sol create mode 100644 contracts/staking/tests/StakingMessages.t.sol diff --git a/contracts/staking/StakingMessages.sol b/contracts/staking/StakingMessages.sol index e91c02577..c0040e682 100644 --- a/contracts/staking/StakingMessages.sol +++ b/contracts/staking/StakingMessages.sol @@ -51,18 +51,23 @@ library StakingMessages { * @param valiationInfo The information to pack into the message. * @return The validationID and the packed message. */ - function packRegisterSubnetValidatorMessage(ValidationInfo memory valiationInfo) - internal - pure - returns (bytes32, bytes memory) - { - (bytes32 validationID, bytes memory serializedValidationInfo) = - packValidationInfo(valiationInfo); + function packRegisterSubnetValidatorMessage( + ValidationInfo memory valiationInfo + ) internal pure returns (bytes32, bytes memory) { + ( + bytes32 validationID, + bytes memory serializedValidationInfo + ) = packValidationInfo(valiationInfo); bytes memory res = new bytes(148); // Pack the message type for (uint256 i; i < 4; ++i) { - res[i] = bytes1(uint8(SUBNET_VALIDATOR_REGISTRATION_MESSAGE_TYPE_ID >> (8 * (3 - i)))); + res[i] = bytes1( + uint8( + SUBNET_VALIDATOR_REGISTRATION_MESSAGE_TYPE_ID >> + (8 * (3 - i)) + ) + ); } // Pack the validation info for (uint256 i; i < 144; ++i) { @@ -179,11 +184,9 @@ library StakingMessages { * @return The validationID and whether or the validation period was registered * or is not a validator and never will be a validator to do the expiry time passing. */ - function unpackSubnetValidatorRegistrationMessage(bytes memory input) - internal - pure - returns (bytes32, bool) - { + function unpackSubnetValidatorRegistrationMessage( + bytes memory input + ) internal pure returns (bytes32, bool) { require(input.length == 37, "StakingMessages: Invalid message length"); // Unpack the type ID @@ -199,7 +202,9 @@ library StakingMessages { // Unpack the validation ID. bytes32 validationID; for (uint256 i; i < 32; ++i) { - validationID |= bytes32(uint256(uint8(input[i + 4])) << (8 * (31 - i))); + validationID |= bytes32( + uint256(uint8(input[i + 4])) << (8 * (31 - i)) + ); } // Unpack the validity @@ -233,24 +238,13 @@ library StakingMessages { uint64 nonce, uint64 weight ) internal pure returns (bytes memory) { - bytes memory res = new bytes(52); - // Pack the type ID. - for (uint256 i; i < 4; ++i) { - res[i] = bytes1(uint8(SET_SUBNET_VALIDATOR_WEIGHT_MESSAGE_TYPE_ID >> (8 * (3 - i)))); - } - // Pack the validation ID. - for (uint256 i; i < 32; ++i) { - res[i + 4] = bytes1(uint8(uint256(validationID >> (8 * (31 - i))))); - } - // Pack the nonce. - for (uint256 i; i < 8; ++i) { - res[i + 36] = bytes1(uint8(nonce >> (8 * (7 - i)))); - } - // Pack the weight. - for (uint256 i; i < 8; ++i) { - res[i + 44] = bytes1(uint8(weight >> (8 * (7 - i)))); - } - return res; + return + abi.encodePacked( + StakingMessages.SET_SUBNET_VALIDATOR_WEIGHT_MESSAGE_TYPE_ID, + validationID, + nonce, + weight + ); } /** @@ -260,39 +254,29 @@ library StakingMessages { * @param input The byte array to unpack. * @return The validationID, nonce, and weight. */ - function unpackSetSubnetValidatorWeightMessage(bytes memory input) - internal - pure - returns (bytes32, uint64, uint64) - { + function unpackSetSubnetValidatorWeightMessage( + bytes memory input + ) internal pure returns (bytes32, uint64, uint64) { require(input.length == 52, "StakingMessages: Invalid message length"); - // Unpack the type ID. uint32 typeID; - for (uint256 i; i < 4; ++i) { - typeID |= uint32(uint8(input[i])) << uint32((8 * (3 - i))); + assembly ("memory-safe") { + typeID := shr(224, mload(add(input, 0x20))) } require( - typeID == SET_SUBNET_VALIDATOR_WEIGHT_MESSAGE_TYPE_ID, + typeID == + StakingMessages.SET_SUBNET_VALIDATOR_WEIGHT_MESSAGE_TYPE_ID, "StakingMessages: Invalid message type" ); - // Unpack the validation ID. bytes32 validationID; - for (uint256 i; i < 32; ++i) { - validationID |= bytes32(uint256(uint8(input[i + 4])) << (8 * (31 - i))); - } - - // Unpack the nonce. uint64 nonce; - for (uint256 i; i < 8; ++i) { - nonce |= uint64(uint8(input[i + 36])) << uint64((8 * (7 - i))); - } - - // Unpack the weight. uint64 weight; - for (uint256 i; i < 8; ++i) { - weight |= uint64(uint8(input[i + 44])) << uint64((8 * (7 - i))); + assembly ("memory-safe") { + validationID := mload(add(input, 0x24)) + let rest := mload(add(input, 0x44)) // only the first 128 bits are valid + nonce := shr(192, rest) + weight := shr(192, shl(64, rest)) // shl(64, ) wipes the nonce } return (validationID, nonce, weight); @@ -342,11 +326,9 @@ library StakingMessages { * @param input The byte array to unpack. * @return The validationID and uptime. */ - function unpackValidationUptimeMessage(bytes memory input) - internal - pure - returns (bytes32, uint64) - { + function unpackValidationUptimeMessage( + bytes memory input + ) internal pure returns (bytes32, uint64) { require(input.length == 44, "StakingMessages: Invalid message length"); // Unpack the type ID. @@ -355,13 +337,16 @@ library StakingMessages { typeID |= uint32(uint8(input[i])) << uint32((8 * (3 - i))); } require( - typeID == VALIDATION_UPTIME_MESSAGE_TYPE_ID, "StakingMessages: Invalid message type" + typeID == VALIDATION_UPTIME_MESSAGE_TYPE_ID, + "StakingMessages: Invalid message type" ); // Unpack the validation ID. bytes32 validationID; for (uint256 i; i < 32; ++i) { - validationID |= bytes32(uint256(uint8(input[i + 4])) << (8 * (31 - i))); + validationID |= bytes32( + uint256(uint8(input[i + 4])) << (8 * (31 - i)) + ); } // Unpack the uptime. @@ -394,12 +379,13 @@ library StakingMessages { * @param validationInfo The information to pack. * @return The validationID and the packed data. */ - function packValidationInfo(ValidationInfo memory validationInfo) - internal - pure - returns (bytes32, bytes memory) - { - require(validationInfo.signature.length == 64, "StakingMessages: Invalid signature length"); + function packValidationInfo( + ValidationInfo memory validationInfo + ) internal pure returns (bytes32, bytes memory) { + require( + validationInfo.signature.length == 64, + "StakingMessages: Invalid signature length" + ); bytes memory res = new bytes(144); // Pack the subnetID for (uint256 i; i < 32; ++i) { @@ -411,11 +397,17 @@ library StakingMessages { } // Pack the weight for (uint256 i; i < 8; ++i) { - res[i + 64] = bytes1(uint8(validationInfo.weight >> uint8((8 * (7 - i))))); + res[i + 64] = bytes1( + uint8(validationInfo.weight >> uint8((8 * (7 - i)))) + ); } // Pack the registration expiry for (uint256 i; i < 8; ++i) { - res[i + 72] = bytes1(uint8(validationInfo.registrationExpiry >> uint64((8 * (7 - i))))); + res[i + 72] = bytes1( + uint8( + validationInfo.registrationExpiry >> uint64((8 * (7 - i))) + ) + ); } // Pack the signature for (uint256 i; i < 64; ++i) { diff --git a/contracts/staking/tests/ManualStakingMessages.sol b/contracts/staking/tests/ManualStakingMessages.sol new file mode 100644 index 000000000..3d6698b89 --- /dev/null +++ b/contracts/staking/tests/ManualStakingMessages.sol @@ -0,0 +1,289 @@ +// (c) 2023, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +// SPDX-License-Identifier: Ecosystem +pragma solidity 0.8.25; + +library StakingMessages { + // The information that uniquely identifies a subnet validation period. + // The SHA-256 hash of the concatenation of these field is the validationID. + struct ValidationInfo { + bytes32 subnetID; + bytes32 nodeID; + uint64 weight; + uint64 registrationExpiry; + bytes signature; + } + + // Subnets send a RegisterSubnetValidator message to the P-Chain to register a validator. + // The P-Chain responds with a RegisterSubnetValidator message indicating whether the registration was successful + // for the given validation ID. + uint32 internal constant SUBNET_VALIDATOR_REGISTRATION_MESSAGE_TYPE_ID = 1; + // Subnets can send a SetSubnetValidatorWeight message to the P-Chain to update a validator's weight. + // The P-Chain responds with a SetSubnetValidatorWeight message acknowledging the weight update. + uint32 internal constant SET_SUBNET_VALIDATOR_WEIGHT_MESSAGE_TYPE_ID = 2; + // The Subnet will self-sign a ValidationUptimeMessage to be provided when a validator is initiating + // the end of their validation period. + uint32 internal constant VALIDATION_UPTIME_MESSAGE_TYPE_ID = 3; + + // TODO: The implemenation of these packing and unpacking functions is neither tested or optimzied at all. + // Full test coverage should be provided, and the implementation should be optimized for gas efficiency. + + /** + * @notice Packs a RegisterSubnetValidator message into a byte array. + * The message format specification is: + * +-----------+----------+-----------+ + * | typeID : uint32 | 4 bytes | + * +-----------+----------+-----------+ + * | subnetID : [32]byte | 32 bytes | + * +-----------+----------+-----------+ + * | nodeID : [32]byte | 32 bytes | + * +-----------+----------+-----------+ + * | weight : uint64 | 8 bytes | + * +-----------+----------+-----------+ + * | expiry : uint64 | 8 bytes | + * +-----------+----------+-----------+ + * | signature : [64]byte | 64 bytes | + * +-----------+----------+-----------+ + * | 148 bytes | + * +-----------+ + */ + function packRegisterSubnetValidatorMessage(ValidationInfo memory valiationInfo) + internal + pure + returns (bytes32, bytes memory) + { + (bytes32 validationID, bytes memory serializedValidationInfo) = + packValidationInfo(valiationInfo); + + bytes memory res = new bytes(148); + // Pack the message type + for (uint256 i; i < 4; ++i) { + res[i] = bytes1(uint8(SUBNET_VALIDATOR_REGISTRATION_MESSAGE_TYPE_ID >> (8 * (3 - i)))); + } + // Pack the validation info + for (uint256 i; i < 144; ++i) { + res[i + 4] = serializedValidationInfo[i]; + } + + return (validationID, res); + } + + /** + * @notice Unpacks a byte array as a RegisterSubnetValidator message. + * The message format specification is: + * +--------------+----------+----------+ + * | typeID : uint32 | 4 bytes | + * +--------------+----------+----------+ + * | validationID : [32]byte | 32 bytes | + * +--------------+----------+----------+ + * | valid : bool + 1 byte | + * +--------------+----------+----------+ + * | 37 bytes | + * +----------+ + * @return The validationID and whether or the validation period was registered + * or is not a validator and never will be a validator to do the expiry time passing. + */ + function unpackSubnetValidatorRegistrationMessage(bytes memory input) + internal + pure + returns (bytes32, bool) + { + require(input.length == 37, "StakingMessages: Invalid message length"); + + // Unpack the type ID + uint32 typeID; + for (uint256 i; i < 4; ++i) { + typeID |= uint32(uint8(input[i])) << uint32((8 * (3 - i))); + } + require( + typeID == SUBNET_VALIDATOR_REGISTRATION_MESSAGE_TYPE_ID, + "StakingMessages: Invalid message type" + ); + + // Unpack the validation ID. + bytes32 validationID; + for (uint256 i; i < 32; ++i) { + validationID |= bytes32(uint256(uint8(input[i + 4])) << (8 * (31 - i))); + } + + // Unpack the validity + bool valid = input[36] != 0; + + return (validationID, valid); + } + + /** + * @notice Packs a SetSubnetValidatorWeight message into a byte array. + * The message format specification is: + * +--------------+----------+----------+ + * | typeID : uint32 | 4 bytes | + * +--------------+----------+----------+ + * | validationID : [32]byte | 32 bytes | + * +--------------+----------+----------+ + * | nonce : uint64 | 8 bytes | + * +--------------+----------+----------+ + * | weight : uint64 | 8 bytes | + * +--------------+----------+----------+ + * | 52 bytes | + * +----------+ + */ + function packSetSubnetValidatorWeightMessage( + bytes32 validationID, + uint64 nonce, + uint64 weight + ) internal pure returns (bytes memory) { + bytes memory res = new bytes(52); + // Pack the type ID. + for (uint256 i; i < 4; ++i) { + res[i] = bytes1(uint8(SET_SUBNET_VALIDATOR_WEIGHT_MESSAGE_TYPE_ID >> (8 * (3 - i)))); + } + // Pack the validation ID. + for (uint256 i; i < 32; ++i) { + res[i + 4] = bytes1(uint8(uint256(validationID >> (8 * (31 - i))))); + } + // Pack the nonce. + for (uint256 i; i < 8; ++i) { + res[i + 36] = bytes1(uint8(nonce >> (8 * (7 - i)))); + } + // Pack the weight. + for (uint256 i; i < 8; ++i) { + res[i + 44] = bytes1(uint8(weight >> (8 * (7 - i)))); + } + return res; + } + + /** + * @notice Unpacks a byte array as a SetSubnetValidatorWeight message. + * The message format specification is the same as the one used in above for packing. + */ + function unpackSetSubnetValidatorWeightMessage(bytes memory input) + internal + pure + returns (bytes32, uint64, uint64) + { + require(input.length == 52, "StakingMessages: Invalid message length"); + + // Unpack the type ID. + uint32 typeID; + for (uint256 i; i < 4; ++i) { + typeID |= uint32(uint8(input[i])) << uint32((8 * (3 - i))); + } + require( + typeID == SET_SUBNET_VALIDATOR_WEIGHT_MESSAGE_TYPE_ID, + "StakingMessages: Invalid message type" + ); + + // Unpack the validation ID. + bytes32 validationID; + for (uint256 i; i < 32; ++i) { + validationID |= bytes32(uint256(uint8(input[i + 4])) << (8 * (31 - i))); + } + + // Unpack the nonce. + uint64 nonce; + for (uint256 i; i < 8; ++i) { + nonce |= uint64(uint8(input[i + 36])) << uint64((8 * (7 - i))); + } + + // Unpack the weight. + uint64 weight; + for (uint256 i; i < 8; ++i) { + weight |= uint64(uint8(input[i + 44])) << uint64((8 * (7 - i))); + } + + return (validationID, nonce, weight); + } + + /** + * @notice Unpacks a byte array as a ValidationUptimeMessage. + * The message format specification is: + * +--------------+----------+----------+ + * | typeID : uint32 | 4 bytes | + * +--------------+----------+----------+ + * | validationID : [32]byte | 32 bytes | + * +--------------+----------+----------+ + * | uptime : uint64 | 8 bytes | + * +--------------+----------+----------+ + * | 44 bytes | + * +----------+ + */ + function unpackValidationUptimeMessage(bytes memory input) + internal + pure + returns (bytes32, uint64) + { + require(input.length == 44, "StakingMessages: Invalid message length"); + + // Unpack the type ID. + uint32 typeID; + for (uint256 i; i < 4; ++i) { + typeID |= uint32(uint8(input[i])) << uint32((8 * (3 - i))); + } + require( + typeID == VALIDATION_UPTIME_MESSAGE_TYPE_ID, "StakingMessages: Invalid message type" + ); + + // Unpack the validation ID. + bytes32 validationID; + for (uint256 i; i < 32; ++i) { + validationID |= bytes32(uint256(uint8(input[i + 4])) << (8 * (31 - i))); + } + + // Unpack the uptime. + uint64 uptime; + for (uint256 i; i < 8; ++i) { + uptime |= uint64(uint8(input[i + 36])) << uint64((8 * (7 - i))); + } + + return (validationID, uptime); + } + + /** + * @notice Packs all of the information pertaining to a validation period into a byte array. + * The packed data is used to calculate the validationID as the SHA-256 hash of the packed data. + * The specification of the packed data is: + * +-----------+----------+-----------+ + * | subnetID : [32]byte | 32 bytes | + * +-----------+----------+-----------+ + * | nodeID : [32]byte | 32 bytes | + * +-----------+----------+-----------+ + * | weight : uint64 | 8 bytes | + * +-----------+----------+-----------+ + * | expiry : uint64 | 8 bytes | + * +-----------+----------+-----------+ + * | signature : [64]byte | 64 bytes | + * +-----------+----------+-----------+ + * | 144 bytes | + * +-----------+ + */ + function packValidationInfo(ValidationInfo memory validationInfo) + internal + pure + returns (bytes32, bytes memory) + { + require(validationInfo.signature.length == 64, "StakingMessages: Invalid signature length"); + bytes memory res = new bytes(144); + // Pack the subnetID + for (uint256 i; i < 32; ++i) { + res[i] = validationInfo.subnetID[i]; + } + // Pack the nodeID + for (uint256 i; i < 32; ++i) { + res[i + 32] = validationInfo.nodeID[i]; + } + // Pack the weight + for (uint256 i; i < 8; ++i) { + res[i + 64] = bytes1(uint8(validationInfo.weight >> uint8((8 * (7 - i))))); + } + // Pack the registration expiry + for (uint256 i; i < 8; ++i) { + res[i + 72] = bytes1(uint8(validationInfo.registrationExpiry >> uint64((8 * (7 - i))))); + } + // Pack the signature + for (uint256 i; i < 64; ++i) { + res[i + 80] = validationInfo.signature[i]; + } + return (sha256(res), res); + } +} diff --git a/contracts/staking/tests/StakingMessages.t.sol b/contracts/staking/tests/StakingMessages.t.sol new file mode 100644 index 000000000..be771e76f --- /dev/null +++ b/contracts/staking/tests/StakingMessages.t.sol @@ -0,0 +1,72 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.25; + +import {Test} from "@forge-std/Test.sol"; +import {StakingMessages} from "../StakingMessages.sol"; +import {StakingMessages as Original} from "./ManualStakingMessages.sol"; + +contract StakingMessagesTest is Test { + function testSubnetValidatorWeightPackRoundTrip( + bytes32 validationID, + uint64 nonce, + uint64 weight + ) public view { + uint256 startGas; + uint256 endGas; + + startGas = gasleft(); + bytes memory original = Original.packSetSubnetValidatorWeightMessage( + validationID, + nonce, + weight + ); + endGas = gasleft(); + uint256 originalGas = startGas - endGas; + + startGas = gasleft(); + bytes memory packed = StakingMessages + .packSetSubnetValidatorWeightMessage(validationID, nonce, weight); + endGas = gasleft(); + // Doing this after the original will actually penalise it because + // memory expansion is quadratic, so the gas saving is higher than the + // test suggests. + uint256 gas = startGas - endGas; + + assertEq(original, packed, "same data"); + assertGe(originalGas - gas, 19_500, "gas saving"); + + ( + bytes32 gotValidationID, + uint64 gotNonce, + uint64 gotWeight + ) = StakingMessages.unpackSetSubnetValidatorWeightMessage(packed); + + assertEq(validationID, gotValidationID, "validation ID"); + assertEq(nonce, gotNonce, "nonce"); + assertEq(weight, gotWeight, "weight"); + } + + function testUnpackSubnetValidatorWeightGas( + bytes32 validationID, + uint64 nonce, + uint64 weight + ) public view { + bytes memory buffer = StakingMessages + .packSetSubnetValidatorWeightMessage(validationID, nonce, weight); + + uint256 startGas; + uint256 endGas; + + startGas = gasleft(); + StakingMessages.unpackSetSubnetValidatorWeightMessage(buffer); + endGas = gasleft(); + uint256 gas = startGas - endGas; + + startGas = gasleft(); + Original.unpackSetSubnetValidatorWeightMessage(buffer); + endGas = gasleft(); + uint256 originalGas = startGas - endGas; + + assertGe(originalGas - gas, 18_000, "gas saving"); + } +} From 9890cca96d35f95d8be460283fbbff520783e9ff Mon Sep 17 00:00:00 2001 From: Arran Schlosberg Date: Tue, 6 Aug 2024 20:19:04 +0100 Subject: [PATCH 10/27] chore: `forge fmt` --- contracts/staking/StakingMessages.sol | 92 ++++++++----------- contracts/staking/tests/StakingMessages.t.sol | 22 ++--- 2 files changed, 46 insertions(+), 68 deletions(-) diff --git a/contracts/staking/StakingMessages.sol b/contracts/staking/StakingMessages.sol index c0040e682..0556c6372 100644 --- a/contracts/staking/StakingMessages.sol +++ b/contracts/staking/StakingMessages.sol @@ -51,23 +51,18 @@ library StakingMessages { * @param valiationInfo The information to pack into the message. * @return The validationID and the packed message. */ - function packRegisterSubnetValidatorMessage( - ValidationInfo memory valiationInfo - ) internal pure returns (bytes32, bytes memory) { - ( - bytes32 validationID, - bytes memory serializedValidationInfo - ) = packValidationInfo(valiationInfo); + function packRegisterSubnetValidatorMessage(ValidationInfo memory valiationInfo) + internal + pure + returns (bytes32, bytes memory) + { + (bytes32 validationID, bytes memory serializedValidationInfo) = + packValidationInfo(valiationInfo); bytes memory res = new bytes(148); // Pack the message type for (uint256 i; i < 4; ++i) { - res[i] = bytes1( - uint8( - SUBNET_VALIDATOR_REGISTRATION_MESSAGE_TYPE_ID >> - (8 * (3 - i)) - ) - ); + res[i] = bytes1(uint8(SUBNET_VALIDATOR_REGISTRATION_MESSAGE_TYPE_ID >> (8 * (3 - i)))); } // Pack the validation info for (uint256 i; i < 144; ++i) { @@ -184,9 +179,11 @@ library StakingMessages { * @return The validationID and whether or the validation period was registered * or is not a validator and never will be a validator to do the expiry time passing. */ - function unpackSubnetValidatorRegistrationMessage( - bytes memory input - ) internal pure returns (bytes32, bool) { + function unpackSubnetValidatorRegistrationMessage(bytes memory input) + internal + pure + returns (bytes32, bool) + { require(input.length == 37, "StakingMessages: Invalid message length"); // Unpack the type ID @@ -202,9 +199,7 @@ library StakingMessages { // Unpack the validation ID. bytes32 validationID; for (uint256 i; i < 32; ++i) { - validationID |= bytes32( - uint256(uint8(input[i + 4])) << (8 * (31 - i)) - ); + validationID |= bytes32(uint256(uint8(input[i + 4])) << (8 * (31 - i))); } // Unpack the validity @@ -238,13 +233,9 @@ library StakingMessages { uint64 nonce, uint64 weight ) internal pure returns (bytes memory) { - return - abi.encodePacked( - StakingMessages.SET_SUBNET_VALIDATOR_WEIGHT_MESSAGE_TYPE_ID, - validationID, - nonce, - weight - ); + return abi.encodePacked( + StakingMessages.SET_SUBNET_VALIDATOR_WEIGHT_MESSAGE_TYPE_ID, validationID, nonce, weight + ); } /** @@ -254,9 +245,11 @@ library StakingMessages { * @param input The byte array to unpack. * @return The validationID, nonce, and weight. */ - function unpackSetSubnetValidatorWeightMessage( - bytes memory input - ) internal pure returns (bytes32, uint64, uint64) { + function unpackSetSubnetValidatorWeightMessage(bytes memory input) + internal + pure + returns (bytes32, uint64, uint64) + { require(input.length == 52, "StakingMessages: Invalid message length"); uint32 typeID; @@ -264,8 +257,7 @@ library StakingMessages { typeID := shr(224, mload(add(input, 0x20))) } require( - typeID == - StakingMessages.SET_SUBNET_VALIDATOR_WEIGHT_MESSAGE_TYPE_ID, + typeID == StakingMessages.SET_SUBNET_VALIDATOR_WEIGHT_MESSAGE_TYPE_ID, "StakingMessages: Invalid message type" ); @@ -326,9 +318,11 @@ library StakingMessages { * @param input The byte array to unpack. * @return The validationID and uptime. */ - function unpackValidationUptimeMessage( - bytes memory input - ) internal pure returns (bytes32, uint64) { + function unpackValidationUptimeMessage(bytes memory input) + internal + pure + returns (bytes32, uint64) + { require(input.length == 44, "StakingMessages: Invalid message length"); // Unpack the type ID. @@ -337,16 +331,13 @@ library StakingMessages { typeID |= uint32(uint8(input[i])) << uint32((8 * (3 - i))); } require( - typeID == VALIDATION_UPTIME_MESSAGE_TYPE_ID, - "StakingMessages: Invalid message type" + typeID == VALIDATION_UPTIME_MESSAGE_TYPE_ID, "StakingMessages: Invalid message type" ); // Unpack the validation ID. bytes32 validationID; for (uint256 i; i < 32; ++i) { - validationID |= bytes32( - uint256(uint8(input[i + 4])) << (8 * (31 - i)) - ); + validationID |= bytes32(uint256(uint8(input[i + 4])) << (8 * (31 - i))); } // Unpack the uptime. @@ -379,13 +370,12 @@ library StakingMessages { * @param validationInfo The information to pack. * @return The validationID and the packed data. */ - function packValidationInfo( - ValidationInfo memory validationInfo - ) internal pure returns (bytes32, bytes memory) { - require( - validationInfo.signature.length == 64, - "StakingMessages: Invalid signature length" - ); + function packValidationInfo(ValidationInfo memory validationInfo) + internal + pure + returns (bytes32, bytes memory) + { + require(validationInfo.signature.length == 64, "StakingMessages: Invalid signature length"); bytes memory res = new bytes(144); // Pack the subnetID for (uint256 i; i < 32; ++i) { @@ -397,17 +387,11 @@ library StakingMessages { } // Pack the weight for (uint256 i; i < 8; ++i) { - res[i + 64] = bytes1( - uint8(validationInfo.weight >> uint8((8 * (7 - i)))) - ); + res[i + 64] = bytes1(uint8(validationInfo.weight >> uint8((8 * (7 - i))))); } // Pack the registration expiry for (uint256 i; i < 8; ++i) { - res[i + 72] = bytes1( - uint8( - validationInfo.registrationExpiry >> uint64((8 * (7 - i))) - ) - ); + res[i + 72] = bytes1(uint8(validationInfo.registrationExpiry >> uint64((8 * (7 - i))))); } // Pack the signature for (uint256 i; i < 64; ++i) { diff --git a/contracts/staking/tests/StakingMessages.t.sol b/contracts/staking/tests/StakingMessages.t.sol index be771e76f..6e63d8b26 100644 --- a/contracts/staking/tests/StakingMessages.t.sol +++ b/contracts/staking/tests/StakingMessages.t.sol @@ -15,17 +15,14 @@ contract StakingMessagesTest is Test { uint256 endGas; startGas = gasleft(); - bytes memory original = Original.packSetSubnetValidatorWeightMessage( - validationID, - nonce, - weight - ); + bytes memory original = + Original.packSetSubnetValidatorWeightMessage(validationID, nonce, weight); endGas = gasleft(); uint256 originalGas = startGas - endGas; startGas = gasleft(); - bytes memory packed = StakingMessages - .packSetSubnetValidatorWeightMessage(validationID, nonce, weight); + bytes memory packed = + StakingMessages.packSetSubnetValidatorWeightMessage(validationID, nonce, weight); endGas = gasleft(); // Doing this after the original will actually penalise it because // memory expansion is quadratic, so the gas saving is higher than the @@ -35,11 +32,8 @@ contract StakingMessagesTest is Test { assertEq(original, packed, "same data"); assertGe(originalGas - gas, 19_500, "gas saving"); - ( - bytes32 gotValidationID, - uint64 gotNonce, - uint64 gotWeight - ) = StakingMessages.unpackSetSubnetValidatorWeightMessage(packed); + (bytes32 gotValidationID, uint64 gotNonce, uint64 gotWeight) = + StakingMessages.unpackSetSubnetValidatorWeightMessage(packed); assertEq(validationID, gotValidationID, "validation ID"); assertEq(nonce, gotNonce, "nonce"); @@ -51,8 +45,8 @@ contract StakingMessagesTest is Test { uint64 nonce, uint64 weight ) public view { - bytes memory buffer = StakingMessages - .packSetSubnetValidatorWeightMessage(validationID, nonce, weight); + bytes memory buffer = + StakingMessages.packSetSubnetValidatorWeightMessage(validationID, nonce, weight); uint256 startGas; uint256 endGas; From 721b63e4fbbb8b67f12f7d1cc88762c826568195 Mon Sep 17 00:00:00 2001 From: Arran Schlosberg Date: Tue, 6 Aug 2024 20:29:15 +0100 Subject: [PATCH 11/27] chore: `solhint-disable` assembly checks + some commentary --- contracts/staking/StakingMessages.sol | 15 +++++++++++++-- contracts/staking/tests/StakingMessages.t.sol | 2 ++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/contracts/staking/StakingMessages.sol b/contracts/staking/StakingMessages.sol index 0556c6372..6c2eda525 100644 --- a/contracts/staking/StakingMessages.sol +++ b/contracts/staking/StakingMessages.sol @@ -234,7 +234,7 @@ library StakingMessages { uint64 weight ) internal pure returns (bytes memory) { return abi.encodePacked( - StakingMessages.SET_SUBNET_VALIDATOR_WEIGHT_MESSAGE_TYPE_ID, validationID, nonce, weight + SET_SUBNET_VALIDATOR_WEIGHT_MESSAGE_TYPE_ID, validationID, nonce, weight ); } @@ -250,14 +250,20 @@ library StakingMessages { pure returns (bytes32, uint64, uint64) { + /* solhint-disable no-inline-assembly */ require(input.length == 52, "StakingMessages: Invalid message length"); + // A `bytes memory` is stored as one word representing the length and + // then the buffer of said length. Using the variable name in assembly + // is equivalent to a pointer to the length, and `add(input, 0x20)` + // points to the first word of the buffer. + uint32 typeID; assembly ("memory-safe") { typeID := shr(224, mload(add(input, 0x20))) } require( - typeID == StakingMessages.SET_SUBNET_VALIDATOR_WEIGHT_MESSAGE_TYPE_ID, + typeID == SET_SUBNET_VALIDATOR_WEIGHT_MESSAGE_TYPE_ID, "StakingMessages: Invalid message type" ); @@ -265,6 +271,10 @@ library StakingMessages { uint64 nonce; uint64 weight; assembly ("memory-safe") { + // Although we could achieve the entire unpacking with only two + // MLOADs, we'd have to stitch the `validationID` together and make + // everything less readable. It may even require _more_ gas because + // the MLOAD is so cheap. validationID := mload(add(input, 0x24)) let rest := mload(add(input, 0x44)) // only the first 128 bits are valid nonce := shr(192, rest) @@ -272,6 +282,7 @@ library StakingMessages { } return (validationID, nonce, weight); + /* solhint-enable no-inline-assembly */ } /** diff --git a/contracts/staking/tests/StakingMessages.t.sol b/contracts/staking/tests/StakingMessages.t.sol index 6e63d8b26..90a12c8af 100644 --- a/contracts/staking/tests/StakingMessages.t.sol +++ b/contracts/staking/tests/StakingMessages.t.sol @@ -31,6 +31,7 @@ contract StakingMessagesTest is Test { assertEq(original, packed, "same data"); assertGe(originalGas - gas, 19_500, "gas saving"); + assertLe(gas, 250, "gas cost"); (bytes32 gotValidationID, uint64 gotNonce, uint64 gotWeight) = StakingMessages.unpackSetSubnetValidatorWeightMessage(packed); @@ -62,5 +63,6 @@ contract StakingMessagesTest is Test { uint256 originalGas = startGas - endGas; assertGe(originalGas - gas, 18_000, "gas saving"); + assertLe(gas, 200, "gas cost"); } } From ef875662c8b0d145e953056cdc8f5ce5469e7c11 Mon Sep 17 00:00:00 2001 From: Arran Schlosberg Date: Fri, 9 Aug 2024 12:51:59 +0100 Subject: [PATCH 12/27] feat: generated code for `abi.encodePacked()` inversion --- contracts/staking/StakingMessages.sol | 138 ++------- contracts/staking/Unpack.sol | 143 +++++++++ contracts/staking/tests/StakingMessages.t.sol | 2 +- contracts/staking/tests/Unpack.t.sol | 83 +++++ contracts/staking/unpackgen.go | 3 + go.mod | 2 +- utils/unpack/Unpack.sol.gotmpl | 69 +++++ utils/unpack/Unpack.t.sol.gotmpl | 25 ++ utils/unpack/unpack.go | 284 ++++++++++++++++++ utils/unpack/unpackgen/unpackgen.go | 104 +++++++ 10 files changed, 742 insertions(+), 111 deletions(-) create mode 100644 contracts/staking/Unpack.sol create mode 100644 contracts/staking/tests/Unpack.t.sol create mode 100644 contracts/staking/unpackgen.go create mode 100644 utils/unpack/Unpack.sol.gotmpl create mode 100644 utils/unpack/Unpack.t.sol.gotmpl create mode 100644 utils/unpack/unpack.go create mode 100644 utils/unpack/unpackgen/unpackgen.go diff --git a/contracts/staking/StakingMessages.sol b/contracts/staking/StakingMessages.sol index 6c2eda525..fb51602e9 100644 --- a/contracts/staking/StakingMessages.sol +++ b/contracts/staking/StakingMessages.sol @@ -4,6 +4,8 @@ // SPDX-License-Identifier: Ecosystem pragma solidity 0.8.25; +import {Unpack} from "./Unpack.sol"; + library StakingMessages { // The information that uniquely identifies a subnet validation period. // The SHA-256 hash of the concatenation of these field is the validationID. @@ -51,25 +53,16 @@ library StakingMessages { * @param valiationInfo The information to pack into the message. * @return The validationID and the packed message. */ - function packRegisterSubnetValidatorMessage(ValidationInfo memory valiationInfo) + function packRegisterSubnetValidatorMessage(ValidationInfo memory validationInfo) internal pure returns (bytes32, bytes memory) { - (bytes32 validationID, bytes memory serializedValidationInfo) = - packValidationInfo(valiationInfo); - - bytes memory res = new bytes(148); - // Pack the message type - for (uint256 i; i < 4; ++i) { - res[i] = bytes1(uint8(SUBNET_VALIDATOR_REGISTRATION_MESSAGE_TYPE_ID >> (8 * (3 - i)))); - } - // Pack the validation info - for (uint256 i; i < 144; ++i) { - res[i + 4] = serializedValidationInfo[i]; - } - - return (validationID, res); + (bytes32 validationID, bytes memory serialized) = packAndHashValidationInfo(validationInfo); + return ( + validationID, + abi.encodePacked(SUBNET_VALIDATOR_REGISTRATION_MESSAGE_TYPE_ID, serialized) + ); } /** @@ -184,28 +177,12 @@ library StakingMessages { pure returns (bytes32, bool) { - require(input.length == 37, "StakingMessages: Invalid message length"); - - // Unpack the type ID - uint32 typeID; - for (uint256 i; i < 4; ++i) { - typeID |= uint32(uint8(input[i])) << uint32((8 * (3 - i))); - } + (bytes4 typeID, bytes32 validationID, bytes1 valid) = Unpack.unpack_4_32_1(input); require( - typeID == SUBNET_VALIDATOR_REGISTRATION_MESSAGE_TYPE_ID, + uint32(typeID) == SUBNET_VALIDATOR_REGISTRATION_MESSAGE_TYPE_ID, "StakingMessages: Invalid message type" ); - - // Unpack the validation ID. - bytes32 validationID; - for (uint256 i; i < 32; ++i) { - validationID |= bytes32(uint256(uint8(input[i + 4])) << (8 * (31 - i))); - } - - // Unpack the validity - bool valid = input[36] != 0; - - return (validationID, valid); + return (validationID, uint8(valid) != 0); } /** @@ -250,39 +227,13 @@ library StakingMessages { pure returns (bytes32, uint64, uint64) { - /* solhint-disable no-inline-assembly */ - require(input.length == 52, "StakingMessages: Invalid message length"); - - // A `bytes memory` is stored as one word representing the length and - // then the buffer of said length. Using the variable name in assembly - // is equivalent to a pointer to the length, and `add(input, 0x20)` - // points to the first word of the buffer. - - uint32 typeID; - assembly ("memory-safe") { - typeID := shr(224, mload(add(input, 0x20))) - } + (bytes4 typeID, bytes32 validationID, bytes8 nonce, bytes8 weight) = + Unpack.unpack_4_32_8_8(input); require( - typeID == SET_SUBNET_VALIDATOR_WEIGHT_MESSAGE_TYPE_ID, + uint32(typeID) == SET_SUBNET_VALIDATOR_WEIGHT_MESSAGE_TYPE_ID, "StakingMessages: Invalid message type" ); - - bytes32 validationID; - uint64 nonce; - uint64 weight; - assembly ("memory-safe") { - // Although we could achieve the entire unpacking with only two - // MLOADs, we'd have to stitch the `validationID` together and make - // everything less readable. It may even require _more_ gas because - // the MLOAD is so cheap. - validationID := mload(add(input, 0x24)) - let rest := mload(add(input, 0x44)) // only the first 128 bits are valid - nonce := shr(192, rest) - weight := shr(192, shl(64, rest)) // shl(64, ) wipes the nonce - } - - return (validationID, nonce, weight); - /* solhint-enable no-inline-assembly */ + return (validationID, uint64(nonce), uint64(weight)); } /** @@ -334,30 +285,12 @@ library StakingMessages { pure returns (bytes32, uint64) { - require(input.length == 44, "StakingMessages: Invalid message length"); - - // Unpack the type ID. - uint32 typeID; - for (uint256 i; i < 4; ++i) { - typeID |= uint32(uint8(input[i])) << uint32((8 * (3 - i))); - } + (bytes4 typeID, bytes32 validationID, bytes8 uptime) = Unpack.unpack_4_32_8(input); require( - typeID == VALIDATION_UPTIME_MESSAGE_TYPE_ID, "StakingMessages: Invalid message type" + uint32(typeID) == VALIDATION_UPTIME_MESSAGE_TYPE_ID, + "StakingMessages: Invalid message type" ); - - // Unpack the validation ID. - bytes32 validationID; - for (uint256 i; i < 32; ++i) { - validationID |= bytes32(uint256(uint8(input[i + 4])) << (8 * (31 - i))); - } - - // Unpack the uptime. - uint64 uptime; - for (uint256 i; i < 8; ++i) { - uptime |= uint64(uint8(input[i + 36])) << uint64((8 * (7 - i))); - } - - return (validationID, uptime); + return (validationID, uint64(uptime)); } /** @@ -381,33 +314,20 @@ library StakingMessages { * @param validationInfo The information to pack. * @return The validationID and the packed data. */ - function packValidationInfo(ValidationInfo memory validationInfo) + function packValidationInfo(ValidationInfo memory info) internal pure returns (bytes memory) { + require(info.signature.length == 64, "StakingMessages: Invalid signature length"); + return abi.encodePacked( + info.subnetID, info.nodeID, info.weight, info.registrationExpiry, info.signature + ); + } + + /// @dev Equivalent to returning `packValidationInfo(info)` and the SHA256 hash thereof. + function packAndHashValidationInfo(ValidationInfo memory info) internal pure returns (bytes32, bytes memory) { - require(validationInfo.signature.length == 64, "StakingMessages: Invalid signature length"); - bytes memory res = new bytes(144); - // Pack the subnetID - for (uint256 i; i < 32; ++i) { - res[i] = validationInfo.subnetID[i]; - } - // Pack the nodeID - for (uint256 i; i < 32; ++i) { - res[i + 32] = validationInfo.nodeID[i]; - } - // Pack the weight - for (uint256 i; i < 8; ++i) { - res[i + 64] = bytes1(uint8(validationInfo.weight >> uint8((8 * (7 - i))))); - } - // Pack the registration expiry - for (uint256 i; i < 8; ++i) { - res[i + 72] = bytes1(uint8(validationInfo.registrationExpiry >> uint64((8 * (7 - i))))); - } - // Pack the signature - for (uint256 i; i < 64; ++i) { - res[i + 80] = validationInfo.signature[i]; - } + bytes memory res = packValidationInfo(info); return (sha256(res), res); } diff --git a/contracts/staking/Unpack.sol b/contracts/staking/Unpack.sol new file mode 100644 index 000000000..0286d1679 --- /dev/null +++ b/contracts/staking/Unpack.sol @@ -0,0 +1,143 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.0; + +// GENERATED CODE - Do not edit + +/* solhint-disable no-inline-assembly */ +/* solhint-disable func-name-mixedcase */ + +library Unpack { + /// @dev Thrown if the input buffer to an unpack function is of the wrong length. + error IncorrectInputLength(uint256 expected, uint256 actual); + + /// @dev Thrown if the input buffer to an unpack function with dynamically sized output is too short. + error InsufficientInputLength(uint256 min, uint256 actual); + + /** + * @notice Inverts `abi.encodePacked()` for the specific return types. + * @dev The originally packed inputs MUST be of the same types as those returned by this function, in the precise + * order, otherwise the output is undefined. + * @dev This function takes ownership of and corrupts the `input` parameter to avoid memory expansion for the + * returned `bytes memory`. The returned array is owned by the caller. + * @param input Buffer returned by `abi.encodePacked()` + */ + function unpack_4_32_32_8_8_Dyn_Destructive(bytes memory input) + internal + pure + returns (bytes4 v0, bytes32 v1, bytes32 v2, bytes8 v3, bytes8 v4, bytes memory v5) + { + if (input.length < 84) { + revert InsufficientInputLength(84, input.length); + } + + assembly ("memory-safe") { + v0 := mload(add(input, 0x20)) + v1 := mload(add(input, 0x24)) + v2 := mload(add(input, 0x44)) + v3 := mload(add(input, 0x64)) + v4 := mload(add(input, 0x6c)) + let length := mload(input) + let dynLength := sub(length, 84) + v5 := add(input, 84) + mstore(v5, dynLength) + let end := add(input, add(length, 0x20)) + } + } + + /** + * @notice Inverts `abi.encodePacked()` for the specific return types. + * @dev The originally packed inputs MUST be of the same types as those returned by this function, in the precise + * order, otherwise the output is undefined. + * @param input Buffer returned by `abi.encodePacked()` + */ + function unpack_4_32_1(bytes memory input) + internal + pure + returns (bytes4 v0, bytes32 v1, bytes1 v2) + { + if (input.length != 37) { + revert IncorrectInputLength(input.length, 37); + } + + assembly ("memory-safe") { + v0 := mload(add(input, 0x20)) + v1 := mload(add(input, 0x24)) + v2 := mload(add(input, 0x44)) + } + } + + /** + * @notice Inverts `abi.encodePacked()` for the specific return types. + * @dev The originally packed inputs MUST be of the same types as those returned by this function, in the precise + * order, otherwise the output is undefined. + * @param input Buffer returned by `abi.encodePacked()` + */ + function unpack_4_32_8_8(bytes memory input) + internal + pure + returns (bytes4 v0, bytes32 v1, bytes8 v2, bytes8 v3) + { + if (input.length != 52) { + revert IncorrectInputLength(input.length, 52); + } + + assembly ("memory-safe") { + v0 := mload(add(input, 0x20)) + v1 := mload(add(input, 0x24)) + v2 := mload(add(input, 0x44)) + v3 := mload(add(input, 0x4c)) + } + } + + /** + * @notice Inverts `abi.encodePacked()` for the specific return types. + * @dev The originally packed inputs MUST be of the same types as those returned by this function, in the precise + * order, otherwise the output is undefined. + * @param input Buffer returned by `abi.encodePacked()` + */ + function unpack_4_32_8(bytes memory input) + internal + pure + returns (bytes4 v0, bytes32 v1, bytes8 v2) + { + if (input.length != 44) { + revert IncorrectInputLength(input.length, 44); + } + + assembly ("memory-safe") { + v0 := mload(add(input, 0x20)) + v1 := mload(add(input, 0x24)) + v2 := mload(add(input, 0x44)) + } + } + + /** + * @notice Inverts `abi.encodePacked()` for the specific return types. + * @dev The originally packed inputs MUST be of the same types as those returned by this function, in the precise + * order, otherwise the output is undefined. + * @dev This function takes ownership of and corrupts the `input` parameter to avoid memory expansion for the + * returned `bytes memory`. The returned array is owned by the caller. + * @param input Buffer returned by `abi.encodePacked()` + */ + function unpack_32_32_8_8_Dyn_Destructive(bytes memory input) + internal + pure + returns (bytes32 v0, bytes32 v1, bytes8 v2, bytes8 v3, bytes memory v4) + { + if (input.length < 80) { + revert InsufficientInputLength(80, input.length); + } + + assembly ("memory-safe") { + v0 := mload(add(input, 0x20)) + v1 := mload(add(input, 0x40)) + v2 := mload(add(input, 0x60)) + v3 := mload(add(input, 0x68)) + let length := mload(input) + let dynLength := sub(length, 80) + v4 := add(input, 80) + mstore(v4, dynLength) + let end := add(input, add(length, 0x20)) + } + } +} diff --git a/contracts/staking/tests/StakingMessages.t.sol b/contracts/staking/tests/StakingMessages.t.sol index 90a12c8af..46c18616a 100644 --- a/contracts/staking/tests/StakingMessages.t.sol +++ b/contracts/staking/tests/StakingMessages.t.sol @@ -63,6 +63,6 @@ contract StakingMessagesTest is Test { uint256 originalGas = startGas - endGas; assertGe(originalGas - gas, 18_000, "gas saving"); - assertLe(gas, 200, "gas cost"); + assertLe(gas, 350, "gas cost"); } } diff --git a/contracts/staking/tests/Unpack.t.sol b/contracts/staking/tests/Unpack.t.sol new file mode 100644 index 000000000..eae08ddc1 --- /dev/null +++ b/contracts/staking/tests/Unpack.t.sol @@ -0,0 +1,83 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.0; + +// GENERATED CODE - Do not edit + +import {Test} from "@forge-std/Test.sol"; +import {console} from "@forge-std/console.sol"; +import {Unpack} from "../Unpack.sol"; + +/* solhint-disable func-name-mixedcase */ + +contract UnpackTest is Test { + function testUnpack_4_32_32_8_8_Dyn_Destructive( + bytes4 v0, + bytes32 v1, + bytes32 v2, + bytes8 v3, + bytes8 v4, + bytes memory v5 + ) external pure { + bytes memory packed = abi.encodePacked(v0, v1, v2, v3, v4, v5); + console.logBytes(packed); + + (bytes4 got0, bytes32 got1, bytes32 got2, bytes8 got3, bytes8 got4, bytes memory got5) = + Unpack.unpack_4_32_32_8_8_Dyn_Destructive(packed); + assertEq(v0, got0, "output[0] bytes4"); + assertEq(v1, got1, "output[1] bytes32"); + assertEq(v2, got2, "output[2] bytes32"); + assertEq(v3, got3, "output[3] bytes8"); + assertEq(v4, got4, "output[4] bytes8"); + assertEq(v5, got5, "output[5] bytes memory"); + } + + function testUnpack_4_32_1(bytes4 v0, bytes32 v1, bytes1 v2) external pure { + bytes memory packed = abi.encodePacked(v0, v1, v2); + console.logBytes(packed); + + (bytes4 got0, bytes32 got1, bytes1 got2) = Unpack.unpack_4_32_1(packed); + assertEq(v0, got0, "output[0] bytes4"); + assertEq(v1, got1, "output[1] bytes32"); + assertEq(v2, got2, "output[2] bytes1"); + } + + function testUnpack_4_32_8_8(bytes4 v0, bytes32 v1, bytes8 v2, bytes8 v3) external pure { + bytes memory packed = abi.encodePacked(v0, v1, v2, v3); + console.logBytes(packed); + + (bytes4 got0, bytes32 got1, bytes8 got2, bytes8 got3) = Unpack.unpack_4_32_8_8(packed); + assertEq(v0, got0, "output[0] bytes4"); + assertEq(v1, got1, "output[1] bytes32"); + assertEq(v2, got2, "output[2] bytes8"); + assertEq(v3, got3, "output[3] bytes8"); + } + + function testUnpack_4_32_8(bytes4 v0, bytes32 v1, bytes8 v2) external pure { + bytes memory packed = abi.encodePacked(v0, v1, v2); + console.logBytes(packed); + + (bytes4 got0, bytes32 got1, bytes8 got2) = Unpack.unpack_4_32_8(packed); + assertEq(v0, got0, "output[0] bytes4"); + assertEq(v1, got1, "output[1] bytes32"); + assertEq(v2, got2, "output[2] bytes8"); + } + + function testUnpack_32_32_8_8_Dyn_Destructive( + bytes32 v0, + bytes32 v1, + bytes8 v2, + bytes8 v3, + bytes memory v4 + ) external pure { + bytes memory packed = abi.encodePacked(v0, v1, v2, v3, v4); + console.logBytes(packed); + + (bytes32 got0, bytes32 got1, bytes8 got2, bytes8 got3, bytes memory got4) = + Unpack.unpack_32_32_8_8_Dyn_Destructive(packed); + assertEq(v0, got0, "output[0] bytes32"); + assertEq(v1, got1, "output[1] bytes32"); + assertEq(v2, got2, "output[2] bytes8"); + assertEq(v3, got3, "output[3] bytes8"); + assertEq(v4, got4, "output[4] bytes memory"); + } +} diff --git a/contracts/staking/unpackgen.go b/contracts/staking/unpackgen.go new file mode 100644 index 000000000..57ab6fe9d --- /dev/null +++ b/contracts/staking/unpackgen.go @@ -0,0 +1,3 @@ +package staking + +//go:generate go run ../../utils/unpack/unpackgen --out=./Unpack.sol --test_out=./tests/Unpack.t.sol --byte_sizes=4,32,32,8,8,0;4,32,1;4,32,8,8;4,32,8;32,32,8,8,0 diff --git a/go.mod b/go.mod index 315e1f355..1f443f063 100644 --- a/go.mod +++ b/go.mod @@ -14,6 +14,7 @@ require ( github.com/onsi/gomega v1.34.1 github.com/pkg/errors v0.9.1 github.com/spf13/cobra v1.8.1 + github.com/spf13/pflag v1.0.5 github.com/stretchr/testify v1.9.0 go.uber.org/zap v1.27.0 ) @@ -108,7 +109,6 @@ require ( github.com/spf13/afero v1.9.5 // indirect github.com/spf13/cast v1.5.1 // indirect github.com/spf13/jwalterweatherman v1.1.0 // indirect - github.com/spf13/pflag v1.0.5 // indirect github.com/spf13/viper v1.16.0 // indirect github.com/status-im/keycard-go v0.2.0 // indirect github.com/subosito/gotenv v1.4.2 // indirect diff --git a/utils/unpack/Unpack.sol.gotmpl b/utils/unpack/Unpack.sol.gotmpl new file mode 100644 index 000000000..a8bf9d0d9 --- /dev/null +++ b/utils/unpack/Unpack.sol.gotmpl @@ -0,0 +1,69 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^{{if false}}0.8.25{{else}}0.8.0{{end}}; + +// GENERATED CODE - Do not edit + +/* solhint-disable no-inline-assembly */ +/* solhint-disable func-name-mixedcase */ + +library Unpack { + /// @dev Thrown if the input buffer to an unpack function is of the wrong length. + error IncorrectInputLength(uint256 expected, uint256 actual); + + /// @dev Thrown if the input buffer to an unpack function with dynamically sized output is too short. + error InsufficientInputLength(uint256 min, uint256 actual); + {{- range .Unpackers}} + + /** + * @notice Inverts `abi.encodePacked()` for the specific return types. + * @dev The originally packed inputs MUST be of the same types as those returned by this function, in the precise + * order, otherwise the output is undefined. + {{- if .HasDynamic}} + {{- if .UseMCopy}} + * @dev The returned `bytes memory` is freshly allocated, resulting in a memory expansion. + {{- else}} + * @dev This function takes ownership of and corrupts the `input` parameter to avoid memory expansion for the + * returned `bytes memory`. The returned array is owned by the caller. + {{- end}} + {{- end}} + * @param input Buffer returned by `abi.encodePacked()` + */ + function unpack_{{.FuncNameSuffix}}(bytes memory input) internal pure returns ({{.Returns}}) { + {{- $unpacker := .}} + {{- if .HasDynamic}} + if (input.length < {{.MinLength}}) { + revert InsufficientInputLength({{.MinLength}}, input.length); + } + {{- else}} + if (input.length != {{.BytesUntilDynamic}}) { + revert IncorrectInputLength(input.length, {{.Bytes}}); + } + {{- end}} + + assembly ("memory-safe") { + {{- range $i, $v := .Vars}} + {{- if .Dynamic}} + let length := mload(input) + let dynLength := sub(length, {{$unpacker.MinLength}}) + {{- if $unpacker.UseMCopy}} + v{{$i}} := mload(0x40) + mstore(0x40, add(v{{$i}}, add(0x20, dynLength))) + mstore(v{{$i}}, dynLength) + mcopy(add(v{{$i}}, 0x20), add(input, {{.OffsetHex}}), dynLength) + {{- else}} + v{{$i}} := add(input, {{.Offset}}) + mstore(v{{$i}}, dynLength) + {{- end}} + let end := add(input, add(length, 0x20)) + {{- else}} + {{- if .Front}} + v{{$i}} := mload(add(input, {{.OffsetHex}})) + {{- else}} + v{{$i}} := mload(sub(end, {{.OffsetHex}})) + {{- end}} + {{- end}} + {{- end}} + } + } + {{- end}} +} diff --git a/utils/unpack/Unpack.t.sol.gotmpl b/utils/unpack/Unpack.t.sol.gotmpl new file mode 100644 index 000000000..2b2bf6148 --- /dev/null +++ b/utils/unpack/Unpack.t.sol.gotmpl @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^{{if false}}0.8.25{{else}}0.8.0{{end}}; + +// GENERATED CODE - Do not edit + +import {Test} from "@forge-std/Test.sol"; +import {console} from "@forge-std/console.sol"; +import {Unpack} from "{{.RelPathFromTestToImpl}}"; + +/* solhint-disable func-name-mixedcase */ + +contract UnpackTest is Test { + {{- range .Unpackers}} + + function testUnpack_{{.FuncNameSuffix}}({{.Returns}}) external pure { + bytes memory packed = abi.encodePacked({{.EncodePackedArgs}}); + console.logBytes(packed); + + ({{.TestVars}}) = Unpack.unpack_{{.FuncNameSuffix}}(packed); + {{- range $i, $v := .Vars}} + assertEq(v{{$i}}, got{{$i}}, "output[{{$i}}] {{.Type}}"); + {{- end}} + } + {{- end}} +} diff --git a/utils/unpack/unpack.go b/utils/unpack/unpack.go new file mode 100644 index 000000000..b13d92da4 --- /dev/null +++ b/utils/unpack/unpack.go @@ -0,0 +1,284 @@ +// Package unpack generates Solidity code to invert `abi.encodePacked()` for +// known, unambiguous output sizes. +package unpack + +import ( + "errors" + "fmt" + "io" + "math" + "strings" + "text/template" + + _ "embed" +) + +var ( + //go:embed Unpack.sol.gotmpl + solTmplRaw string + //go:embed Unpack.t.sol.gotmpl + solTestTmplRaw string + solTmpl, solTestTmpl *template.Template +) + +func init() { + solTmpl = template.Must(template.New("sol").Parse(solTmplRaw)) + solTestTmpl = template.Must(template.New("solTest").Parse(solTestTmplRaw)) +} + +// Errors returned by [Generate]. +var ( + ErrZeroBytes = errors.New("zero bytes") + ErrMax32Bytes = errors.New("max 32 bytes") + ErrMultipleDynamic = errors.New("multiple unsized inputs") +) + +// Dynamic is a sentinel value, used instead of a number of bytes, indicating +// that an unpacked type has dynamic length. At most one Dynamic value can be +// used per generated unpack function. +const Dynamic = math.MaxUint + +// Generate generates implementations and tests for unpacking Solidity values +// encoded with `abi.encodePacked()`. Each slice of `[]uint` results in the +// generation of one `unpack_...()` function and MAY have at most one [Dynamic] +// size. +func Generate(impl, test io.Writer, relPathFromTestToImpl string, bytes ...[]uint) error { + us := make([]*unpacker, len(bytes)) + for i, bs := range bytes { + u, err := newUnpacker(bs...) + if err != nil { + return err + } + us[i] = u + } + + data := tmplData{ + RelPathFromTestToImpl: relPathFromTestToImpl, + Unpackers: us, + } + return errors.Join( + solTmpl.Execute(impl, data), + solTestTmpl.Execute(test, data), + ) +} + +type tmplData struct { + RelPathFromTestToImpl string + Unpackers []*unpacker +} + +// An unpacker defines all values required to generate a single `unpack_...()` +// function. +type unpacker struct { + Vars []output + HasDynamic bool + UseMCopy bool +} + +// An output defines a single output returned by an `unpack_...()` function. +type output struct { + end end + Offset uint // relative to `end` + Len uint // non-zero if `!Dynamic` + Dynamic bool +} + +type end uint + +const ( + front end = iota + 1 + back +) + +func newUnpacker(bytes ...uint) (*unpacker, error) { + u := &unpacker{ + Vars: make([]output, len(bytes)), + } + + for i, b := range bytes { + switch { + case b == 0: + return nil, ErrZeroBytes + case b == Dynamic: + if u.HasDynamic { + return nil, ErrMultipleDynamic + } + u.HasDynamic = true + case b > 32: + return nil, ErrMax32Bytes + } + + v := &u.Vars[i] + switch { + case b == Dynamic: + v.end = front + v.Offset = u.BytesUntilDynamic() + v.Dynamic = true + + case !u.HasDynamic: + v.end = front + v.Offset = u.BytesUntilDynamic() + + case u.HasDynamic: + v.end = back + + } + v.Len = b + } + if !u.HasDynamic { + return u, nil + } + + // Once a dynamically sized output exists, we can no longer calculate + // offsets from the front. + var offset uint + for i := len(u.Vars) - 1; i >= 0; i-- { + v := &u.Vars[i] + if v.Dynamic { + break + } + offset += v.Len + v.Offset = offset + } + return u, nil +} + +// UsesMCopy returns whether at least one unpack function uses the MCOPY op +// code. +func (d *tmplData) UsesMCopy() bool { + for _, u := range d.Unpackers { + if u.UseMCopy { + return true + } + } + return false +} + +// BytesUntilDynamic returns the total number of bytes before the first +// dynamically sized output, or until the end of the input buffer if all sizes +// are known in advance. +// +// While an `unpacker` is being constructed, this function returns only the +// already-parsed output sizes, which can be used for setting the offset of the +// next value. +func (u *unpacker) BytesUntilDynamic() uint { + var l uint + for _, v := range u.Vars { + if v.Dynamic { + break + } + l += v.Len + } + return l +} + +// Bytes is an alias of [BytesUntilDynamic] to aid in readability of the +// template. +func (u *unpacker) Bytes() uint { + return u.BytesUntilDynamic() +} + +// MinLength returns the minimum number of bytes that an input buffer MUST have +// to be unpacked. This is the sum of all non-dynamically sized outputs. +func (u *unpacker) MinLength() uint { + var n uint + for _, v := range u.Vars { + if !v.Dynamic { + n += v.Len + } + } + return n +} + +// mapVar maps u.Vars -> []string. +func (u *unpacker) mapVars(fn func(int, output) string) []string { + out := make([]string, len(u.Vars)) + for i, v := range u.Vars { + out[i] = fn(i, v) + } + return out +} + +// FuncNameSuffix returns the suffix appended to `unpack_` when naming the +// generated function. It concatenates all byte sizes, using the keyword "Dyn" +// for dynamically sized outputs. +// +// If the generated code doesn't use MCOPY it takes ownership of the input +// buffer in a destructive fashion. All such functions have the "_Destructive" +// suffix appended. +func (u *unpacker) FuncNameSuffix() string { + base := strings.Join( + u.mapVars(func(_ int, o output) string { + if o.Dynamic { + return "Dyn" + } + return fmt.Sprintf("%d", o.Len) + }), + "_", + ) + if !u.HasDynamic || u.UseMCopy { + return base + } + return fmt.Sprintf("%s_Destructive", base) +} + +// varPrefix is the prefix of all numerically identified variables in the +// generated code; i.e. for prefix v, the variables are v0, v1, v2... +const varPrefix = "v" + +// EncodePackedArgs returns the arguments to be passed to `abi.encodePacked()` +// in the generated test. +func (u *unpacker) EncodePackedArgs() string { + return strings.Join( + u.mapVars(func(i int, _ output) string { + return fmt.Sprintf("%s%d", varPrefix, i) + }), + ", ", + ) +} + +// Returns returns the return values of the generated unpack function. +func (u *unpacker) Returns() string { + return u.typedVars(varPrefix) +} + +// TestVars returns the variables under test in the generated test function. +func (u *unpacker) TestVars() string { + return u.typedVars("got") +} + +func (u *unpacker) typedVars(prefix string) string { + return strings.Join( + u.mapVars(func(i int, o output) string { + return fmt.Sprintf("%s %s%d", o.Type(), prefix, i) + }), + ", ", + ) +} + +// Type returns the Solidity type of the output variable. +func (o *output) Type() string { + if o.Dynamic { + return "bytes memory" + } + return fmt.Sprintf("bytes%d", o.Len) +} + +func (o *output) Front() bool { + switch o.end { + case front: + return true + case back: + return false + default: + panic(fmt.Sprintf("BUG: %T.end not set", o)) + } +} + +func (o *output) OffsetHex() string { + off := o.Offset + if o.end == front { + off += 32 + } + return fmt.Sprintf("%#02x", off) +} diff --git a/utils/unpack/unpackgen/unpackgen.go b/utils/unpack/unpackgen/unpackgen.go new file mode 100644 index 000000000..bf3dec327 --- /dev/null +++ b/utils/unpack/unpackgen/unpackgen.go @@ -0,0 +1,104 @@ +// The unpackgen binary generates Solidity code to invert `abi.encodePacked()` +// for known, unambiguous output sizes. See the [unpack] package for details. +package main + +import ( + "errors" + "fmt" + "os" + "path/filepath" + "strconv" + "strings" + + "github.com/spf13/pflag" + + "github.com/ava-labs/teleporter/utils/unpack" +) + +func main() { + implPath := pflag.String("out", "./Unpack.sol", "Output path to which the Solidity implementations are written") + testPath := pflag.String("test_out", "./Unpack.t.sol", "Output path to which the Solidity tests are written") + bytes := new(bytesFlag) + pflag.Var(bytes, "byte_sizes", "Semicolon-delimited list of groups of comma-delimited byte sizes. Use 0 for (at most one) dynamically sized byte array per group.") + + pflag.Parse() + + if err := run(*implPath, *testPath, bytes.val); err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } +} + +// run creates files at both paths and then calls `unpack.Generate()`. +func run(implPath, testPath string, bytes [][]uint) error { + impl, err := os.Create(implPath) + if err != nil { + return err + } + test, err := os.Create(testPath) + if err != nil { + return err + } + + rel, err := filepath.Rel(filepath.Dir(testPath), implPath) + if err != nil { + return fmt.Errorf("determine path from test to implementation: %v", err) + } + + if err := unpack.Generate(impl, test, rel, bytes...); err != nil { + return err + } + return errors.Join(impl.Close(), test.Close()) +} + +type bytesFlag struct { + val [][]uint +} + +var _ pflag.Value = (*bytesFlag)(nil) + +// Set splits `s` by semicolons then splits each result by commas, parsing all +// resulting values as uints. It trims whitespace. If a parsed value is 0 it is +// replaced with unpack.Dynamic. +func (f *bytesFlag) Set(s string) error { + groups := strings.Split(s, ";") + var val [][]uint + + for _, g := range groups { + var bytes []uint + for _, bStr := range strings.Split(g, ",") { + b, err := strconv.ParseUint(strings.TrimSpace(bStr), 10, 32) + if err != nil { + return err + } + if b == 0 { + b = unpack.Dynamic + } + bytes = append(bytes, uint(b)) + } + val = append(val, bytes) + } + + f.val = val + return nil +} + +// String is the inverse of `bytesFlag.Set()`. +func (f *bytesFlag) String() string { + var parts []string + for _, grp := range f.val { + var vs []string + for _, v := range grp { + if v == unpack.Dynamic { + v = 0 + } + vs = append(vs, fmt.Sprintf("%d", v)) + } + parts = append(parts, strings.Join(vs, ",")) + } + return strings.Join(parts, ";") +} + +func (f *bytesFlag) Type() string { + return fmt.Sprintf("%T", *f) +} From c9e28b6f6555b778e393ca1f4038b68f2aa8b7af Mon Sep 17 00:00:00 2001 From: Arran Schlosberg Date: Fri, 9 Aug 2024 13:45:32 +0100 Subject: [PATCH 13/27] fix: `solc` pragma `^0.8.0` unless using `mcopy` then `^0.8.25` --- utils/unpack/Unpack.sol.gotmpl | 2 +- utils/unpack/Unpack.t.sol.gotmpl | 2 +- utils/unpack/unpack.go | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/utils/unpack/Unpack.sol.gotmpl b/utils/unpack/Unpack.sol.gotmpl index a8bf9d0d9..76dd1ae0d 100644 --- a/utils/unpack/Unpack.sol.gotmpl +++ b/utils/unpack/Unpack.sol.gotmpl @@ -1,5 +1,5 @@ // SPDX-License-Identifier: UNLICENSED -pragma solidity ^{{if false}}0.8.25{{else}}0.8.0{{end}}; +pragma solidity ^{{if .UsesMCopy}}0.8.25{{else}}0.8.0{{end}}; // GENERATED CODE - Do not edit diff --git a/utils/unpack/Unpack.t.sol.gotmpl b/utils/unpack/Unpack.t.sol.gotmpl index 2b2bf6148..1501c0ef7 100644 --- a/utils/unpack/Unpack.t.sol.gotmpl +++ b/utils/unpack/Unpack.t.sol.gotmpl @@ -1,5 +1,5 @@ // SPDX-License-Identifier: UNLICENSED -pragma solidity ^{{if false}}0.8.25{{else}}0.8.0{{end}}; +pragma solidity ^{{if .UsesMCopy}}0.8.25{{else}}0.8.0{{end}}; // GENERATED CODE - Do not edit diff --git a/utils/unpack/unpack.go b/utils/unpack/unpack.go index b13d92da4..8a4f86824 100644 --- a/utils/unpack/unpack.go +++ b/utils/unpack/unpack.go @@ -52,7 +52,7 @@ func Generate(impl, test io.Writer, relPathFromTestToImpl string, bytes ...[]uin us[i] = u } - data := tmplData{ + data := &tmplData{ RelPathFromTestToImpl: relPathFromTestToImpl, Unpackers: us, } From 1c2ad1ea2b2c74ed85e02440e96b14d01cda934b Mon Sep 17 00:00:00 2001 From: Arran Schlosberg Date: Fri, 9 Aug 2024 13:50:52 +0100 Subject: [PATCH 14/27] fix: remove unused variable when dynamically sized at end --- contracts/staking/Unpack.sol | 2 -- utils/unpack/Unpack.sol.gotmpl | 2 ++ utils/unpack/unpack.go | 4 ++++ 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/contracts/staking/Unpack.sol b/contracts/staking/Unpack.sol index 0286d1679..adbf8b83e 100644 --- a/contracts/staking/Unpack.sol +++ b/contracts/staking/Unpack.sol @@ -40,7 +40,6 @@ library Unpack { let dynLength := sub(length, 84) v5 := add(input, 84) mstore(v5, dynLength) - let end := add(input, add(length, 0x20)) } } @@ -137,7 +136,6 @@ library Unpack { let dynLength := sub(length, 80) v4 := add(input, 80) mstore(v4, dynLength) - let end := add(input, add(length, 0x20)) } } } diff --git a/utils/unpack/Unpack.sol.gotmpl b/utils/unpack/Unpack.sol.gotmpl index 76dd1ae0d..76058fad9 100644 --- a/utils/unpack/Unpack.sol.gotmpl +++ b/utils/unpack/Unpack.sol.gotmpl @@ -54,7 +54,9 @@ library Unpack { v{{$i}} := add(input, {{.Offset}}) mstore(v{{$i}}, dynLength) {{- end}} + {{- if not ($unpacker.IsLastVar $i)}} let end := add(input, add(length, 0x20)) + {{- end}} {{- else}} {{- if .Front}} v{{$i}} := mload(add(input, {{.OffsetHex}})) diff --git a/utils/unpack/unpack.go b/utils/unpack/unpack.go index 8a4f86824..e3bb64993 100644 --- a/utils/unpack/unpack.go +++ b/utils/unpack/unpack.go @@ -222,6 +222,10 @@ func (u *unpacker) FuncNameSuffix() string { return fmt.Sprintf("%s_Destructive", base) } +func (u *unpacker) IsLastVar(i int) bool { + return i >= len(u.Vars)-1 +} + // varPrefix is the prefix of all numerically identified variables in the // generated code; i.e. for prefix v, the variables are v0, v1, v2... const varPrefix = "v" From 7f98e2a91a6267130a23547cb3a61ddb31194276 Mon Sep 17 00:00:00 2001 From: Arran Schlosberg Date: Fri, 9 Aug 2024 13:52:40 +0100 Subject: [PATCH 15/27] chore: add copyright notices --- contracts/staking/Unpack.sol | 2 ++ contracts/staking/tests/Unpack.t.sol | 2 ++ utils/unpack/Unpack.sol.gotmpl | 2 ++ utils/unpack/Unpack.t.sol.gotmpl | 2 ++ utils/unpack/unpack.go | 3 +++ utils/unpack/unpackgen/unpackgen.go | 3 +++ 6 files changed, 14 insertions(+) diff --git a/contracts/staking/Unpack.sol b/contracts/staking/Unpack.sol index adbf8b83e..773286398 100644 --- a/contracts/staking/Unpack.sol +++ b/contracts/staking/Unpack.sol @@ -1,3 +1,5 @@ +// (c) 2024, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. // SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.0; diff --git a/contracts/staking/tests/Unpack.t.sol b/contracts/staking/tests/Unpack.t.sol index eae08ddc1..1d89d3e93 100644 --- a/contracts/staking/tests/Unpack.t.sol +++ b/contracts/staking/tests/Unpack.t.sol @@ -1,3 +1,5 @@ +// (c) 2024, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. // SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.0; diff --git a/utils/unpack/Unpack.sol.gotmpl b/utils/unpack/Unpack.sol.gotmpl index 76058fad9..ca7384c5e 100644 --- a/utils/unpack/Unpack.sol.gotmpl +++ b/utils/unpack/Unpack.sol.gotmpl @@ -1,3 +1,5 @@ +// (c) 2024, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. // SPDX-License-Identifier: UNLICENSED pragma solidity ^{{if .UsesMCopy}}0.8.25{{else}}0.8.0{{end}}; diff --git a/utils/unpack/Unpack.t.sol.gotmpl b/utils/unpack/Unpack.t.sol.gotmpl index 1501c0ef7..70915712d 100644 --- a/utils/unpack/Unpack.t.sol.gotmpl +++ b/utils/unpack/Unpack.t.sol.gotmpl @@ -1,3 +1,5 @@ +// (c) 2024, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. // SPDX-License-Identifier: UNLICENSED pragma solidity ^{{if .UsesMCopy}}0.8.25{{else}}0.8.0{{end}}; diff --git a/utils/unpack/unpack.go b/utils/unpack/unpack.go index e3bb64993..b8d1710e8 100644 --- a/utils/unpack/unpack.go +++ b/utils/unpack/unpack.go @@ -1,3 +1,6 @@ +// (c) 2024, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. +// // Package unpack generates Solidity code to invert `abi.encodePacked()` for // known, unambiguous output sizes. package unpack diff --git a/utils/unpack/unpackgen/unpackgen.go b/utils/unpack/unpackgen/unpackgen.go index bf3dec327..c2127f405 100644 --- a/utils/unpack/unpackgen/unpackgen.go +++ b/utils/unpack/unpackgen/unpackgen.go @@ -1,3 +1,6 @@ +// (c) 2024, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. +// // The unpackgen binary generates Solidity code to invert `abi.encodePacked()` // for known, unambiguous output sizes. See the [unpack] package for details. package main From ee4bbf6ee50a3aa5bc3159b0c13e805476a12f16 Mon Sep 17 00:00:00 2001 From: Arran Schlosberg Date: Fri, 9 Aug 2024 14:20:02 +0100 Subject: [PATCH 16/27] chore: placate the linters... ssshhhhh --- contracts/staking/Unpack.sol | 7 ++++--- contracts/staking/tests/Unpack.t.sol | 8 +++++--- utils/unpack/Unpack.sol.gotmpl | 7 ++++--- utils/unpack/Unpack.t.sol.gotmpl | 8 +++++--- utils/unpack/unpack.go | 1 - 5 files changed, 18 insertions(+), 13 deletions(-) diff --git a/contracts/staking/Unpack.sol b/contracts/staking/Unpack.sol index 773286398..e427dd023 100644 --- a/contracts/staking/Unpack.sol +++ b/contracts/staking/Unpack.sol @@ -1,12 +1,13 @@ // (c) 2024, Ava Labs, Inc. All rights reserved. // See the file LICENSE for licensing terms. // SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.8.0; +pragma solidity ^0.8.0; // solhint-disable-line compiler-version // GENERATED CODE - Do not edit -/* solhint-disable no-inline-assembly */ -/* solhint-disable func-name-mixedcase */ +// solhint-disable no-inline-assembly +// Mixed-case can't apply to numbers and an underscore is the most natural separator +// solhint-disable func-name-mixedcase library Unpack { /// @dev Thrown if the input buffer to an unpack function is of the wrong length. diff --git a/contracts/staking/tests/Unpack.t.sol b/contracts/staking/tests/Unpack.t.sol index 1d89d3e93..08fa62838 100644 --- a/contracts/staking/tests/Unpack.t.sol +++ b/contracts/staking/tests/Unpack.t.sol @@ -1,16 +1,18 @@ // (c) 2024, Ava Labs, Inc. All rights reserved. // See the file LICENSE for licensing terms. // SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.8.0; +pragma solidity ^0.8.0; // solhint-disable-line compiler-version // GENERATED CODE - Do not edit +// Console logging is useful for debug information in _tests_. +// solhint-disable no-console +// solhint-disable func-name-mixedcase + import {Test} from "@forge-std/Test.sol"; import {console} from "@forge-std/console.sol"; import {Unpack} from "../Unpack.sol"; -/* solhint-disable func-name-mixedcase */ - contract UnpackTest is Test { function testUnpack_4_32_32_8_8_Dyn_Destructive( bytes4 v0, diff --git a/utils/unpack/Unpack.sol.gotmpl b/utils/unpack/Unpack.sol.gotmpl index ca7384c5e..298e38957 100644 --- a/utils/unpack/Unpack.sol.gotmpl +++ b/utils/unpack/Unpack.sol.gotmpl @@ -1,12 +1,13 @@ // (c) 2024, Ava Labs, Inc. All rights reserved. // See the file LICENSE for licensing terms. // SPDX-License-Identifier: UNLICENSED -pragma solidity ^{{if .UsesMCopy}}0.8.25{{else}}0.8.0{{end}}; +pragma solidity ^{{if .UsesMCopy}}0.8.25{{else}}0.8.0{{end}}; // solhint-disable-line compiler-version // GENERATED CODE - Do not edit -/* solhint-disable no-inline-assembly */ -/* solhint-disable func-name-mixedcase */ +// solhint-disable no-inline-assembly +// Mixed-case can't apply to numbers and an underscore is the most natural separator +// solhint-disable func-name-mixedcase library Unpack { /// @dev Thrown if the input buffer to an unpack function is of the wrong length. diff --git a/utils/unpack/Unpack.t.sol.gotmpl b/utils/unpack/Unpack.t.sol.gotmpl index 70915712d..47f3f3657 100644 --- a/utils/unpack/Unpack.t.sol.gotmpl +++ b/utils/unpack/Unpack.t.sol.gotmpl @@ -1,16 +1,18 @@ // (c) 2024, Ava Labs, Inc. All rights reserved. // See the file LICENSE for licensing terms. // SPDX-License-Identifier: UNLICENSED -pragma solidity ^{{if .UsesMCopy}}0.8.25{{else}}0.8.0{{end}}; +pragma solidity ^{{if .UsesMCopy}}0.8.25{{else}}0.8.0{{end}}; // solhint-disable-line compiler-version // GENERATED CODE - Do not edit +// Console logging is useful for debug information in _tests_. +// solhint-disable no-console +// solhint-disable func-name-mixedcase + import {Test} from "@forge-std/Test.sol"; import {console} from "@forge-std/console.sol"; import {Unpack} from "{{.RelPathFromTestToImpl}}"; -/* solhint-disable func-name-mixedcase */ - contract UnpackTest is Test { {{- range .Unpackers}} diff --git a/utils/unpack/unpack.go b/utils/unpack/unpack.go index b8d1710e8..07162c341 100644 --- a/utils/unpack/unpack.go +++ b/utils/unpack/unpack.go @@ -124,7 +124,6 @@ func newUnpacker(bytes ...uint) (*unpacker, error) { case u.HasDynamic: v.end = back - } v.Len = b } From 3bb7bb6f944188d56bb3c31c6b0d8da648bd454f Mon Sep 17 00:00:00 2001 From: Arran Schlosberg Date: Fri, 9 Aug 2024 14:41:43 +0100 Subject: [PATCH 17/27] chore: remove obsolete test of equivalence --- .../staking/tests/ManualStakingMessages.sol | 289 ------------------ contracts/staking/tests/StakingMessages.t.sol | 68 ----- 2 files changed, 357 deletions(-) delete mode 100644 contracts/staking/tests/ManualStakingMessages.sol delete mode 100644 contracts/staking/tests/StakingMessages.t.sol diff --git a/contracts/staking/tests/ManualStakingMessages.sol b/contracts/staking/tests/ManualStakingMessages.sol deleted file mode 100644 index 3d6698b89..000000000 --- a/contracts/staking/tests/ManualStakingMessages.sol +++ /dev/null @@ -1,289 +0,0 @@ -// (c) 2023, Ava Labs, Inc. All rights reserved. -// See the file LICENSE for licensing terms. - -// SPDX-License-Identifier: Ecosystem -pragma solidity 0.8.25; - -library StakingMessages { - // The information that uniquely identifies a subnet validation period. - // The SHA-256 hash of the concatenation of these field is the validationID. - struct ValidationInfo { - bytes32 subnetID; - bytes32 nodeID; - uint64 weight; - uint64 registrationExpiry; - bytes signature; - } - - // Subnets send a RegisterSubnetValidator message to the P-Chain to register a validator. - // The P-Chain responds with a RegisterSubnetValidator message indicating whether the registration was successful - // for the given validation ID. - uint32 internal constant SUBNET_VALIDATOR_REGISTRATION_MESSAGE_TYPE_ID = 1; - // Subnets can send a SetSubnetValidatorWeight message to the P-Chain to update a validator's weight. - // The P-Chain responds with a SetSubnetValidatorWeight message acknowledging the weight update. - uint32 internal constant SET_SUBNET_VALIDATOR_WEIGHT_MESSAGE_TYPE_ID = 2; - // The Subnet will self-sign a ValidationUptimeMessage to be provided when a validator is initiating - // the end of their validation period. - uint32 internal constant VALIDATION_UPTIME_MESSAGE_TYPE_ID = 3; - - // TODO: The implemenation of these packing and unpacking functions is neither tested or optimzied at all. - // Full test coverage should be provided, and the implementation should be optimized for gas efficiency. - - /** - * @notice Packs a RegisterSubnetValidator message into a byte array. - * The message format specification is: - * +-----------+----------+-----------+ - * | typeID : uint32 | 4 bytes | - * +-----------+----------+-----------+ - * | subnetID : [32]byte | 32 bytes | - * +-----------+----------+-----------+ - * | nodeID : [32]byte | 32 bytes | - * +-----------+----------+-----------+ - * | weight : uint64 | 8 bytes | - * +-----------+----------+-----------+ - * | expiry : uint64 | 8 bytes | - * +-----------+----------+-----------+ - * | signature : [64]byte | 64 bytes | - * +-----------+----------+-----------+ - * | 148 bytes | - * +-----------+ - */ - function packRegisterSubnetValidatorMessage(ValidationInfo memory valiationInfo) - internal - pure - returns (bytes32, bytes memory) - { - (bytes32 validationID, bytes memory serializedValidationInfo) = - packValidationInfo(valiationInfo); - - bytes memory res = new bytes(148); - // Pack the message type - for (uint256 i; i < 4; ++i) { - res[i] = bytes1(uint8(SUBNET_VALIDATOR_REGISTRATION_MESSAGE_TYPE_ID >> (8 * (3 - i)))); - } - // Pack the validation info - for (uint256 i; i < 144; ++i) { - res[i + 4] = serializedValidationInfo[i]; - } - - return (validationID, res); - } - - /** - * @notice Unpacks a byte array as a RegisterSubnetValidator message. - * The message format specification is: - * +--------------+----------+----------+ - * | typeID : uint32 | 4 bytes | - * +--------------+----------+----------+ - * | validationID : [32]byte | 32 bytes | - * +--------------+----------+----------+ - * | valid : bool + 1 byte | - * +--------------+----------+----------+ - * | 37 bytes | - * +----------+ - * @return The validationID and whether or the validation period was registered - * or is not a validator and never will be a validator to do the expiry time passing. - */ - function unpackSubnetValidatorRegistrationMessage(bytes memory input) - internal - pure - returns (bytes32, bool) - { - require(input.length == 37, "StakingMessages: Invalid message length"); - - // Unpack the type ID - uint32 typeID; - for (uint256 i; i < 4; ++i) { - typeID |= uint32(uint8(input[i])) << uint32((8 * (3 - i))); - } - require( - typeID == SUBNET_VALIDATOR_REGISTRATION_MESSAGE_TYPE_ID, - "StakingMessages: Invalid message type" - ); - - // Unpack the validation ID. - bytes32 validationID; - for (uint256 i; i < 32; ++i) { - validationID |= bytes32(uint256(uint8(input[i + 4])) << (8 * (31 - i))); - } - - // Unpack the validity - bool valid = input[36] != 0; - - return (validationID, valid); - } - - /** - * @notice Packs a SetSubnetValidatorWeight message into a byte array. - * The message format specification is: - * +--------------+----------+----------+ - * | typeID : uint32 | 4 bytes | - * +--------------+----------+----------+ - * | validationID : [32]byte | 32 bytes | - * +--------------+----------+----------+ - * | nonce : uint64 | 8 bytes | - * +--------------+----------+----------+ - * | weight : uint64 | 8 bytes | - * +--------------+----------+----------+ - * | 52 bytes | - * +----------+ - */ - function packSetSubnetValidatorWeightMessage( - bytes32 validationID, - uint64 nonce, - uint64 weight - ) internal pure returns (bytes memory) { - bytes memory res = new bytes(52); - // Pack the type ID. - for (uint256 i; i < 4; ++i) { - res[i] = bytes1(uint8(SET_SUBNET_VALIDATOR_WEIGHT_MESSAGE_TYPE_ID >> (8 * (3 - i)))); - } - // Pack the validation ID. - for (uint256 i; i < 32; ++i) { - res[i + 4] = bytes1(uint8(uint256(validationID >> (8 * (31 - i))))); - } - // Pack the nonce. - for (uint256 i; i < 8; ++i) { - res[i + 36] = bytes1(uint8(nonce >> (8 * (7 - i)))); - } - // Pack the weight. - for (uint256 i; i < 8; ++i) { - res[i + 44] = bytes1(uint8(weight >> (8 * (7 - i)))); - } - return res; - } - - /** - * @notice Unpacks a byte array as a SetSubnetValidatorWeight message. - * The message format specification is the same as the one used in above for packing. - */ - function unpackSetSubnetValidatorWeightMessage(bytes memory input) - internal - pure - returns (bytes32, uint64, uint64) - { - require(input.length == 52, "StakingMessages: Invalid message length"); - - // Unpack the type ID. - uint32 typeID; - for (uint256 i; i < 4; ++i) { - typeID |= uint32(uint8(input[i])) << uint32((8 * (3 - i))); - } - require( - typeID == SET_SUBNET_VALIDATOR_WEIGHT_MESSAGE_TYPE_ID, - "StakingMessages: Invalid message type" - ); - - // Unpack the validation ID. - bytes32 validationID; - for (uint256 i; i < 32; ++i) { - validationID |= bytes32(uint256(uint8(input[i + 4])) << (8 * (31 - i))); - } - - // Unpack the nonce. - uint64 nonce; - for (uint256 i; i < 8; ++i) { - nonce |= uint64(uint8(input[i + 36])) << uint64((8 * (7 - i))); - } - - // Unpack the weight. - uint64 weight; - for (uint256 i; i < 8; ++i) { - weight |= uint64(uint8(input[i + 44])) << uint64((8 * (7 - i))); - } - - return (validationID, nonce, weight); - } - - /** - * @notice Unpacks a byte array as a ValidationUptimeMessage. - * The message format specification is: - * +--------------+----------+----------+ - * | typeID : uint32 | 4 bytes | - * +--------------+----------+----------+ - * | validationID : [32]byte | 32 bytes | - * +--------------+----------+----------+ - * | uptime : uint64 | 8 bytes | - * +--------------+----------+----------+ - * | 44 bytes | - * +----------+ - */ - function unpackValidationUptimeMessage(bytes memory input) - internal - pure - returns (bytes32, uint64) - { - require(input.length == 44, "StakingMessages: Invalid message length"); - - // Unpack the type ID. - uint32 typeID; - for (uint256 i; i < 4; ++i) { - typeID |= uint32(uint8(input[i])) << uint32((8 * (3 - i))); - } - require( - typeID == VALIDATION_UPTIME_MESSAGE_TYPE_ID, "StakingMessages: Invalid message type" - ); - - // Unpack the validation ID. - bytes32 validationID; - for (uint256 i; i < 32; ++i) { - validationID |= bytes32(uint256(uint8(input[i + 4])) << (8 * (31 - i))); - } - - // Unpack the uptime. - uint64 uptime; - for (uint256 i; i < 8; ++i) { - uptime |= uint64(uint8(input[i + 36])) << uint64((8 * (7 - i))); - } - - return (validationID, uptime); - } - - /** - * @notice Packs all of the information pertaining to a validation period into a byte array. - * The packed data is used to calculate the validationID as the SHA-256 hash of the packed data. - * The specification of the packed data is: - * +-----------+----------+-----------+ - * | subnetID : [32]byte | 32 bytes | - * +-----------+----------+-----------+ - * | nodeID : [32]byte | 32 bytes | - * +-----------+----------+-----------+ - * | weight : uint64 | 8 bytes | - * +-----------+----------+-----------+ - * | expiry : uint64 | 8 bytes | - * +-----------+----------+-----------+ - * | signature : [64]byte | 64 bytes | - * +-----------+----------+-----------+ - * | 144 bytes | - * +-----------+ - */ - function packValidationInfo(ValidationInfo memory validationInfo) - internal - pure - returns (bytes32, bytes memory) - { - require(validationInfo.signature.length == 64, "StakingMessages: Invalid signature length"); - bytes memory res = new bytes(144); - // Pack the subnetID - for (uint256 i; i < 32; ++i) { - res[i] = validationInfo.subnetID[i]; - } - // Pack the nodeID - for (uint256 i; i < 32; ++i) { - res[i + 32] = validationInfo.nodeID[i]; - } - // Pack the weight - for (uint256 i; i < 8; ++i) { - res[i + 64] = bytes1(uint8(validationInfo.weight >> uint8((8 * (7 - i))))); - } - // Pack the registration expiry - for (uint256 i; i < 8; ++i) { - res[i + 72] = bytes1(uint8(validationInfo.registrationExpiry >> uint64((8 * (7 - i))))); - } - // Pack the signature - for (uint256 i; i < 64; ++i) { - res[i + 80] = validationInfo.signature[i]; - } - return (sha256(res), res); - } -} diff --git a/contracts/staking/tests/StakingMessages.t.sol b/contracts/staking/tests/StakingMessages.t.sol deleted file mode 100644 index 46c18616a..000000000 --- a/contracts/staking/tests/StakingMessages.t.sol +++ /dev/null @@ -1,68 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.25; - -import {Test} from "@forge-std/Test.sol"; -import {StakingMessages} from "../StakingMessages.sol"; -import {StakingMessages as Original} from "./ManualStakingMessages.sol"; - -contract StakingMessagesTest is Test { - function testSubnetValidatorWeightPackRoundTrip( - bytes32 validationID, - uint64 nonce, - uint64 weight - ) public view { - uint256 startGas; - uint256 endGas; - - startGas = gasleft(); - bytes memory original = - Original.packSetSubnetValidatorWeightMessage(validationID, nonce, weight); - endGas = gasleft(); - uint256 originalGas = startGas - endGas; - - startGas = gasleft(); - bytes memory packed = - StakingMessages.packSetSubnetValidatorWeightMessage(validationID, nonce, weight); - endGas = gasleft(); - // Doing this after the original will actually penalise it because - // memory expansion is quadratic, so the gas saving is higher than the - // test suggests. - uint256 gas = startGas - endGas; - - assertEq(original, packed, "same data"); - assertGe(originalGas - gas, 19_500, "gas saving"); - assertLe(gas, 250, "gas cost"); - - (bytes32 gotValidationID, uint64 gotNonce, uint64 gotWeight) = - StakingMessages.unpackSetSubnetValidatorWeightMessage(packed); - - assertEq(validationID, gotValidationID, "validation ID"); - assertEq(nonce, gotNonce, "nonce"); - assertEq(weight, gotWeight, "weight"); - } - - function testUnpackSubnetValidatorWeightGas( - bytes32 validationID, - uint64 nonce, - uint64 weight - ) public view { - bytes memory buffer = - StakingMessages.packSetSubnetValidatorWeightMessage(validationID, nonce, weight); - - uint256 startGas; - uint256 endGas; - - startGas = gasleft(); - StakingMessages.unpackSetSubnetValidatorWeightMessage(buffer); - endGas = gasleft(); - uint256 gas = startGas - endGas; - - startGas = gasleft(); - Original.unpackSetSubnetValidatorWeightMessage(buffer); - endGas = gasleft(); - uint256 originalGas = startGas - endGas; - - assertGe(originalGas - gas, 18_000, "gas saving"); - assertLe(gas, 350, "gas cost"); - } -} From 34f629fb734c8846912583b6df08706459b7fb3d Mon Sep 17 00:00:00 2001 From: Arran Schlosberg Date: Fri, 9 Aug 2024 14:49:46 +0100 Subject: [PATCH 18/27] refactor: `abi.encodePacked()` and `Unpack.unpack_...()` all the things --- contracts/staking/StakingMessages.sol | 115 ++++---------------------- 1 file changed, 18 insertions(+), 97 deletions(-) diff --git a/contracts/staking/StakingMessages.sol b/contracts/staking/StakingMessages.sol index 82fe8e879..11aa929fa 100644 --- a/contracts/staking/StakingMessages.sol +++ b/contracts/staking/StakingMessages.sol @@ -77,53 +77,26 @@ library StakingMessages { pure returns (ValidationInfo memory) { - require(input.length == 148, "StakingMessages: Invalid message length"); + ( + bytes4 typeID, + bytes32 subnetID, + bytes32 nodeID, + bytes8 weight, + bytes8 expiry, + bytes memory signature + ) = Unpack.unpack_4_32_32_8_8_Dyn_Destructive(input); - // Unpack the type ID - uint32 typeID; - for (uint256 i; i < 4; ++i) { - typeID |= uint32(uint8(input[i])) << uint32((8 * (3 - i))); - } require( uint32(typeID) == SUBNET_VALIDATOR_REGISTRATION_MESSAGE_TYPE_ID, "StakingMessages: Invalid message type" ); - - // Unpack the subnet ID - bytes32 subnetID; - for (uint256 i; i < 32; ++i) { - subnetID |= bytes32(uint256(uint8(input[i + 4])) << (8 * (31 - i))); - } - - // Unpack the node ID - bytes32 nodeID; - for (uint256 i; i < 32; ++i) { - nodeID |= bytes32(uint256(uint8(input[i + 36])) << (8 * (31 - i))); - } - - // Unpack the weight - uint64 weight; - for (uint256 i; i < 8; ++i) { - weight |= uint64(uint8(input[i + 68])) << uint64((8 * (7 - i))); - } - - // Unpack the expiry - uint64 expiry; - for (uint256 i; i < 8; ++i) { - expiry |= uint64(uint8(input[i + 76])) << uint64((8 * (7 - i))); - } - - // Unpack the signature - bytes memory signature = new bytes(64); - for (uint256 i; i < 64; ++i) { - signature[i] = input[i + 84]; - } + require(signature.length == 64, "StakingMessages: Invalid unpacked signature length"); return ValidationInfo({ subnetID: subnetID, nodeID: nodeID, - weight: weight, - registrationExpiry: expiry, + weight: uint64(weight), + registrationExpiry: uint64(expiry), signature: signature }); } @@ -150,18 +123,7 @@ library StakingMessages { bytes32 validationID, bool valid ) internal pure returns (bytes memory) { - bytes memory res = new bytes(37); - // Pack the type ID. - for (uint256 i; i < 4; ++i) { - res[i] = bytes1(uint8(SUBNET_VALIDATOR_REGISTRATION_MESSAGE_TYPE_ID >> (8 * (3 - i)))); - } - // Pack the validation ID. - for (uint256 i; i < 32; ++i) { - res[i + 4] = bytes1(uint8(uint256(validationID >> (8 * (31 - i))))); - } - // Pack the validity. - res[36] = bytes1(valid ? 1 : 0); - return res; + return abi.encodePacked(SUBNET_VALIDATOR_REGISTRATION_MESSAGE_TYPE_ID, validationID, valid); } /** @@ -257,20 +219,7 @@ library StakingMessages { bytes32 validationID, uint64 uptime ) internal pure returns (bytes memory) { - bytes memory res = new bytes(44); - // Pack the type ID. - for (uint256 i; i < 4; ++i) { - res[i] = bytes1(uint8(VALIDATION_UPTIME_MESSAGE_TYPE_ID >> (8 * (3 - i)))); - } - // Pack the validation ID. - for (uint256 i; i < 32; ++i) { - res[i + 4] = bytes1(uint8(uint256(validationID >> (8 * (31 - i))))); - } - // Pack the uptime. - for (uint256 i; i < 8; ++i) { - res[i + 36] = bytes1(uint8(uptime >> (8 * (7 - i)))); - } - return res; + return abi.encodePacked(VALIDATION_UPTIME_MESSAGE_TYPE_ID, validationID, uptime); } /** @@ -343,43 +292,15 @@ library StakingMessages { pure returns (ValidationInfo memory) { - require(input.length == 144, "StakingMessages: Invalid message length"); - - // Unpack the subnetID - bytes32 subnetID; - for (uint256 i; i < 32; ++i) { - subnetID |= bytes32(uint256(uint8(input[i])) << (8 * (31 - i))); - } - - // Unpack the nodeID - bytes32 nodeID; - for (uint256 i; i < 32; ++i) { - nodeID |= bytes32(uint256(uint8(input[i + 32])) << (8 * (31 - i))); - } - - // Unpack the weight - uint64 weight; - for (uint256 i; i < 8; ++i) { - weight |= uint64(uint8(input[i + 64])) << uint64((8 * (7 - i))); - } - - // Unpack the registration expiry - uint64 expiry; - for (uint256 i; i < 8; ++i) { - expiry |= uint64(uint8(input[i + 72])) << uint64((8 * (7 - i))); - } - - // Unpack the signature - bytes memory signature = new bytes(64); - for (uint256 i; i < 64; ++i) { - signature[i] = input[i + 80]; - } + (bytes32 subnetID, bytes32 nodeID, bytes8 weight, bytes8 expiry, bytes memory signature) = + Unpack.unpack_32_32_8_8_Dyn_Destructive(input); + require(signature.length == 64, "StakingMessages: Invalid unpacked signature length"); return ValidationInfo({ subnetID: subnetID, nodeID: nodeID, - weight: weight, - registrationExpiry: expiry, + weight: uint64(weight), + registrationExpiry: uint64(expiry), signature: signature }); } From f32bbcf32485fdcb1c8e52282a18a1214f4548fa Mon Sep 17 00:00:00 2001 From: Arran Schlosberg Date: Fri, 9 Aug 2024 15:11:15 +0100 Subject: [PATCH 19/27] chore: make Slither keep quiet --- contracts/staking/Unpack.sol | 7 +++++++ contracts/staking/tests/Unpack.t.sol | 1 + utils/unpack/Unpack.sol.gotmpl | 3 +++ utils/unpack/Unpack.t.sol.gotmpl | 1 + 4 files changed, 12 insertions(+) diff --git a/contracts/staking/Unpack.sol b/contracts/staking/Unpack.sol index e427dd023..6f1890a15 100644 --- a/contracts/staking/Unpack.sol +++ b/contracts/staking/Unpack.sol @@ -1,11 +1,13 @@ // (c) 2024, Ava Labs, Inc. All rights reserved. // See the file LICENSE for licensing terms. // SPDX-License-Identifier: UNLICENSED +// slither-disable-next-line solc-version pragma solidity ^0.8.0; // solhint-disable-line compiler-version // GENERATED CODE - Do not edit // solhint-disable no-inline-assembly +// slither-disable-start assembly // Mixed-case can't apply to numbers and an underscore is the most natural separator // solhint-disable func-name-mixedcase @@ -24,6 +26,7 @@ library Unpack { * returned `bytes memory`. The returned array is owned by the caller. * @param input Buffer returned by `abi.encodePacked()` */ + // slither-disable-next-line naming-convention function unpack_4_32_32_8_8_Dyn_Destructive(bytes memory input) internal pure @@ -52,6 +55,7 @@ library Unpack { * order, otherwise the output is undefined. * @param input Buffer returned by `abi.encodePacked()` */ + // slither-disable-next-line naming-convention function unpack_4_32_1(bytes memory input) internal pure @@ -74,6 +78,7 @@ library Unpack { * order, otherwise the output is undefined. * @param input Buffer returned by `abi.encodePacked()` */ + // slither-disable-next-line naming-convention function unpack_4_32_8_8(bytes memory input) internal pure @@ -97,6 +102,7 @@ library Unpack { * order, otherwise the output is undefined. * @param input Buffer returned by `abi.encodePacked()` */ + // slither-disable-next-line naming-convention function unpack_4_32_8(bytes memory input) internal pure @@ -121,6 +127,7 @@ library Unpack { * returned `bytes memory`. The returned array is owned by the caller. * @param input Buffer returned by `abi.encodePacked()` */ + // slither-disable-next-line naming-convention function unpack_32_32_8_8_Dyn_Destructive(bytes memory input) internal pure diff --git a/contracts/staking/tests/Unpack.t.sol b/contracts/staking/tests/Unpack.t.sol index 08fa62838..4b0f5f08c 100644 --- a/contracts/staking/tests/Unpack.t.sol +++ b/contracts/staking/tests/Unpack.t.sol @@ -1,6 +1,7 @@ // (c) 2024, Ava Labs, Inc. All rights reserved. // See the file LICENSE for licensing terms. // SPDX-License-Identifier: UNLICENSED +// slither-disable-next-line solc-version pragma solidity ^0.8.0; // solhint-disable-line compiler-version // GENERATED CODE - Do not edit diff --git a/utils/unpack/Unpack.sol.gotmpl b/utils/unpack/Unpack.sol.gotmpl index 298e38957..c02ed2859 100644 --- a/utils/unpack/Unpack.sol.gotmpl +++ b/utils/unpack/Unpack.sol.gotmpl @@ -1,11 +1,13 @@ // (c) 2024, Ava Labs, Inc. All rights reserved. // See the file LICENSE for licensing terms. // SPDX-License-Identifier: UNLICENSED +// slither-disable-next-line solc-version pragma solidity ^{{if .UsesMCopy}}0.8.25{{else}}0.8.0{{end}}; // solhint-disable-line compiler-version // GENERATED CODE - Do not edit // solhint-disable no-inline-assembly +// slither-disable-start assembly // Mixed-case can't apply to numbers and an underscore is the most natural separator // solhint-disable func-name-mixedcase @@ -31,6 +33,7 @@ library Unpack { {{- end}} * @param input Buffer returned by `abi.encodePacked()` */ + // slither-disable-next-line naming-convention function unpack_{{.FuncNameSuffix}}(bytes memory input) internal pure returns ({{.Returns}}) { {{- $unpacker := .}} {{- if .HasDynamic}} diff --git a/utils/unpack/Unpack.t.sol.gotmpl b/utils/unpack/Unpack.t.sol.gotmpl index 47f3f3657..1edf49f92 100644 --- a/utils/unpack/Unpack.t.sol.gotmpl +++ b/utils/unpack/Unpack.t.sol.gotmpl @@ -1,6 +1,7 @@ // (c) 2024, Ava Labs, Inc. All rights reserved. // See the file LICENSE for licensing terms. // SPDX-License-Identifier: UNLICENSED +// slither-disable-next-line solc-version pragma solidity ^{{if .UsesMCopy}}0.8.25{{else}}0.8.0{{end}}; // solhint-disable-line compiler-version // GENERATED CODE - Do not edit From 0272bdef06589b83891c09bb8e9b75d7437b694b Mon Sep 17 00:00:00 2001 From: Arran Schlosberg Date: Fri, 9 Aug 2024 15:16:47 +0100 Subject: [PATCH 20/27] chore: disable `line-length-limiter` on flag usage --- utils/unpack/unpackgen/unpackgen.go | 1 + 1 file changed, 1 insertion(+) diff --git a/utils/unpack/unpackgen/unpackgen.go b/utils/unpack/unpackgen/unpackgen.go index c2127f405..192a9e18d 100644 --- a/utils/unpack/unpackgen/unpackgen.go +++ b/utils/unpack/unpackgen/unpackgen.go @@ -22,6 +22,7 @@ func main() { implPath := pflag.String("out", "./Unpack.sol", "Output path to which the Solidity implementations are written") testPath := pflag.String("test_out", "./Unpack.t.sol", "Output path to which the Solidity tests are written") bytes := new(bytesFlag) + //nolint:lll pflag.Var(bytes, "byte_sizes", "Semicolon-delimited list of groups of comma-delimited byte sizes. Use 0 for (at most one) dynamically sized byte array per group.") pflag.Parse() From aed84c7d2f2d3bfc94b2382b2b0a9687137edab3 Mon Sep 17 00:00:00 2001 From: Arran Schlosberg Date: Fri, 9 Aug 2024 15:21:02 +0100 Subject: [PATCH 21/27] feat: use literal "dyn" string in `unpackgen` flag --- contracts/staking/unpackgen.go | 2 +- utils/unpack/unpackgen/unpackgen.go | 24 +++++++++++++++--------- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/contracts/staking/unpackgen.go b/contracts/staking/unpackgen.go index 57ab6fe9d..07715b764 100644 --- a/contracts/staking/unpackgen.go +++ b/contracts/staking/unpackgen.go @@ -1,3 +1,3 @@ package staking -//go:generate go run ../../utils/unpack/unpackgen --out=./Unpack.sol --test_out=./tests/Unpack.t.sol --byte_sizes=4,32,32,8,8,0;4,32,1;4,32,8,8;4,32,8;32,32,8,8,0 +//go:generate go run ../../utils/unpack/unpackgen --out=./Unpack.sol --test_out=./tests/Unpack.t.sol --byte_sizes=4,32,32,8,8,dyn;4,32,1;4,32,8,8;4,32,8;32,32,8,8,dyn diff --git a/utils/unpack/unpackgen/unpackgen.go b/utils/unpack/unpackgen/unpackgen.go index 192a9e18d..63b66ec82 100644 --- a/utils/unpack/unpackgen/unpackgen.go +++ b/utils/unpack/unpackgen/unpackgen.go @@ -18,12 +18,14 @@ import ( "github.com/ava-labs/teleporter/utils/unpack" ) +const dynFlagSentinel = "dyn" + func main() { implPath := pflag.String("out", "./Unpack.sol", "Output path to which the Solidity implementations are written") testPath := pflag.String("test_out", "./Unpack.t.sol", "Output path to which the Solidity tests are written") bytes := new(bytesFlag) - //nolint:lll - pflag.Var(bytes, "byte_sizes", "Semicolon-delimited list of groups of comma-delimited byte sizes. Use 0 for (at most one) dynamically sized byte array per group.") + bytesMsg := fmt.Sprintf("Semicolon-delimited list of groups of comma-delimited byte sizes. Use literal %q for (at most one) dynamically sized byte array per group.", dynFlagSentinel) //nolint:lll + pflag.Var(bytes, "byte_sizes", bytesMsg) pflag.Parse() @@ -62,8 +64,8 @@ type bytesFlag struct { var _ pflag.Value = (*bytesFlag)(nil) // Set splits `s` by semicolons then splits each result by commas, parsing all -// resulting values as uints. It trims whitespace. If a parsed value is 0 it is -// replaced with unpack.Dynamic. +// resulting values as uints. It trims whitespace. If a value is "dyn" it +// is replaced with unpack.Dynamic. func (f *bytesFlag) Set(s string) error { groups := strings.Split(s, ";") var val [][]uint @@ -71,13 +73,14 @@ func (f *bytesFlag) Set(s string) error { for _, g := range groups { var bytes []uint for _, bStr := range strings.Split(g, ",") { + if strings.ToLower(bStr) == dynFlagSentinel { + bytes = append(bytes, unpack.Dynamic) + continue + } b, err := strconv.ParseUint(strings.TrimSpace(bStr), 10, 32) if err != nil { return err } - if b == 0 { - b = unpack.Dynamic - } bytes = append(bytes, uint(b)) } val = append(val, bytes) @@ -93,10 +96,13 @@ func (f *bytesFlag) String() string { for _, grp := range f.val { var vs []string for _, v := range grp { + var vStr string if v == unpack.Dynamic { - v = 0 + vStr = dynFlagSentinel + } else { + vStr = fmt.Sprintf("%d", v) } - vs = append(vs, fmt.Sprintf("%d", v)) + vs = append(vs, vStr) } parts = append(parts, strings.Join(vs, ",")) } From aab08742f9fe17013514662e31cb5c1486886156 Mon Sep 17 00:00:00 2001 From: Arran Schlosberg Date: Fri, 6 Sep 2024 12:32:35 +0100 Subject: [PATCH 22/27] feat: `pragma solidity` version override --- contracts/staking/Unpack.sol | 2 +- contracts/staking/unpackgen.go | 2 +- utils/unpack/Unpack.sol.gotmpl | 8 ++++---- utils/unpack/unpack.go | 26 +++++++++++++++++++++----- utils/unpack/unpackgen/unpackgen.go | 28 ++++++++++++++++++---------- 5 files changed, 45 insertions(+), 21 deletions(-) diff --git a/contracts/staking/Unpack.sol b/contracts/staking/Unpack.sol index 6f1890a15..692f70f6e 100644 --- a/contracts/staking/Unpack.sol +++ b/contracts/staking/Unpack.sol @@ -2,7 +2,7 @@ // See the file LICENSE for licensing terms. // SPDX-License-Identifier: UNLICENSED // slither-disable-next-line solc-version -pragma solidity ^0.8.0; // solhint-disable-line compiler-version +pragma solidity "0.8.25"; // solhint-disable-line compiler-version // GENERATED CODE - Do not edit diff --git a/contracts/staking/unpackgen.go b/contracts/staking/unpackgen.go index 07715b764..8ab04200c 100644 --- a/contracts/staking/unpackgen.go +++ b/contracts/staking/unpackgen.go @@ -1,3 +1,3 @@ package staking -//go:generate go run ../../utils/unpack/unpackgen --out=./Unpack.sol --test_out=./tests/Unpack.t.sol --byte_sizes=4,32,32,8,8,dyn;4,32,1;4,32,8,8;4,32,8;32,32,8,8,dyn +//go:generate go run ../../utils/unpack/unpackgen --out=./Unpack.sol --test_out=./tests/Unpack.t.sol --solc_version="0.8.25" --byte_sizes=4,32,32,8,8,dyn;4,32,1;4,32,8,8;4,32,8;32,32,8,8,dyn diff --git a/utils/unpack/Unpack.sol.gotmpl b/utils/unpack/Unpack.sol.gotmpl index c02ed2859..54324f6a7 100644 --- a/utils/unpack/Unpack.sol.gotmpl +++ b/utils/unpack/Unpack.sol.gotmpl @@ -2,7 +2,7 @@ // See the file LICENSE for licensing terms. // SPDX-License-Identifier: UNLICENSED // slither-disable-next-line solc-version -pragma solidity ^{{if .UsesMCopy}}0.8.25{{else}}0.8.0{{end}}; // solhint-disable-line compiler-version +pragma solidity {{.SolidityVersion}}; // solhint-disable-line compiler-version // GENERATED CODE - Do not edit @@ -25,10 +25,10 @@ library Unpack { * order, otherwise the output is undefined. {{- if .HasDynamic}} {{- if .UseMCopy}} - * @dev The returned `bytes memory` is freshly allocated, resulting in a memory expansion. + * @dev The returned `bytes memory` is freshly allocated, resulting in a memory expansion. {{- else}} - * @dev This function takes ownership of and corrupts the `input` parameter to avoid memory expansion for the - * returned `bytes memory`. The returned array is owned by the caller. + * @dev This function takes ownership of and corrupts the `input` parameter to avoid memory expansion for the + * returned `bytes memory`. The returned array is owned by the caller. {{- end}} {{- end}} * @param input Buffer returned by `abi.encodePacked()` diff --git a/utils/unpack/unpack.go b/utils/unpack/unpack.go index 07162c341..534f4b2b4 100644 --- a/utils/unpack/unpack.go +++ b/utils/unpack/unpack.go @@ -45,7 +45,10 @@ const Dynamic = math.MaxUint // encoded with `abi.encodePacked()`. Each slice of `[]uint` results in the // generation of one `unpack_...()` function and MAY have at most one [Dynamic] // size. -func Generate(impl, test io.Writer, relPathFromTestToImpl string, bytes ...[]uint) error { +// +// solcVersion is only used if non-empty, otherwise the most permissive version +// range is used. +func Generate(impl, test io.Writer, solcVersion, relPathFromTestToImpl string, bytes ...[]uint) error { us := make([]*unpacker, len(bytes)) for i, bs := range bytes { u, err := newUnpacker(bs...) @@ -56,8 +59,9 @@ func Generate(impl, test io.Writer, relPathFromTestToImpl string, bytes ...[]uin } data := &tmplData{ - RelPathFromTestToImpl: relPathFromTestToImpl, - Unpackers: us, + ExplicitSolidityVersion: solcVersion, + RelPathFromTestToImpl: relPathFromTestToImpl, + Unpackers: us, } return errors.Join( solTmpl.Execute(impl, data), @@ -66,8 +70,9 @@ func Generate(impl, test io.Writer, relPathFromTestToImpl string, bytes ...[]uin } type tmplData struct { - RelPathFromTestToImpl string - Unpackers []*unpacker + ExplicitSolidityVersion string // see SolidityVersion() method + RelPathFromTestToImpl string + Unpackers []*unpacker } // An unpacker defines all values required to generate a single `unpack_...()` @@ -145,6 +150,17 @@ func newUnpacker(bytes ...uint) (*unpacker, error) { return u, nil } +// SolidityVersion returns the pragma version string. +func (d *tmplData) SolidityVersion() string { + if v := d.ExplicitSolidityVersion; v != "" { + return v + } + if d.UsesMCopy() { + return "^0.8.25" + } + return "^0.8.0" +} + // UsesMCopy returns whether at least one unpack function uses the MCOPY op // code. func (d *tmplData) UsesMCopy() bool { diff --git a/utils/unpack/unpackgen/unpackgen.go b/utils/unpack/unpackgen/unpackgen.go index 63b66ec82..f88494d99 100644 --- a/utils/unpack/unpackgen/unpackgen.go +++ b/utils/unpack/unpackgen/unpackgen.go @@ -21,37 +21,45 @@ import ( const dynFlagSentinel = "dyn" func main() { - implPath := pflag.String("out", "./Unpack.sol", "Output path to which the Solidity implementations are written") - testPath := pflag.String("test_out", "./Unpack.t.sol", "Output path to which the Solidity tests are written") - bytes := new(bytesFlag) + var cfg config + + pflag.StringVar(&cfg.implPath, "out", "./Unpack.sol", "Output path to which the Solidity implementations are written") + pflag.StringVar(&cfg.testPath, "test_out", "./Unpack.t.sol", "Output path to which the Solidity tests are written") + pflag.StringVar(&cfg.solcVersion, "solc_version", "", "If non-empty, used verbatim as the version of the `pragma solidity` directive") + bytesMsg := fmt.Sprintf("Semicolon-delimited list of groups of comma-delimited byte sizes. Use literal %q for (at most one) dynamically sized byte array per group.", dynFlagSentinel) //nolint:lll - pflag.Var(bytes, "byte_sizes", bytesMsg) + pflag.Var(&cfg.bytes, "byte_sizes", bytesMsg) pflag.Parse() - if err := run(*implPath, *testPath, bytes.val); err != nil { + if err := cfg.run(); err != nil { fmt.Fprintln(os.Stderr, err) os.Exit(1) } } +type config struct { + implPath, testPath, solcVersion string + bytes bytesFlag +} + // run creates files at both paths and then calls `unpack.Generate()`. -func run(implPath, testPath string, bytes [][]uint) error { - impl, err := os.Create(implPath) +func (cfg *config) run() error { + impl, err := os.Create(cfg.implPath) if err != nil { return err } - test, err := os.Create(testPath) + test, err := os.Create(cfg.testPath) if err != nil { return err } - rel, err := filepath.Rel(filepath.Dir(testPath), implPath) + rel, err := filepath.Rel(filepath.Dir(cfg.testPath), cfg.implPath) if err != nil { return fmt.Errorf("determine path from test to implementation: %v", err) } - if err := unpack.Generate(impl, test, rel, bytes...); err != nil { + if err := unpack.Generate(impl, test, cfg.solcVersion, rel, cfg.bytes.val...); err != nil { return err } return errors.Join(impl.Close(), test.Close()) From f4a773c1797affdd04a05fd501bc08b0c291e3b6 Mon Sep 17 00:00:00 2001 From: Arran Schlosberg Date: Fri, 6 Sep 2024 12:34:51 +0100 Subject: [PATCH 23/27] fix: apply explicit `solc` version to generated tests --- contracts/staking/tests/Unpack.t.sol | 2 +- utils/unpack/Unpack.t.sol.gotmpl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts/staking/tests/Unpack.t.sol b/contracts/staking/tests/Unpack.t.sol index 4b0f5f08c..bd33d6268 100644 --- a/contracts/staking/tests/Unpack.t.sol +++ b/contracts/staking/tests/Unpack.t.sol @@ -2,7 +2,7 @@ // See the file LICENSE for licensing terms. // SPDX-License-Identifier: UNLICENSED // slither-disable-next-line solc-version -pragma solidity ^0.8.0; // solhint-disable-line compiler-version +pragma solidity "0.8.25"; // solhint-disable-line compiler-version // GENERATED CODE - Do not edit diff --git a/utils/unpack/Unpack.t.sol.gotmpl b/utils/unpack/Unpack.t.sol.gotmpl index 1edf49f92..a294ea5c5 100644 --- a/utils/unpack/Unpack.t.sol.gotmpl +++ b/utils/unpack/Unpack.t.sol.gotmpl @@ -2,7 +2,7 @@ // See the file LICENSE for licensing terms. // SPDX-License-Identifier: UNLICENSED // slither-disable-next-line solc-version -pragma solidity ^{{if .UsesMCopy}}0.8.25{{else}}0.8.0{{end}}; // solhint-disable-line compiler-version +pragma solidity {{.SolidityVersion}}; // solhint-disable-line compiler-version // GENERATED CODE - Do not edit From 1bfcf4bfb332de95c0dea40cae87cd9f327d597c Mon Sep 17 00:00:00 2001 From: Arran Schlosberg Date: Fri, 6 Sep 2024 12:37:13 +0100 Subject: [PATCH 24/27] doc: clarify allowable interchange of `bytes` and `uint<8N>` types --- contracts/staking/Unpack.sol | 20 ++++++++++---------- utils/unpack/Unpack.sol.gotmpl | 4 ++-- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/contracts/staking/Unpack.sol b/contracts/staking/Unpack.sol index 692f70f6e..112c1ec49 100644 --- a/contracts/staking/Unpack.sol +++ b/contracts/staking/Unpack.sol @@ -20,8 +20,8 @@ library Unpack { /** * @notice Inverts `abi.encodePacked()` for the specific return types. - * @dev The originally packed inputs MUST be of the same types as those returned by this function, in the precise - * order, otherwise the output is undefined. + * @dev The originally packed inputs MUST be of the same byte lengths as those returned by this function, in the + * precise order, otherwise the output is undefined. `bytes` and `uint<8N>` are interchangeable. * @dev This function takes ownership of and corrupts the `input` parameter to avoid memory expansion for the * returned `bytes memory`. The returned array is owned by the caller. * @param input Buffer returned by `abi.encodePacked()` @@ -51,8 +51,8 @@ library Unpack { /** * @notice Inverts `abi.encodePacked()` for the specific return types. - * @dev The originally packed inputs MUST be of the same types as those returned by this function, in the precise - * order, otherwise the output is undefined. + * @dev The originally packed inputs MUST be of the same byte lengths as those returned by this function, in the + * precise order, otherwise the output is undefined. `bytes` and `uint<8N>` are interchangeable. * @param input Buffer returned by `abi.encodePacked()` */ // slither-disable-next-line naming-convention @@ -74,8 +74,8 @@ library Unpack { /** * @notice Inverts `abi.encodePacked()` for the specific return types. - * @dev The originally packed inputs MUST be of the same types as those returned by this function, in the precise - * order, otherwise the output is undefined. + * @dev The originally packed inputs MUST be of the same byte lengths as those returned by this function, in the + * precise order, otherwise the output is undefined. `bytes` and `uint<8N>` are interchangeable. * @param input Buffer returned by `abi.encodePacked()` */ // slither-disable-next-line naming-convention @@ -98,8 +98,8 @@ library Unpack { /** * @notice Inverts `abi.encodePacked()` for the specific return types. - * @dev The originally packed inputs MUST be of the same types as those returned by this function, in the precise - * order, otherwise the output is undefined. + * @dev The originally packed inputs MUST be of the same byte lengths as those returned by this function, in the + * precise order, otherwise the output is undefined. `bytes` and `uint<8N>` are interchangeable. * @param input Buffer returned by `abi.encodePacked()` */ // slither-disable-next-line naming-convention @@ -121,8 +121,8 @@ library Unpack { /** * @notice Inverts `abi.encodePacked()` for the specific return types. - * @dev The originally packed inputs MUST be of the same types as those returned by this function, in the precise - * order, otherwise the output is undefined. + * @dev The originally packed inputs MUST be of the same byte lengths as those returned by this function, in the + * precise order, otherwise the output is undefined. `bytes` and `uint<8N>` are interchangeable. * @dev This function takes ownership of and corrupts the `input` parameter to avoid memory expansion for the * returned `bytes memory`. The returned array is owned by the caller. * @param input Buffer returned by `abi.encodePacked()` diff --git a/utils/unpack/Unpack.sol.gotmpl b/utils/unpack/Unpack.sol.gotmpl index 54324f6a7..a49633e1c 100644 --- a/utils/unpack/Unpack.sol.gotmpl +++ b/utils/unpack/Unpack.sol.gotmpl @@ -21,8 +21,8 @@ library Unpack { /** * @notice Inverts `abi.encodePacked()` for the specific return types. - * @dev The originally packed inputs MUST be of the same types as those returned by this function, in the precise - * order, otherwise the output is undefined. + * @dev The originally packed inputs MUST be of the same byte lengths as those returned by this function, in the + * precise order, otherwise the output is undefined. `bytes` and `uint<8N>` are interchangeable. {{- if .HasDynamic}} {{- if .UseMCopy}} * @dev The returned `bytes memory` is freshly allocated, resulting in a memory expansion. From 78a1f47cf336687f7e3b82d3bc7ef5c0b1c33fdd Mon Sep 17 00:00:00 2001 From: Arran Schlosberg Date: Fri, 6 Sep 2024 12:55:11 +0100 Subject: [PATCH 25/27] refactor: only change `pack*()` methods to `abi.encodePacked()` This allows the existing tests of round-trip pack-unpack to demonstrate equivalence. --- contracts/staking/ValidatorMessages.sol | 134 ++++-------------------- utils/unpack/unpackgen/unpackgen.go | 2 +- 2 files changed, 21 insertions(+), 115 deletions(-) diff --git a/contracts/staking/ValidatorMessages.sol b/contracts/staking/ValidatorMessages.sol index 849658043..3177209f0 100644 --- a/contracts/staking/ValidatorMessages.sol +++ b/contracts/staking/ValidatorMessages.sol @@ -73,39 +73,16 @@ library ValidatorMessages { require( validationPeriod.blsPublicKey.length == 48, "StakingMessages: invalid signature length" ); - bytes memory res = new bytes(134); - // Pack the codec ID - for (uint256 i; i < 2; ++i) { - res[i] = bytes1(uint8(CODEC_ID >> uint8((8 * (1 - i))))); - } - // Pack the type ID - for (uint256 i; i < 4; ++i) { - res[i + 2] = - bytes1(uint8(REGISTER_SUBNET_VALIDATOR_MESSAGE_TYPE_ID >> uint8((8 * (3 - i))))); - } - - // Pack the subnetID - for (uint256 i; i < 32; ++i) { - res[i + 6] = validationPeriod.subnetID[i]; - } - // Pack the nodeID - for (uint256 i; i < 32; ++i) { - res[i + 38] = validationPeriod.nodeID[i]; - } - // Pack the weight - for (uint256 i; i < 8; ++i) { - res[i + 70] = bytes1(uint8(validationPeriod.weight >> uint8((8 * (7 - i))))); - } - // Pack the blsPublicKey - for (uint256 i; i < 48; ++i) { - res[i + 78] = validationPeriod.blsPublicKey[i]; - } - // Pack the registration expiry - for (uint256 i; i < 8; ++i) { - res[i + 126] = - bytes1(uint8(validationPeriod.registrationExpiry >> uint64((8 * (7 - i))))); - } - return (sha256(res), res); + bytes memory packed = abi.encodePacked( + CODEC_ID, + REGISTER_SUBNET_VALIDATOR_MESSAGE_TYPE_ID, + validationPeriod.subnetID, + validationPeriod.nodeID, + validationPeriod.weight, + validationPeriod.blsPublicKey, + validationPeriod.registrationExpiry + ); + return (sha256(packed), packed); } /** @@ -202,23 +179,9 @@ library ValidatorMessages { bytes32 validationID, bool valid ) internal pure returns (bytes memory) { - bytes memory res = new bytes(39); - // Pack the codec ID. - for (uint256 i; i < 2; ++i) { - res[i] = bytes1(uint8(CODEC_ID >> (8 * (1 - i)))); - } - // Pack the type ID. - for (uint256 i; i < 4; ++i) { - res[i + 2] = - bytes1(uint8(SUBNET_VALIDATOR_REGISTRATION_MESSAGE_TYPE_ID >> (8 * (3 - i)))); - } - // Pack the validation ID. - for (uint256 i; i < 32; ++i) { - res[i + 6] = bytes1(uint8(uint256(validationID >> (8 * (31 - i))))); - } - // Pack the validity. - res[38] = bytes1(valid ? 1 : 0); - return res; + return abi.encodePacked( + CODEC_ID, SUBNET_VALIDATOR_REGISTRATION_MESSAGE_TYPE_ID, validationID, valid + ); } /** @@ -291,28 +254,9 @@ library ValidatorMessages { uint64 nonce, uint64 weight ) internal pure returns (bytes memory) { - bytes memory res = new bytes(54); - // Pack the codec ID. - for (uint256 i; i < 2; ++i) { - res[i] = bytes1(uint8(CODEC_ID >> (8 * (1 - i)))); - } - // Pack the type ID. - for (uint256 i; i < 4; ++i) { - res[i + 2] = bytes1(uint8(SET_SUBNET_VALIDATOR_WEIGHT_MESSAGE_TYPE_ID >> (8 * (3 - i)))); - } - // Pack the validation ID. - for (uint256 i; i < 32; ++i) { - res[i + 6] = bytes1(uint8(uint256(validationID >> (8 * (31 - i))))); - } - // Pack the nonce. - for (uint256 i; i < 8; ++i) { - res[i + 38] = bytes1(uint8(nonce >> (8 * (7 - i)))); - } - // Pack the weight. - for (uint256 i; i < 8; ++i) { - res[i + 46] = bytes1(uint8(weight >> (8 * (7 - i)))); - } - return res; + return abi.encodePacked( + CODEC_ID, SET_SUBNET_VALIDATOR_WEIGHT_MESSAGE_TYPE_ID, validationID, nonce, weight + ); } /** @@ -389,29 +333,9 @@ library ValidatorMessages { uint64 nonce, uint64 weight ) internal pure returns (bytes memory) { - bytes memory res = new bytes(54); - // Pack the codec ID. - for (uint256 i; i < 2; ++i) { - res[i] = bytes1(uint8(CODEC_ID >> (8 * (1 - i)))); - } - // Pack the type ID. - for (uint256 i; i < 4; ++i) { - res[i + 2] = - bytes1(uint8(SUBNET_VALIDATOR_WEIGHT_UPDATE_MESSAGE_TYPE_ID >> (8 * (3 - i)))); - } - // Pack the validation ID. - for (uint256 i; i < 32; ++i) { - res[i + 6] = bytes1(uint8(uint256(validationID >> (8 * (31 - i))))); - } - // Pack the nonce. - for (uint256 i; i < 8; ++i) { - res[i + 38] = bytes1(uint8(nonce >> (8 * (7 - i)))); - } - // Pack the weight. - for (uint256 i; i < 8; ++i) { - res[i + 46] = bytes1(uint8(weight >> (8 * (7 - i)))); - } - return res; + return abi.encodePacked( + CODEC_ID, SUBNET_VALIDATOR_WEIGHT_UPDATE_MESSAGE_TYPE_ID, validationID, nonce, weight + ); } /** @@ -489,25 +413,7 @@ library ValidatorMessages { bytes32 validationID, uint64 uptime ) internal pure returns (bytes memory) { - bytes memory res = new bytes(46); - - // Pack the codec ID. - for (uint256 i; i < 2; ++i) { - res[i] = bytes1(uint8(CODEC_ID >> (8 * (1 - i)))); - } - // Pack the type ID. - for (uint256 i; i < 4; ++i) { - res[i + 2] = bytes1(uint8(VALIDATION_UPTIME_MESSAGE_TYPE_ID >> (8 * (3 - i)))); - } - // Pack the validation ID. - for (uint256 i; i < 32; ++i) { - res[i + 6] = bytes1(uint8(uint256(validationID >> (8 * (31 - i))))); - } - // Pack the uptime. - for (uint256 i; i < 8; ++i) { - res[i + 38] = bytes1(uint8(uptime >> (8 * (7 - i)))); - } - return res; + return abi.encodePacked(CODEC_ID, VALIDATION_UPTIME_MESSAGE_TYPE_ID, validationID, uptime); } /** diff --git a/utils/unpack/unpackgen/unpackgen.go b/utils/unpack/unpackgen/unpackgen.go index f88494d99..44530bfc0 100644 --- a/utils/unpack/unpackgen/unpackgen.go +++ b/utils/unpack/unpackgen/unpackgen.go @@ -25,7 +25,7 @@ func main() { pflag.StringVar(&cfg.implPath, "out", "./Unpack.sol", "Output path to which the Solidity implementations are written") pflag.StringVar(&cfg.testPath, "test_out", "./Unpack.t.sol", "Output path to which the Solidity tests are written") - pflag.StringVar(&cfg.solcVersion, "solc_version", "", "If non-empty, used verbatim as the version of the `pragma solidity` directive") + pflag.StringVar(&cfg.solcVersion, "solc_version", "", "If non-empty, used verbatim as the version of the `pragma solidity` directive") //nolint:lll bytesMsg := fmt.Sprintf("Semicolon-delimited list of groups of comma-delimited byte sizes. Use literal %q for (at most one) dynamically sized byte array per group.", dynFlagSentinel) //nolint:lll pflag.Var(&cfg.bytes, "byte_sizes", bytesMsg) From e13cabc2e31a4476a9b27ef9ec9f8674306f86c3 Mon Sep 17 00:00:00 2001 From: Arran Schlosberg Date: Fri, 6 Sep 2024 13:18:36 +0100 Subject: [PATCH 26/27] refactor: change `unpack*()` methods to use generated code --- contracts/staking/Unpack.sol | 101 +++++------- contracts/staking/ValidatorMessages.sol | 200 +++++------------------- contracts/staking/tests/Unpack.t.sol | 94 +++++------ contracts/staking/unpackgen.go | 2 +- 4 files changed, 132 insertions(+), 265 deletions(-) diff --git a/contracts/staking/Unpack.sol b/contracts/staking/Unpack.sol index 112c1ec49..1788890db 100644 --- a/contracts/staking/Unpack.sol +++ b/contracts/staking/Unpack.sol @@ -27,25 +27,35 @@ library Unpack { * @param input Buffer returned by `abi.encodePacked()` */ // slither-disable-next-line naming-convention - function unpack_4_32_32_8_8_Dyn_Destructive(bytes memory input) + function unpack_2_4_32_32_8_Dyn_8_Destructive(bytes memory input) internal pure - returns (bytes4 v0, bytes32 v1, bytes32 v2, bytes8 v3, bytes8 v4, bytes memory v5) + returns ( + bytes2 v0, + bytes4 v1, + bytes32 v2, + bytes32 v3, + bytes8 v4, + bytes memory v5, + bytes8 v6 + ) { - if (input.length < 84) { - revert InsufficientInputLength(84, input.length); + if (input.length < 86) { + revert InsufficientInputLength(86, input.length); } assembly ("memory-safe") { v0 := mload(add(input, 0x20)) - v1 := mload(add(input, 0x24)) - v2 := mload(add(input, 0x44)) - v3 := mload(add(input, 0x64)) - v4 := mload(add(input, 0x6c)) + v1 := mload(add(input, 0x22)) + v2 := mload(add(input, 0x26)) + v3 := mload(add(input, 0x46)) + v4 := mload(add(input, 0x66)) let length := mload(input) - let dynLength := sub(length, 84) - v5 := add(input, 84) + let dynLength := sub(length, 86) + v5 := add(input, 78) mstore(v5, dynLength) + let end := add(input, add(length, 0x20)) + v6 := mload(sub(end, 0x08)) } } @@ -56,19 +66,20 @@ library Unpack { * @param input Buffer returned by `abi.encodePacked()` */ // slither-disable-next-line naming-convention - function unpack_4_32_1(bytes memory input) + function unpack_2_4_32_1(bytes memory input) internal pure - returns (bytes4 v0, bytes32 v1, bytes1 v2) + returns (bytes2 v0, bytes4 v1, bytes32 v2, bytes1 v3) { - if (input.length != 37) { - revert IncorrectInputLength(input.length, 37); + if (input.length != 39) { + revert IncorrectInputLength(input.length, 39); } assembly ("memory-safe") { v0 := mload(add(input, 0x20)) - v1 := mload(add(input, 0x24)) - v2 := mload(add(input, 0x44)) + v1 := mload(add(input, 0x22)) + v2 := mload(add(input, 0x26)) + v3 := mload(add(input, 0x46)) } } @@ -79,20 +90,21 @@ library Unpack { * @param input Buffer returned by `abi.encodePacked()` */ // slither-disable-next-line naming-convention - function unpack_4_32_8_8(bytes memory input) + function unpack_2_4_32_8_8(bytes memory input) internal pure - returns (bytes4 v0, bytes32 v1, bytes8 v2, bytes8 v3) + returns (bytes2 v0, bytes4 v1, bytes32 v2, bytes8 v3, bytes8 v4) { - if (input.length != 52) { - revert IncorrectInputLength(input.length, 52); + if (input.length != 54) { + revert IncorrectInputLength(input.length, 54); } assembly ("memory-safe") { v0 := mload(add(input, 0x20)) - v1 := mload(add(input, 0x24)) - v2 := mload(add(input, 0x44)) - v3 := mload(add(input, 0x4c)) + v1 := mload(add(input, 0x22)) + v2 := mload(add(input, 0x26)) + v3 := mload(add(input, 0x46)) + v4 := mload(add(input, 0x4e)) } } @@ -103,49 +115,20 @@ library Unpack { * @param input Buffer returned by `abi.encodePacked()` */ // slither-disable-next-line naming-convention - function unpack_4_32_8(bytes memory input) + function unpack_2_4_32_8(bytes memory input) internal pure - returns (bytes4 v0, bytes32 v1, bytes8 v2) + returns (bytes2 v0, bytes4 v1, bytes32 v2, bytes8 v3) { - if (input.length != 44) { - revert IncorrectInputLength(input.length, 44); + if (input.length != 46) { + revert IncorrectInputLength(input.length, 46); } assembly ("memory-safe") { v0 := mload(add(input, 0x20)) - v1 := mload(add(input, 0x24)) - v2 := mload(add(input, 0x44)) - } - } - - /** - * @notice Inverts `abi.encodePacked()` for the specific return types. - * @dev The originally packed inputs MUST be of the same byte lengths as those returned by this function, in the - * precise order, otherwise the output is undefined. `bytes` and `uint<8N>` are interchangeable. - * @dev This function takes ownership of and corrupts the `input` parameter to avoid memory expansion for the - * returned `bytes memory`. The returned array is owned by the caller. - * @param input Buffer returned by `abi.encodePacked()` - */ - // slither-disable-next-line naming-convention - function unpack_32_32_8_8_Dyn_Destructive(bytes memory input) - internal - pure - returns (bytes32 v0, bytes32 v1, bytes8 v2, bytes8 v3, bytes memory v4) - { - if (input.length < 80) { - revert InsufficientInputLength(80, input.length); - } - - assembly ("memory-safe") { - v0 := mload(add(input, 0x20)) - v1 := mload(add(input, 0x40)) - v2 := mload(add(input, 0x60)) - v3 := mload(add(input, 0x68)) - let length := mload(input) - let dynLength := sub(length, 80) - v4 := add(input, 80) - mstore(v4, dynLength) + v1 := mload(add(input, 0x22)) + v2 := mload(add(input, 0x26)) + v3 := mload(add(input, 0x46)) } } } diff --git a/contracts/staking/ValidatorMessages.sol b/contracts/staking/ValidatorMessages.sol index 3177209f0..9c447f9c1 100644 --- a/contracts/staking/ValidatorMessages.sol +++ b/contracts/staking/ValidatorMessages.sol @@ -4,6 +4,8 @@ // SPDX-License-Identifier: Ecosystem pragma solidity 0.8.25; +import {Unpack} from "./Unpack.sol"; + library ValidatorMessages { // The information that uniquely identifies a subnet validation period. // The validationID is the SHA-256 hash of the concatenation of the CODEC_ID, @@ -99,58 +101,27 @@ library ValidatorMessages { { require(input.length == 134, "ValidatorMessages: invalid message length"); - // Unpack the codec ID - uint16 codecID; - for (uint256 i; i < 2; ++i) { - codecID |= uint16(uint8(input[i])) << uint16((8 * (1 - i))); - } - require(codecID == CODEC_ID, "ValidatorMessages: invalid codec ID"); - - // Unpack the type ID - uint32 typeID; - for (uint256 i; i < 4; ++i) { - typeID |= uint32(uint8(input[i + 2])) << uint32((8 * (3 - i))); - } + ( + bytes2 codecID, + bytes4 typeID, + bytes32 subnetID, + bytes32 nodeID, + bytes8 weight, + bytes memory blsPublicKey, + bytes8 expiry + ) = Unpack.unpack_2_4_32_32_8_Dyn_8_Destructive(input); + + require(uint16(codecID) == CODEC_ID, "ValidatorMessages: invalid codec ID"); require( - typeID == REGISTER_SUBNET_VALIDATOR_MESSAGE_TYPE_ID, + uint32(typeID) == REGISTER_SUBNET_VALIDATOR_MESSAGE_TYPE_ID, "ValidatorMessages: invalid message type" ); - // Unpack the subnetID - bytes32 subnetID; - for (uint256 i; i < 32; ++i) { - subnetID |= bytes32(uint256(uint8(input[i + 6])) << (8 * (31 - i))); - } - - // Unpack the nodeID - bytes32 nodeID; - for (uint256 i; i < 32; ++i) { - nodeID |= bytes32(uint256(uint8(input[i + 38])) << (8 * (31 - i))); - } - - // Unpack the weight - uint64 weight; - for (uint256 i; i < 8; ++i) { - weight |= uint64(uint8(input[i + 70])) << uint64((8 * (7 - i))); - } - - // Unpack the blsPublicKey - bytes memory blsPublicKey = new bytes(48); - for (uint256 i; i < 48; ++i) { - blsPublicKey[i] = input[i + 78]; - } - - // Unpack the registration expiry - uint64 expiry; - for (uint256 i; i < 8; ++i) { - expiry |= uint64(uint8(input[i + 126])) << uint64((8 * (7 - i))); - } - return ValidationPeriod({ subnetID: subnetID, nodeID: nodeID, - weight: weight, - registrationExpiry: expiry, + weight: uint64(weight), + registrationExpiry: uint64(expiry), blsPublicKey: blsPublicKey }); } @@ -198,33 +169,17 @@ library ValidatorMessages { returns (bytes32, bool) { require(input.length == 39, "ValidatorMessages: invalid message length"); - // Unpack the codec ID - uint16 codecID; - for (uint256 i; i < 2; ++i) { - codecID |= uint16(uint8(input[i])) << uint16((8 * (1 - i))); - } - require(codecID == CODEC_ID, "ValidatorMessages: invalid codec ID"); - - // Unpack the type ID - uint32 typeID; - for (uint256 i; i < 4; ++i) { - typeID |= uint32(uint8(input[i + 2])) << uint32((8 * (3 - i))); - } + + (bytes2 codecID, bytes4 typeID, bytes32 validationID, bytes1 valid) = + Unpack.unpack_2_4_32_1(input); + + require(uint16(codecID) == CODEC_ID, "ValidatorMessages: invalid codec ID"); require( - typeID == SUBNET_VALIDATOR_REGISTRATION_MESSAGE_TYPE_ID, + uint32(typeID) == SUBNET_VALIDATOR_REGISTRATION_MESSAGE_TYPE_ID, "ValidatorMessages: invalid message type" ); - // Unpack the validation ID. - bytes32 validationID; - for (uint256 i; i < 32; ++i) { - validationID |= bytes32(uint256(uint8(input[i + 6])) << (8 * (31 - i))); - } - - // Unpack the validity - bool valid = input[38] != 0; - - return (validationID, valid); + return (validationID, uint8(valid) != 0); } /** @@ -273,42 +228,16 @@ library ValidatorMessages { { require(input.length == 54, "ValidatorMessages: invalid message length"); - // Unpack the codec ID. - uint16 codecID; - for (uint256 i; i < 2; ++i) { - codecID |= uint16(uint8(input[i])) << uint16((8 * (1 - i))); - } - require(codecID == CODEC_ID, "ValidatorMessages: invalid codec ID"); - - // Unpack the type ID. - uint32 typeID; - for (uint256 i; i < 4; ++i) { - typeID |= uint32(uint8(input[i + 2])) << uint32((8 * (3 - i))); - } + (bytes2 codecID, bytes4 typeID, bytes32 validationID, bytes8 nonce, bytes8 weight) = + Unpack.unpack_2_4_32_8_8(input); + + require(uint16(codecID) == CODEC_ID, "ValidatorMessages: invalid codec ID"); require( - typeID == SET_SUBNET_VALIDATOR_WEIGHT_MESSAGE_TYPE_ID, + uint32(typeID) == SET_SUBNET_VALIDATOR_WEIGHT_MESSAGE_TYPE_ID, "ValidatorMessages: invalid message type" ); - // Unpack the validation ID. - bytes32 validationID; - for (uint256 i; i < 32; ++i) { - validationID |= bytes32(uint256(uint8(input[i + 6])) << (8 * (31 - i))); - } - - // Unpack the nonce. - uint64 nonce; - for (uint256 i; i < 8; ++i) { - nonce |= uint64(uint8(input[i + 38])) << uint64((8 * (7 - i))); - } - - // Unpack the weight. - uint64 weight; - for (uint256 i; i < 8; ++i) { - weight |= uint64(uint8(input[i + 46])) << uint64((8 * (7 - i))); - } - - return (validationID, nonce, weight); + return (validationID, uint64(nonce), uint64(weight)); } /** @@ -352,42 +281,16 @@ library ValidatorMessages { { require(input.length == 54, "ValidatorMessages: invalid message length"); - // Unpack the codec ID. - uint16 codecID; - for (uint256 i; i < 2; ++i) { - codecID |= uint16(uint8(input[i])) << uint16((8 * (1 - i))); - } - require(codecID == CODEC_ID, "ValidatorMessages: invalid codec ID"); - - // Unpack the type ID. - uint32 typeID; - for (uint256 i; i < 4; ++i) { - typeID |= uint32(uint8(input[i + 2])) << uint32((8 * (3 - i))); - } + (bytes2 codecID, bytes4 typeID, bytes32 validationID, bytes8 nonce, bytes8 weight) = + Unpack.unpack_2_4_32_8_8(input); + + require(uint16(codecID) == CODEC_ID, "ValidatorMessages: invalid codec ID"); require( - typeID == SUBNET_VALIDATOR_WEIGHT_UPDATE_MESSAGE_TYPE_ID, + uint32(typeID) == SUBNET_VALIDATOR_WEIGHT_UPDATE_MESSAGE_TYPE_ID, "ValidatorMessages: invalid message type" ); - // Unpack the validation ID. - bytes32 validationID; - for (uint256 i; i < 32; ++i) { - validationID |= bytes32(uint256(uint8(input[i + 6])) << (8 * (31 - i))); - } - - // Unpack the nonce. - uint64 nonce; - for (uint256 i; i < 8; ++i) { - nonce |= uint64(uint8(input[i + 38])) << uint64((8 * (7 - i))); - } - - // Unpack the weight. - uint64 weight; - for (uint256 i; i < 8; ++i) { - weight |= uint64(uint8(input[i + 46])) << uint64((8 * (7 - i))); - } - - return (validationID, nonce, weight); + return (validationID, uint64(nonce), uint64(weight)); } /** @@ -430,34 +333,15 @@ library ValidatorMessages { { require(input.length == 46, "ValidatorMessages: invalid message length"); - // Unpack the codec ID. - uint16 codecID; - for (uint256 i; i < 2; ++i) { - codecID |= uint16(uint8(input[i])) << uint16((8 * (1 - i))); - } - require(codecID == CODEC_ID, "ValidatorMessages: invalid codec ID"); - - // Unpack the type ID. - uint32 typeID; - for (uint256 i; i < 4; ++i) { - typeID |= uint32(uint8(input[i + 2])) << uint32((8 * (3 - i))); - } + (bytes2 codecID, bytes4 typeID, bytes32 validationID, bytes8 uptime) = + Unpack.unpack_2_4_32_8(input); + + require(uint16(codecID) == CODEC_ID, "ValidatorMessages: invalid codec ID"); require( - typeID == VALIDATION_UPTIME_MESSAGE_TYPE_ID, "ValidatorMessages: invalid message type" + uint32(typeID) == VALIDATION_UPTIME_MESSAGE_TYPE_ID, + "ValidatorMessages: invalid message type" ); - // Unpack the validation ID. - bytes32 validationID; - for (uint256 i; i < 32; ++i) { - validationID |= bytes32(uint256(uint8(input[i + 6])) << (8 * (31 - i))); - } - - // Unpack the uptime. - uint64 uptime; - for (uint256 i; i < 8; ++i) { - uptime |= uint64(uint8(input[i + 38])) << uint64((8 * (7 - i))); - } - - return (validationID, uptime); + return (validationID, uint64(uptime)); } } diff --git a/contracts/staking/tests/Unpack.t.sol b/contracts/staking/tests/Unpack.t.sol index bd33d6268..687663eb1 100644 --- a/contracts/staking/tests/Unpack.t.sol +++ b/contracts/staking/tests/Unpack.t.sol @@ -15,74 +15,74 @@ import {console} from "@forge-std/console.sol"; import {Unpack} from "../Unpack.sol"; contract UnpackTest is Test { - function testUnpack_4_32_32_8_8_Dyn_Destructive( - bytes4 v0, - bytes32 v1, + function testUnpack_2_4_32_32_8_Dyn_8_Destructive( + bytes2 v0, + bytes4 v1, bytes32 v2, - bytes8 v3, + bytes32 v3, bytes8 v4, - bytes memory v5 + bytes memory v5, + bytes8 v6 ) external pure { - bytes memory packed = abi.encodePacked(v0, v1, v2, v3, v4, v5); + bytes memory packed = abi.encodePacked(v0, v1, v2, v3, v4, v5, v6); console.logBytes(packed); - (bytes4 got0, bytes32 got1, bytes32 got2, bytes8 got3, bytes8 got4, bytes memory got5) = - Unpack.unpack_4_32_32_8_8_Dyn_Destructive(packed); - assertEq(v0, got0, "output[0] bytes4"); - assertEq(v1, got1, "output[1] bytes32"); + ( + bytes2 got0, + bytes4 got1, + bytes32 got2, + bytes32 got3, + bytes8 got4, + bytes memory got5, + bytes8 got6 + ) = Unpack.unpack_2_4_32_32_8_Dyn_8_Destructive(packed); + assertEq(v0, got0, "output[0] bytes2"); + assertEq(v1, got1, "output[1] bytes4"); assertEq(v2, got2, "output[2] bytes32"); - assertEq(v3, got3, "output[3] bytes8"); + assertEq(v3, got3, "output[3] bytes32"); assertEq(v4, got4, "output[4] bytes8"); assertEq(v5, got5, "output[5] bytes memory"); + assertEq(v6, got6, "output[6] bytes8"); } - function testUnpack_4_32_1(bytes4 v0, bytes32 v1, bytes1 v2) external pure { - bytes memory packed = abi.encodePacked(v0, v1, v2); - console.logBytes(packed); - - (bytes4 got0, bytes32 got1, bytes1 got2) = Unpack.unpack_4_32_1(packed); - assertEq(v0, got0, "output[0] bytes4"); - assertEq(v1, got1, "output[1] bytes32"); - assertEq(v2, got2, "output[2] bytes1"); - } - - function testUnpack_4_32_8_8(bytes4 v0, bytes32 v1, bytes8 v2, bytes8 v3) external pure { + function testUnpack_2_4_32_1(bytes2 v0, bytes4 v1, bytes32 v2, bytes1 v3) external pure { bytes memory packed = abi.encodePacked(v0, v1, v2, v3); console.logBytes(packed); - (bytes4 got0, bytes32 got1, bytes8 got2, bytes8 got3) = Unpack.unpack_4_32_8_8(packed); - assertEq(v0, got0, "output[0] bytes4"); - assertEq(v1, got1, "output[1] bytes32"); - assertEq(v2, got2, "output[2] bytes8"); - assertEq(v3, got3, "output[3] bytes8"); + (bytes2 got0, bytes4 got1, bytes32 got2, bytes1 got3) = Unpack.unpack_2_4_32_1(packed); + assertEq(v0, got0, "output[0] bytes2"); + assertEq(v1, got1, "output[1] bytes4"); + assertEq(v2, got2, "output[2] bytes32"); + assertEq(v3, got3, "output[3] bytes1"); } - function testUnpack_4_32_8(bytes4 v0, bytes32 v1, bytes8 v2) external pure { - bytes memory packed = abi.encodePacked(v0, v1, v2); + function testUnpack_2_4_32_8_8( + bytes2 v0, + bytes4 v1, + bytes32 v2, + bytes8 v3, + bytes8 v4 + ) external pure { + bytes memory packed = abi.encodePacked(v0, v1, v2, v3, v4); console.logBytes(packed); - (bytes4 got0, bytes32 got1, bytes8 got2) = Unpack.unpack_4_32_8(packed); - assertEq(v0, got0, "output[0] bytes4"); - assertEq(v1, got1, "output[1] bytes32"); - assertEq(v2, got2, "output[2] bytes8"); + (bytes2 got0, bytes4 got1, bytes32 got2, bytes8 got3, bytes8 got4) = + Unpack.unpack_2_4_32_8_8(packed); + assertEq(v0, got0, "output[0] bytes2"); + assertEq(v1, got1, "output[1] bytes4"); + assertEq(v2, got2, "output[2] bytes32"); + assertEq(v3, got3, "output[3] bytes8"); + assertEq(v4, got4, "output[4] bytes8"); } - function testUnpack_32_32_8_8_Dyn_Destructive( - bytes32 v0, - bytes32 v1, - bytes8 v2, - bytes8 v3, - bytes memory v4 - ) external pure { - bytes memory packed = abi.encodePacked(v0, v1, v2, v3, v4); + function testUnpack_2_4_32_8(bytes2 v0, bytes4 v1, bytes32 v2, bytes8 v3) external pure { + bytes memory packed = abi.encodePacked(v0, v1, v2, v3); console.logBytes(packed); - (bytes32 got0, bytes32 got1, bytes8 got2, bytes8 got3, bytes memory got4) = - Unpack.unpack_32_32_8_8_Dyn_Destructive(packed); - assertEq(v0, got0, "output[0] bytes32"); - assertEq(v1, got1, "output[1] bytes32"); - assertEq(v2, got2, "output[2] bytes8"); + (bytes2 got0, bytes4 got1, bytes32 got2, bytes8 got3) = Unpack.unpack_2_4_32_8(packed); + assertEq(v0, got0, "output[0] bytes2"); + assertEq(v1, got1, "output[1] bytes4"); + assertEq(v2, got2, "output[2] bytes32"); assertEq(v3, got3, "output[3] bytes8"); - assertEq(v4, got4, "output[4] bytes memory"); } } diff --git a/contracts/staking/unpackgen.go b/contracts/staking/unpackgen.go index 8ab04200c..c5712f0ff 100644 --- a/contracts/staking/unpackgen.go +++ b/contracts/staking/unpackgen.go @@ -1,3 +1,3 @@ package staking -//go:generate go run ../../utils/unpack/unpackgen --out=./Unpack.sol --test_out=./tests/Unpack.t.sol --solc_version="0.8.25" --byte_sizes=4,32,32,8,8,dyn;4,32,1;4,32,8,8;4,32,8;32,32,8,8,dyn +//go:generate go run ../../utils/unpack/unpackgen --out=./Unpack.sol --test_out=./tests/Unpack.t.sol --solc_version="0.8.25" --byte_sizes=2,4,32,32,8,dyn,8;2,4,32,1;2,4,32,8,8;2,4,32,8 From a19b841a09b1effa09dbefe31cb1772accbb0646 Mon Sep 17 00:00:00 2001 From: Arran Schlosberg Date: Fri, 6 Sep 2024 13:40:12 +0100 Subject: [PATCH 27/27] chore: regenerate ABI bindings --- .../ERC20TokenStakingManager/ERC20TokenStakingManager.go | 4 ++-- .../NativeTokenStakingManager/NativeTokenStakingManager.go | 4 ++-- .../go/staking/PoAValidatorManager/PoAValidatorManager.go | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/abi-bindings/go/staking/ERC20TokenStakingManager/ERC20TokenStakingManager.go b/abi-bindings/go/staking/ERC20TokenStakingManager/ERC20TokenStakingManager.go index d57c7ca9f..44204d10c 100644 --- a/abi-bindings/go/staking/ERC20TokenStakingManager/ERC20TokenStakingManager.go +++ b/abi-bindings/go/staking/ERC20TokenStakingManager/ERC20TokenStakingManager.go @@ -47,8 +47,8 @@ type ValidatorManagerSettings struct { // ERC20TokenStakingManagerMetaData contains all meta data concerning the ERC20TokenStakingManager contract. var ERC20TokenStakingManagerMetaData = &bind.MetaData{ - ABI: "[{\"type\":\"constructor\",\"inputs\":[{\"name\":\"init\",\"type\":\"uint8\",\"internalType\":\"enumICMInitializable\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"WARP_MESSENGER\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"contractIWarpMessenger\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"activeValidators\",\"inputs\":[{\"name\":\"nodeID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"completeDelegatorRegistration\",\"inputs\":[{\"name\":\"messageIndex\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"delegationID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"completeEndDelegation\",\"inputs\":[{\"name\":\"messageIndex\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"delegationID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"completeEndValidation\",\"inputs\":[{\"name\":\"messageIndex\",\"type\":\"uint32\",\"internalType\":\"uint32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"completeValidatorRegistration\",\"inputs\":[{\"name\":\"messageIndex\",\"type\":\"uint32\",\"internalType\":\"uint32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"getWeight\",\"inputs\":[{\"name\":\"validationID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"initialize\",\"inputs\":[{\"name\":\"settings\",\"type\":\"tuple\",\"internalType\":\"structPoSValidatorManagerSettings\",\"components\":[{\"name\":\"baseSettings\",\"type\":\"tuple\",\"internalType\":\"structValidatorManagerSettings\",\"components\":[{\"name\":\"pChainBlockchainID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"subnetID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"maximumHourlyChurn\",\"type\":\"uint8\",\"internalType\":\"uint8\"}]},{\"name\":\"minimumStakeAmount\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"maximumStakeAmount\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"minimumStakeDuration\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"rewardCalculator\",\"type\":\"address\",\"internalType\":\"contractIRewardCalculator\"}]},{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"contractIERC20\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"initializeDelegatorRegistration\",\"inputs\":[{\"name\":\"validationID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"delegationAmount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"initializeEndDelegation\",\"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\":\"initializeEndValidation\",\"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\":\"initializeValidatorRegistration\",\"inputs\":[{\"name\":\"stakeAmount\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"nodeID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"registrationExpiry\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"blsPublicKey\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[{\"name\":\"validationID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"resendDelegatorRegistration\",\"inputs\":[{\"name\":\"delegationID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"resendEndDelegation\",\"inputs\":[{\"name\":\"delegationID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"resendEndValidatorMessage\",\"inputs\":[{\"name\":\"validationID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"resendRegisterValidatorMessage\",\"inputs\":[{\"name\":\"validationID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"valueToWeight\",\"inputs\":[{\"name\":\"value\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"stateMutability\":\"pure\"},{\"type\":\"function\",\"name\":\"weightToValue\",\"inputs\":[{\"name\":\"weight\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"pure\"},{\"type\":\"event\",\"name\":\"DelegationEnded\",\"inputs\":[{\"name\":\"delegationID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"validationID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"nonce\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"DelegatorAdded\",\"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\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"DelegatorRegistered\",\"inputs\":[{\"name\":\"delegationID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"validationID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"nonce\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"startTime\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"DelegatorRemovalInitialized\",\"inputs\":[{\"name\":\"delegationID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"validationID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"nonce\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"validatorWeight\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"},{\"name\":\"endTime\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"},{\"name\":\"setWeightMessageID\",\"type\":\"bytes32\",\"indexed\":false,\"internalType\":\"bytes32\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Initialized\",\"inputs\":[{\"name\":\"version\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ValidationPeriodCreated\",\"inputs\":[{\"name\":\"validationID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"nodeID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"registerValidationMessageID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"weight\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"},{\"name\":\"registrationExpiry\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ValidationPeriodEnded\",\"inputs\":[{\"name\":\"validationID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"status\",\"type\":\"uint8\",\"indexed\":true,\"internalType\":\"enumValidatorStatus\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ValidationPeriodRegistered\",\"inputs\":[{\"name\":\"validationID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"weight\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"},{\"name\":\"timestamp\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ValidatorRemovalInitialized\",\"inputs\":[{\"name\":\"validationID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"setWeightMessageID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"weight\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"},{\"name\":\"endTime\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"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\":\"FailedInnerCall\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidInitialization\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"NotInitializing\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"ReentrancyGuardReentrantCall\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"SafeERC20FailedOperation\",\"inputs\":[{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"address\"}]}]", - Bin: "0x608060405234801561000f575f80fd5b5060405161478938038061478983398101604081905261002e91610107565b60018160018111156100425761004261012c565b0361004f5761004f610055565b50610140565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000900460ff16156100a55760405163f92ee8a960e01b815260040160405180910390fd5b80546001600160401b03908116146101045780546001600160401b0319166001600160401b0390811782556040519081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50565b5f60208284031215610117575f80fd5b815160028110610125575f80fd5b9392505050565b634e487b7160e01b5f52602160045260245ffd5b61463c8061014d5f395ff3fe608060405234801561000f575f80fd5b5060043610610111575f3560e01c806366435abf1161009e57806398f3e2b41161006e57806398f3e2b4146102645780639e1bc4ef14610277578063a3a65e481461028a578063b771b3bc1461029d578063bee0a03f146102c3575f80fd5b806366435abf146102185780636d0e43fa1461022b57806376f786211461023e578063872fda6414610251575f80fd5b806327f39ca8116100e457806327f39ca8146101a15780632e2194d8146101b4578063467ef06f146101df5780635297fae6146101f25780636206585614610205575f80fd5b80630118acc4146101155780630322ed981461012a5780630cdd09851461013d578063162f1f611461018e575b5f80fd5b610128610123366004613ca8565b6102d6565b005b610128610138366004613ce3565b61076a565b61017b61014b366004613ce3565b5f9081527fe92546d698950ddd38910d2e15ed1d923cd0a7b3dde9e2a6a3f380565559cb08602052604090205490565b6040519081526020015b60405180910390f35b61012861019c366004613ce3565b6108c6565b6101286101af366004613d0e565b610933565b6101c76101c2366004613ce3565b610a17565b6040516001600160401b039091168152602001610185565b6101286101ed366004613d4b565b610a2d565b610128610200366004613d64565b610db0565b61017b610213366004613da2565b610fa1565b6101c7610226366004613ce3565b610fba565b610128610239366004613ce3565b610fce565b61012861024c366004613ca8565b61103b565b61017b61025f366004613e4d565b611056565b610128610272366004613d64565b61107b565b61017b610285366004613ee9565b61121b565b610128610298366004613d4b565b61122e565b6102ab6005600160991b0181565b6040516001600160a01b039091168152602001610185565b6101286102d1366004613ce3565b6113eb565b5f8381527f4317713f7ecbdddd4bc99e95d903adedaa883b2e7c2551610bd13e2c7e473d0360205260408120600101545f805160206145908339815191529184156103285761032582856114ba565b90505b5f868152600384016020526040808220815161010081019092528054829060ff16600481111561035a5761035a613f09565b600481111561036b5761036b613f09565b8152815461010090046001600160a01b031660208201526001820154604082015260028201546001600160401b038082166060840152600160401b820481166080840152600160801b8204811660a0840152600160c01b909104811660c083015260039092015490911660e0909101529050336001600160a01b031681602001516001600160a01b0316146104505760405162461bcd60e51b815260206004820152603360248201525f805160206145b08339815191526044820152723737ba1037bbb732b210313c9039b2b73232b960691b60648201526084015b60405180910390fd5b60028151600481111561046557610465613f09565b146104b25760405162461bcd60e51b815260206004820152602a60248201525f805160206145b08339815191526044820152696e6f742061637469766560b01b6064820152608401610447565b5f6104bc84611756565b60038084526001600160401b0342811660a0860152821660e08501525f8a815290870160205260409020835181549293508492829060ff1916600183600481111561050957610509613f09565b021790555060208201518154610100600160a81b0319166101006001600160a01b0390921691909102178155604082015160018201556060820151600282018054608085015160a086015160c08701516001600160401b039586166001600160801b031990941693909317600160401b92861692909202919091176001600160801b0316600160801b918516919091026001600160c01b031617600160c01b9184169190910217905560e0909201516003909101805467ffffffffffffffff1916919092161790555f6105db856117ca565b905082606001516001600160401b03168160a001516001600160401b0316116106525760405162461bcd60e51b815260206004820152602360248201527f506f5356616c696461746f724d616e616765723a20496e76616c69642077656960448201526219da1d60ea1b6064820152608401610447565b5f83606001518260a001516106679190613f31565b905061067386826118db565b5f61067f878584611923565b5f8c815260058a016020526040902090915061069b8282613fdb565b5060405163ee5b48eb60e01b81525f906005600160991b019063ee5b48eb906106c89085906004016140bc565b6020604051808303815f875af11580156106e4573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061070891906140ee565b604080516001600160401b03868116825242602083015291810183905291925086169089908e907f5318ab4d7cdf77056db2db5b539a08fe7d1a63d6885ecee8236a0dbda2843b4e9060600160405180910390a4505050505050505050505050565b5f8181527fe92546d698950ddd38910d2e15ed1d923cd0a7b3dde9e2a6a3f380565559cb066020526040812080545f805160206145d08339815191529291906107b290613f58565b90501180156107e4575060035f83815260078301602052604090205460ff1660058111156107e2576107e2613f09565b145b6108485760405162461bcd60e51b815260206004820152602f60248201527f56616c696461746f724d616e616765723a2056616c696461746f72206e6f742060448201526e1c195b991a5b99c81c995b5bdd985b608a1b6064820152608401610447565b5f82815260068201602052604090819020905163ee5b48eb60e01b81526005600160991b019163ee5b48eb916108819190600401614105565b6020604051808303815f875af115801561089d573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108c191906140ee565b505050565b6108cf81611b40565b5f8181527f4317713f7ecbdddd4bc99e95d903adedaa883b2e7c2551610bd13e2c7e473d05602052604090819020905163ee5b48eb60e01b81525f80516020614590833981519152916005600160991b019163ee5b48eb9161088191600401614105565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805460029190600160401b900460ff168061097c575080546001600160401b03808416911610155b1561099a5760405163f92ee8a960e01b815260040160405180910390fd5b805468ffffffffffffffffff19166001600160401b03831617600160401b1781556109c58484611c13565b805468ff0000000000000000191681556040516001600160401b03831681527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a150505050565b5f610a2764e8d4a51000836141a3565b92915050565b5f805160206145d08339815191525f610a4583611c2d565b90505f80610a568360400151611e0e565b915091508015610abb5760405162461bcd60e51b815260206004820152602a60248201527f56616c696461746f724d616e616765723a20726567697374726174696f6e20736044820152691d1a5b1b081d985b1a5960b21b6064820152608401610447565b5f828152600785016020526040808220815161010081019092528054829060ff166005811115610aed57610aed613f09565b6005811115610afe57610afe613f09565b81526001820154602082015260028201546001600160a01b03811660408301526001600160401b03600160a01b909104811660608301526003928301548082166080840152600160401b8104821660a0840152600160801b8104821660c0840152600160c01b90041660e0909101529091505f9082516005811115610b8557610b85613f09565b1480610ba35750600182516005811115610ba157610ba1613f09565b145b610c025760405162461bcd60e51b815260206004820152602a60248201527f56616c696461746f724d616e616765723a20696e76616c69642076616c696461604482015269746f722073746174757360b01b6064820152608401610447565b600382516005811115610c1757610c17613f09565b03610c3e57505f8381526006860160205260408120600491610c399190613c39565b610c42565b5060055b6020808301515f90815260088801909152604081205581816005811115610c6b57610c6b613f09565b90816005811115610c7e57610c7e613f09565b9052505f84815260078701602052604090208251815484929190829060ff19166001836005811115610cb257610cb2613f09565b021790555060208201516001820155604082015160028201805460608501516001600160401b03908116600160a01b026001600160e01b03199092166001600160a01b039094169390931717905560808301516003909201805460a085015160c086015160e0909601518416600160c01b026001600160c01b03968516600160801b02969096166001600160801b03918516600160401b026001600160801b0319909316959094169490941717929092161791909117905581516005811115610d7d57610d7d613f09565b60405185907f1c08e59656f1a18dc2da76826cdc52805c43e897a17c50faefb8ab3c1526cc16905f90a350505050505050565b5f805160206145908339815191525f610dc884611c2d565b90505f80610dd98360400151611faf565b5091509150610de7856121ea565b5f8581526004850160205260408120610dff91613c39565b5f610e09836117ca565b9050816001600160401b031681608001516001600160401b03161015610e415760405162461bcd60e51b8152600401610447906141b6565b5f8681526003860160205260409020600201546001600160401b03808416600160c01b909204161115610e865760405162461bcd60e51b8152600401610447906141f8565b60015f87815260038701602052604090205460ff166004811115610eac57610eac613f09565b14610f155760405162461bcd60e51b815260206004820152603360248201527f506f5356616c696461746f724d616e616765723a2064656c65676174696f6e4960448201527211081b9bdd081c195b991a5b99c81859191959606a1b6064820152608401610447565b5f868152600386016020908152604091829020805460ff1916600290811782550180546001600160401b0342818116600160401b0267ffffffffffffffff60401b19909316929092179092559251928352841691859189917f245fc69b36e168426e0306fc8d8300661b9af297c7958820dbf804f9f63e7064910160405180910390a450505050505050565b5f610a276001600160401b03831664e8d4a51000614241565b5f610fc4826117ca565b60a0015192915050565b610fd7816121ea565b5f8181527f4317713f7ecbdddd4bc99e95d903adedaa883b2e7c2551610bd13e2c7e473d04602052604090819020905163ee5b48eb60e01b81525f80516020614590833981519152916005600160991b019163ee5b48eb9161088191600401614105565b811561104d5761104b83826114ba565b505b6108c1836122c3565b5f806110618661267b565b905061106f85828686612728565b9150505b949350505050565b5f805160206145908339815191525f61109384611c2d565b90505f806110a48360400151611faf565b50915091506110b285611b40565b5f85815260058501602052604081206110ca91613c39565b5f6110d4836117ca565b9050816001600160401b031681608001516001600160401b0316101561110c5760405162461bcd60e51b8152600401610447906141b6565b5f8681526003808701602052604090912001546001600160401b038084169116111561114a5760405162461bcd60e51b8152600401610447906141f8565b60035f87815260038701602052604090205460ff16600481111561117057611170613f09565b146111c45760405162461bcd60e51b815260206004820152603160248201525f805160206145b08339815191526044820152701b9bdd081c195b991a5b99c81859191959607a1b6064820152608401610447565b5f868152600386016020526040808220805460ff19166004179055516001600160401b03841691859189917f52e9b1eaef84d46cda83ccb9d427267bc4d04f756b4a32c8302722b79e5c65ab91a450505050505050565b5f611227833384612b7d565b9392505050565b5f805160206145d08339815191525f61124683611c2d565b90505f806112578360400151611e0e565b91509150806112b95760405162461bcd60e51b815260206004820152602860248201527f56616c696461746f724d616e616765723a20526567697374726174696f6e206e6044820152671bdd081d985b1a5960c21b6064820152608401610447565b5f828152600585016020526040812080546112d390613f58565b9050118015611305575060015f83815260078601602052604090205460ff16600581111561130357611303613f09565b145b6113215760405162461bcd60e51b815260040161044790614258565b5f828152600585016020526040812061133991613c39565b5f8281526007850160208181526040808420805460ff191660021781556003810180546001600160401b0342818116600160801b0267ffffffffffffffff60801b19909316929092178355600190930154875260088b0185528387208990559588905293835292548151600160401b90910490931683529082019290925283917ff8fd1c90fb9cfa2ca2358fdf5806b086ad43315d92b221c929efc7f105ce7568910160405180910390a25050505050565b5f8181527fe92546d698950ddd38910d2e15ed1d923cd0a7b3dde9e2a6a3f380565559cb056020526040812080545f805160206145d083398151915292919061143390613f58565b9050118015611465575060015f83815260078301602052604090205460ff16600581111561146357611463613f09565b145b6114815760405162461bcd60e51b815260040161044790614258565b5f82815260058201602052604090819020905163ee5b48eb60e01b81526005600160991b019163ee5b48eb916108819190600401614105565b6040516306f8253560e41b815263ffffffff821660048201525f90819081906005600160991b0190636f825350906024015f60405180830381865afa158015611505573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f1916820160405261152c91908101906142aa565b915091508061158f5760405162461bcd60e51b815260206004820152602960248201527f506f5356616c696461746f724d616e616765723a20696e76616c69642077617260448201526870206d65737361676560b81b6064820152608401610447565b6005600160991b016001600160a01b0316634213cf786040518163ffffffff1660e01b8152600401602060405180830381865afa1580156115d2573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906115f691906140ee565b82511461165a5760405162461bcd60e51b815260206004820152602c60248201527f506f5356616c696461746f724d616e616765723a20696e76616c696420736f7560448201526b1c98d94818da185a5b88125160a21b6064820152608401610447565b60208201516001600160a01b0316156116d05760405162461bcd60e51b815260206004820152603260248201527f506f5356616c696461746f724d616e616765723a20696e76616c6964206f726960448201527167696e2073656e646572206164647265737360701b6064820152608401610447565b5f806116df8460400151612f38565b9150915081871461174c5760405162461bcd60e51b815260206004820152603160248201527f506f5356616c696461746f724d616e616765723a20696e76616c6964207570746044820152701a5b59481d985b1a59185d1a5bdb881251607a1b6064820152608401610447565b9695505050505050565b5f8181525f805160206146108339815191526020526040812060030180545f805160206145d0833981519152916001600160401b039091169081908461179b8361437c565b91906101000a8154816001600160401b0302191690836001600160401b03160217905550508092505050919050565b6040805161010080820183525f8083526020808401829052838501829052606084018290526080840182905260a0840182905260c0840182905260e084018290528582525f8051602061461083398151915290528390208351918201909352825491925f805160206145d083398151915292829060ff16600581111561185257611852613f09565b600581111561186357611863613f09565b81526001820154602082015260028201546001600160a01b03811660408301526001600160401b03600160a01b909104811660608301526003909201548083166080830152600160401b8104831660a0830152600160801b8104831660c0830152600160c01b900490911660e0909101529392505050565b5f9182525f80516020614610833981519152602052604090912060030180546001600160401b03909216600160401b0267ffffffffffffffff60401b19909216919091179055565b60408051603680825260608281019093525f91906020820181803683370190505090505f5b600281101561199c5761195c8160016143a1565b611967906008614241565b5081515f9083908390811061197e5761197e6143b4565b60200101906001600160f81b03191690815f1a905350600101611948565b505f5b60048110156119ff576119b38160036143a1565b6119be906008614241565b6001901c60f81b826119d18360026143c8565b815181106119e1576119e16143b4565b60200101906001600160f81b03191690815f1a90535060010161199f565b505f5b6020811015611a6157611a1681601f6143a1565b611a21906008614241565b86901c60f81b82611a338360066143c8565b81518110611a4357611a436143b4565b60200101906001600160f81b03191690815f1a905350600101611a02565b505f5b6008811015611acc57611a788160076143a1565b611a83906008614241565b6001600160401b038616901c60f81b82611a9e8360266143c8565b81518110611aae57611aae6143b4565b60200101906001600160f81b03191690815f1a905350600101611a64565b505f5b6008811015611b3757611ae38160076143a1565b611aee906008614241565b6001600160401b038516901c60f81b82611b0983602e6143c8565b81518110611b1957611b196143b4565b60200101906001600160f81b03191690815f1a905350600101611acf565b50949350505050565b5f8181527f4317713f7ecbdddd4bc99e95d903adedaa883b2e7c2551610bd13e2c7e473d056020526040812080545f80516020614590833981519152929190611b8890613f58565b9050118015611bba575060035f83815260038301602052604090205460ff166004811115611bb857611bb8613f09565b145b611c0f5760405162461bcd60e51b815260206004820152603360248201525f805160206145b083398151915260448201527272656d6f76616c206e6f742070656e64696e6760681b6064820152608401610447565b5050565b611c1b613110565b611c248261315b565b611c0f816131a1565b60408051606080820183525f8083526020830181905292820152905f805160206145d08339815191526040516306f8253560e41b815263ffffffff851660048201529091505f9081906005600160991b0190636f825350906024015f60405180830381865afa158015611ca2573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052611cc991908101906142aa565b9150915080611d305760405162461bcd60e51b815260206004820152602d60248201527f56616c696461746f724d616e616765723a20496e76696e76616c6964616c696460448201526c2077617270206d65737361676560981b6064820152608401610447565b8254825114611d935760405162461bcd60e51b815260206004820152602960248201527f56616c696461746f724d616e616765723a20696e76616c696420736f757263656044820152680818da185a5b88125160ba1b6064820152608401610447565b60208201516001600160a01b031615611e065760405162461bcd60e51b815260206004820152602f60248201527f56616c696461746f724d616e616765723a20696e76616c6964206f726967696e60448201526e2073656e646572206164647265737360881b6064820152608401610447565b509392505050565b5f808251602714611e315760405162461bcd60e51b8152600401610447906143db565b5f805b6002811015611e8057611e488160016143a1565b611e53906008614241565b61ffff16858281518110611e6957611e696143b4565b016020015160f81c901b9190911790600101611e34565b5061ffff811615611ea35760405162461bcd60e51b815260040161044790614424565b5f805b6004811015611efe57611eba8160036143a1565b611ec5906008614241565b63ffffffff1686611ed78360026143c8565b81518110611ee757611ee76143b4565b016020015160f81c901b9190911790600101611ea6565b5063ffffffff8116600214611f255760405162461bcd60e51b815260040161044790614467565b5f805b6020811015611f7a57611f3c81601f6143a1565b611f47906008614241565b87611f538360066143c8565b81518110611f6357611f636143b4565b016020015160f81c901b9190911790600101611f28565b505f86602681518110611f8f57611f8f6143b4565b016020015191976001600160f81b03199092161515965090945050505050565b5f805f8351603614611fd35760405162461bcd60e51b8152600401610447906143db565b5f805b600281101561202257611fea8160016143a1565b611ff5906008614241565b61ffff1686828151811061200b5761200b6143b4565b016020015160f81c901b9190911790600101611fd6565b5061ffff8116156120455760405162461bcd60e51b815260040161044790614424565b5f805b60048110156120a05761205c8160036143a1565b612067906008614241565b63ffffffff16876120798360026143c8565b81518110612089576120896143b4565b016020015160f81c901b9190911790600101612048565b5063ffffffff81166003146120c75760405162461bcd60e51b815260040161044790614467565b5f805b602081101561211c576120de81601f6143a1565b6120e9906008614241565b886120f58360066143c8565b81518110612105576121056143b4565b016020015160f81c901b91909117906001016120ca565b505f805b600881101561217b576121348160076143a1565b61213f906008614241565b6001600160401b0316896121548360266143c8565b81518110612164576121646143b4565b016020015160f81c901b9190911790600101612120565b505f805b60088110156121da576121938160076143a1565b61219e906008614241565b6001600160401b03168a6121b383602e6143c8565b815181106121c3576121c36143b4565b016020015160f81c901b919091179060010161217f565b5091989097509095509350505050565b5f8181527f4317713f7ecbdddd4bc99e95d903adedaa883b2e7c2551610bd13e2c7e473d046020526040812080545f8051602061459083398151915292919061223290613f58565b9050118015612264575060015f83815260038301602052604090205460ff16600481111561226257612262613f09565b145b611c0f5760405162461bcd60e51b815260206004820152603860248201525f805160206145b083398151915260448201527f726567697374726174696f6e206e6f742070656e64696e6700000000000000006064820152608401610447565b5f8181525f8051602061461083398151915260205260408082208151610100810190925280545f805160206145d083398151915293929190829060ff16600581111561231157612311613f09565b600581111561232257612322613f09565b8152600182015460208201526002808301546001600160a01b03811660408401526001600160401b03600160a01b909104811660608401526003909301548084166080840152600160401b8104841660a0840152600160801b8104841660c0840152600160c01b900490921660e090910152909150815160058111156123aa576123aa613f09565b146124065760405162461bcd60e51b815260206004820152602660248201527f56616c696461746f724d616e616765723a2076616c696461746f72206e6f742060448201526561637469766560d01b6064820152608401610447565b60408101516001600160a01b0316336001600160a01b0316146124805760405162461bcd60e51b815260206004820152602c60248201527f56616c696461746f724d616e616765723a2073656e646572206e6f742076616c60448201526b34b230ba37b91037bbb732b960a11b6064820152608401610447565b61248d8160a00151613255565b60038152426001600160401b031660e08201525f83815260078301602052604090208151815483929190829060ff191660018360058111156124d1576124d1613f09565b021790555060208201516001820155604082015160028201805460608501516001600160401b03908116600160a01b026001600160e01b03199092166001600160a01b039094169390931717905560808301516003909201805460a085015160c086015160e0909601518416600160c01b026001600160c01b03968516600160801b02969096166001600160801b03918516600160401b026001600160801b031990931695909416949094171792909216179190911790555f61259d8461259781611756565b5f611923565b5f85815260068501602052604090209091506125b98282613fdb565b5060405163ee5b48eb60e01b81525f906005600160991b019063ee5b48eb906125e69085906004016140bc565b6020604051808303815f875af1158015612602573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061262691906140ee565b60a0840151604080516001600160401b039092168252426020830152919250829187917f13d58394cf269d48bcf927959a29a5ffee7c9924dafff8927ecdf3c48ffa7c67910160405180910390a35050505050565b5f5f8051602061459083398151915281612694846133f6565b90505f6126a082610a17565b83549091506001600160401b038216108015906126ca57508260010154816001600160401b031611155b6110735760405162461bcd60e51b815260206004820152602960248201527f506f5356616c696461746f724d616e616765723a20696e76616c6964207374616044820152681ad948185b5bdd5b9d60ba1b6064820152608401610447565b5f61273161342c565b5f805160206145d0833981519152426001600160401b03851611801561276b57506001600160401b038416612769426202a3006143c8565b115b6127cd5760405162461bcd60e51b815260206004820152602d60248201527f56616c696461746f724d616e616765723a20696e76616c69642072656769737460448201526c726174696f6e2065787069727960981b6064820152608401610447565b856128245760405162461bcd60e51b815260206004820152602160248201527f56616c696461746f724d616e616765723a20696e76616c6964206e6f646520496044820152601160fa1b6064820152608401610447565b5f868152600882016020526040902054156128925760405162461bcd60e51b815260206004820152602860248201527f56616c696461746f724d616e616765723a206e6f646520494420616c72656164604482015267792061637469766560c01b6064820152608401610447565b82516030146128f95760405162461bcd60e51b815260206004820152602d60248201527f56616c696461746f724d616e616765723a20696e76616c696420626c7350756260448201526c0d8d2c696caf240d8cadccee8d609b1b6064820152608401610447565b61290285613255565b5f806129496040518060a00160405280856001015481526020018a8152602001896001600160401b03168152602001886001600160401b0316815260200187815250613463565b5f828152600586016020526040902091935091506129678282613fdb565b5060405163ee5b48eb60e01b81525f906005600160991b019063ee5b48eb906129949085906004016140bc565b6020604051808303815f875af11580156129b0573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906129d491906140ee565b604080516101008101825260018152602081018c90529192508101336001600160a01b031681526001600160401b038a1660208083018290525f604080850182905260608501939093526080840181905260a0909301839052868352600788019052902081518154829060ff19166001836005811115612a5657612a56613f09565b021790555060208201516001820155604082015160028201805460608501516001600160401b03908116600160a01b026001600160e01b03199092166001600160a01b039094169390931717905560808301516003909201805460a085015160c086015160e0909601518416600160c01b026001600160c01b03968516600160801b02969096166001600160801b03918516600160401b026001600160801b03199093169590941694909417179290921617919091179055612b1783611756565b50604080516001600160401b03808b1682528916602082015282918b9186917f79b81620b81daf2c08cd5bb3dbb79e75d2d7a87f52171fde5aadc8c47823026e910160405180910390a450909250505061107360015f805160206145f083398151915255565b5f612b8661342c565b5f612b936101c2846133f6565b90505f805160206145908339815191525f612bad876117ca565b9050600281516005811115612bc457612bc4613f09565b14612c235760405162461bcd60e51b815260206004820152602960248201527f506f5356616c696461746f724d616e616765723a2076616c696461746f72206e6044820152686f742061637469766560b81b6064820152608401610447565b5f838260a00151612c3491906144ae565b9050612c4088826118db565b5f612c4a89611756565b90505f898983604051602001612c929392919092835260609190911b6bffffffffffffffffffffffff1916602083015260c01b6001600160c01b0319166034820152603c0190565b604051602081830303815290604052805190602001209050612cb386613255565b5f612cbf8b8486611923565b5f8381526004880160205260409020909150612cdb8282613fdb565b5060405163ee5b48eb60e01b81525f906005600160991b019063ee5b48eb90612d089085906004016140bc565b6020604051808303815f875af1158015612d24573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612d4891906140ee565b60408051610100810190915290915080600181526020018c6001600160a01b031681526020018d8152602001896001600160401b031681526020015f6001600160401b031681526020015f6001600160401b03168152602001856001600160401b031681526020015f6001600160401b0316815250876003015f8581526020019081526020015f205f820151815f015f6101000a81548160ff02191690836004811115612df757612df7613f09565b02179055506020828101518254610100600160a81b0319166101006001600160a01b039283160217835560408085015160018501556060808601516002860180546080808a015160a08b015160c08c01516001600160401b039687166001600160801b031990951694909417600160401b92871692909202919091176001600160801b0316600160801b918616919091026001600160c01b031617600160c01b928516929092029190911790915560e0909701516003909601805467ffffffffffffffff19169682169690961790955581518a861681528b861694810194909452938d1690830152918101849052908d16918e9186917fb0024b263bc3a0b728a6edea50a69efa841189f8d32ee8af9d1c2b1a1a223426910160405180910390a45090965050505050505061122760015f805160206145f083398151915255565b5f808251602e14612f5b5760405162461bcd60e51b8152600401610447906143db565b5f805b6002811015612faa57612f728160016143a1565b612f7d906008614241565b61ffff16858281518110612f9357612f936143b4565b016020015160f81c901b9190911790600101612f5e565b5061ffff811615612fcd5760405162461bcd60e51b815260040161044790614424565b5f805b600481101561302857612fe48160036143a1565b612fef906008614241565b63ffffffff16866130018360026143c8565b81518110613011576130116143b4565b016020015160f81c901b9190911790600101612fd0565b5063ffffffff811660041461304f5760405162461bcd60e51b815260040161044790614467565b5f805b60208110156130a45761306681601f6143a1565b613071906008614241565b8761307d8360066143c8565b8151811061308d5761308d6143b4565b016020015160f81c901b9190911790600101613052565b505f805b6008811015613103576130bc8160076143a1565b6130c7906008614241565b6001600160401b0316886130dc8360266143c8565b815181106130ec576130ec6143b4565b016020015160f81c901b91909117906001016130a8565b5090969095509350505050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054600160401b900460ff1661315957604051631afcd79f60e31b815260040160405180910390fd5b565b613163613110565b61316c8161381b565b61319e6060820135608083013561318960c0850160a08601613da2565b61319960e0860160c087016144ce565b61383c565b50565b6131a9613110565b7f6e5bdfcce15e53c3406ea67bfce37dcd26f5152d5492824e43fd5e3c8ac5ab006001600160a01b0382166132355760405162461bcd60e51b815260206004820152602c60248201527f4552433230546f6b656e5374616b696e674d616e616765723a207a65726f207460448201526b6f6b656e206164647265737360a01b6064820152608401610447565b80546001600160a01b0319166001600160a01b0392909216919091179055565b7fe92546d698950ddd38910d2e15ed1d923cd0a7b3dde9e2a6a3f380565559cb02545f805160206145d08339815191529060ff165f03613293575050565b60408051606081018252600383015480825260048401546001600160401b038082166020850152600160401b9091041692820192909252904290610e10906132db90836143a1565b106132f7576001600160401b0384166040830152808252613316565b838260400181815161330991906144ae565b6001600160401b03169052505b5f82602001518360400151606461332d91906144e9565b6133379190614514565b600285015490915060ff90811690821611156133b25760405162461bcd60e51b815260206004820152603460248201527f56616c696461746f724d616e616765723a206d6178696d756d20686f75726c796044820152730818da1d5c9b881c985d1948195e18d95959195960621b6064820152608401610447565b5050805160038301556020810151600490920180546040909201516001600160401b03908116600160401b026001600160801b031990931693169290921717905550565b5f610a27827f6e5bdfcce15e53c3406ea67bfce37dcd26f5152d5492824e43fd5e3c8ac5ab00546001600160a01b031690613897565b5f805160206145f083398151915280546001190161345d57604051633ee5aeb560e01b815260040160405180910390fd5b60029055565b5f60608260800151516030146134cd5760405162461bcd60e51b815260206004820152602960248201527f5374616b696e674d657373616765733a20696e76616c6964207369676e6174756044820152680e4ca40d8cadccee8d60bb1b6064820152608401610447565b60408051608680825260c082019092525f916020820181803683370190505090505f5b6002811015613544576135048160016143a1565b61350f906008614241565b5081515f90839083908110613526576135266143b4565b60200101906001600160f81b03191690815f1a9053506001016134f0565b505f5b60048110156135a25761355b8160036143a1565b613566906008614241565b505f826135748360026143c8565b81518110613584576135846143b4565b60200101906001600160f81b03191690815f1a905350600101613547565b505f5b60208110156135ff57845181602081106135c1576135c16143b4565b1a60f81b826135d18360066143c8565b815181106135e1576135e16143b4565b60200101906001600160f81b03191690815f1a9053506001016135a5565b505f5b602081101561365f5784602001518160208110613621576136216143b4565b1a60f81b826136318360266143c8565b81518110613641576136416143b4565b60200101906001600160f81b03191690815f1a905350600101613602565b505f5b60088110156136d3576136768160076143a1565b613681906008614241565b60ff1685604001516001600160401b0316901c60f81b828260466136a591906143c8565b815181106136b5576136b56143b4565b60200101906001600160f81b03191690815f1a905350600101613662565b505f5b603081101561373e57846080015181815181106136f5576136f56143b4565b01602001516001600160f81b0319168261371083604e6143c8565b81518110613720576137206143b4565b60200101906001600160f81b03191690815f1a9053506001016136d6565b505f5b60088110156137b0576137558160076143a1565b613760906008614241565b60608601516001600160401b0390811691161c60f81b8261378283607e6143c8565b81518110613792576137926143b4565b60200101906001600160f81b03191690815f1a905350600101613741565b506002816040516137c19190614539565b602060405180830381855afa1580156137dc573d5f803e3d5ffd5b5050506040513d601f19601f820116820180604052508101906137ff91906140ee565b94909350915050565b60015f805160206145f083398151915255565b613823613110565b61382b6139f9565b613833613a09565b61319e81613a11565b613844613110565b5f5f80516020614590833981519152948555506001840192909255600290920180546001600160a01b03909216600160401b026001600160e01b03199092166001600160401b0390931692909217179055565b6040516370a0823160e01b81523060048201525f9081906001600160a01b038516906370a0823190602401602060405180830381865afa1580156138dd573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061390191906140ee565b90506139186001600160a01b038516333086613a7d565b6040516370a0823160e01b81523060048201525f906001600160a01b038616906370a0823190602401602060405180830381865afa15801561395c573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061398091906140ee565b90508181116139e65760405162461bcd60e51b815260206004820152602c60248201527f5361666545524332305472616e7366657246726f6d3a2062616c616e6365206e60448201526b1bdd081a5b98dc99585cd95960a21b6064820152608401610447565b6139f082826143a1565b95945050505050565b613a01613110565b613159613add565b613159613110565b613a19613110565b80355f805160206145d083398151915290815560208201357fe92546d698950ddd38910d2e15ed1d923cd0a7b3dde9e2a6a3f380565559cb0155613a636060830160408401614554565b600291909101805460ff191660ff90921691909117905550565b604080516001600160a01b0385811660248301528416604482015260648082018490528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b179052613ad7908590613ae5565b50505050565b613808613110565b5f613af96001600160a01b03841683613b46565b905080515f14158015613b1d575080806020019051810190613b1b9190614574565b155b156108c157604051635274afe760e01b81526001600160a01b0384166004820152602401610447565b606061122783835f845f80856001600160a01b03168486604051613b6a9190614539565b5f6040518083038185875af1925050503d805f8114613ba4576040519150601f19603f3d011682016040523d82523d5f602084013e613ba9565b606091505b509150915061174c868383606082613bc957613bc482613c10565b611227565b8151158015613be057506001600160a01b0384163b155b15613c0957604051639996b31560e01b81526001600160a01b0385166004820152602401610447565b5080611227565b805115613c205780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b508054613c4590613f58565b5f825580601f10613c54575050565b601f0160209004905f5260205f209081019061319e91905b80821115613c7f575f8155600101613c6c565b5090565b801515811461319e575f80fd5b803563ffffffff81168114613ca3575f80fd5b919050565b5f805f60608486031215613cba575f80fd5b833592506020840135613ccc81613c83565b9150613cda60408501613c90565b90509250925092565b5f60208284031215613cf3575f80fd5b5035919050565b6001600160a01b038116811461319e575f80fd5b5f80828403610100811215613d21575f80fd5b60e0811215613d2e575f80fd5b5082915060e0830135613d4081613cfa565b809150509250929050565b5f60208284031215613d5b575f80fd5b61122782613c90565b5f8060408385031215613d75575f80fd5b613d7e83613c90565b946020939093013593505050565b80356001600160401b0381168114613ca3575f80fd5b5f60208284031215613db2575f80fd5b61122782613d8c565b634e487b7160e01b5f52604160045260245ffd5b604051606081016001600160401b0381118282101715613df157613df1613dbb565b60405290565b604051601f8201601f191681016001600160401b0381118282101715613e1f57613e1f613dbb565b604052919050565b5f6001600160401b03821115613e3f57613e3f613dbb565b50601f01601f191660200190565b5f805f8060808587031215613e60575f80fd5b8435935060208501359250613e7760408601613d8c565b915060608501356001600160401b03811115613e91575f80fd5b8501601f81018713613ea1575f80fd5b8035613eb4613eaf82613e27565b613df7565b818152886020838501011115613ec8575f80fd5b816020840160208301375f6020838301015280935050505092959194509250565b5f8060408385031215613efa575f80fd5b50508035926020909101359150565b634e487b7160e01b5f52602160045260245ffd5b634e487b7160e01b5f52601160045260245ffd5b6001600160401b03828116828216039080821115613f5157613f51613f1d565b5092915050565b600181811c90821680613f6c57607f821691505b602082108103613f8a57634e487b7160e01b5f52602260045260245ffd5b50919050565b601f8211156108c157805f5260205f20601f840160051c81016020851015613fb55750805b601f840160051c820191505b81811015613fd4575f8155600101613fc1565b5050505050565b81516001600160401b03811115613ff457613ff4613dbb565b614008816140028454613f58565b84613f90565b602080601f83116001811461403b575f84156140245750858301515b5f19600386901b1c1916600185901b178555614092565b5f85815260208120601f198616915b828110156140695788860151825594840194600190910190840161404a565b508582101561408657878501515f19600388901b60f8161c191681555b505060018460011b0185555b505050505050565b5f5b838110156140b457818101518382015260200161409c565b50505f910152565b602081525f82518060208401526140da81604085016020870161409a565b601f01601f19169190910160400192915050565b5f602082840312156140fe575f80fd5b5051919050565b5f60208083525f845461411781613f58565b806020870152604060018084165f8114614138576001811461415457614181565b60ff19851660408a0152604084151560051b8a01019550614181565b895f5260205f205f5b858110156141785781548b820186015290830190880161415d565b8a016040019650505b509398975050505050505050565b634e487b7160e01b5f52601260045260245ffd5b5f826141b1576141b161418f565b500490565b60208082526022908201527f506f5356616c696461746f724d616e616765723a20696e76616c6964206e6f6e604082015261636560f01b606082015260800190565b60208082526029908201527f506f5356616c696461746f724d616e616765723a206e6f6e636520646f6573206040820152680dcdee840dac2e8c6d60bb1b606082015260800190565b8082028115828204841417610a2757610a27613f1d565b60208082526027908201527f56616c696461746f724d616e616765723a20696e76616c69642076616c6964616040820152661d1a5bdb88125160ca1b606082015260800190565b8051613ca381613c83565b5f80604083850312156142bb575f80fd5b82516001600160401b03808211156142d1575f80fd5b90840190606082870312156142e4575f80fd5b6142ec613dcf565b825181526020808401516142ff81613cfa565b82820152604084015183811115614314575f80fd5b80850194505087601f850112614328575f80fd5b83519250614338613eaf84613e27565b838152888285870101111561434b575f80fd5b61435a8483830184880161409a565b8060408401525081955061436f81880161429f565b9450505050509250929050565b5f6001600160401b0380831681810361439757614397613f1d565b6001019392505050565b81810381811115610a2757610a27613f1d565b634e487b7160e01b5f52603260045260245ffd5b80820180821115610a2757610a27613f1d565b60208082526029908201527f56616c696461746f724d657373616765733a20696e76616c6964206d657373616040820152680ceca40d8cadccee8d60bb1b606082015260800190565b60208082526023908201527f56616c696461746f724d657373616765733a20696e76616c696420636f64656360408201526208125160ea1b606082015260800190565b60208082526027908201527f56616c696461746f724d657373616765733a20696e76616c6964206d657373616040820152666765207479706560c81b606082015260800190565b6001600160401b03818116838216019080821115613f5157613f51613f1d565b5f602082840312156144de575f80fd5b813561122781613cfa565b6001600160401b0381811683821602808216919082811461450c5761450c613f1d565b505092915050565b5f6001600160401b038084168061452d5761452d61418f565b92169190910492915050565b5f825161454a81846020870161409a565b9190910192915050565b5f60208284031215614564575f80fd5b813560ff81168114611227575f80fd5b5f60208284031215614584575f80fd5b815161122781613c8356fe4317713f7ecbdddd4bc99e95d903adedaa883b2e7c2551610bd13e2c7e473d00506f5356616c696461746f724d616e616765723a2064656c65676174696f6e20e92546d698950ddd38910d2e15ed1d923cd0a7b3dde9e2a6a3f380565559cb009b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00e92546d698950ddd38910d2e15ed1d923cd0a7b3dde9e2a6a3f380565559cb07a164736f6c6343000819000a", + ABI: "[{\"type\":\"constructor\",\"inputs\":[{\"name\":\"init\",\"type\":\"uint8\",\"internalType\":\"enumICMInitializable\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"WARP_MESSENGER\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"contractIWarpMessenger\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"activeValidators\",\"inputs\":[{\"name\":\"nodeID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"completeDelegatorRegistration\",\"inputs\":[{\"name\":\"messageIndex\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"delegationID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"completeEndDelegation\",\"inputs\":[{\"name\":\"messageIndex\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"delegationID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"completeEndValidation\",\"inputs\":[{\"name\":\"messageIndex\",\"type\":\"uint32\",\"internalType\":\"uint32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"completeValidatorRegistration\",\"inputs\":[{\"name\":\"messageIndex\",\"type\":\"uint32\",\"internalType\":\"uint32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"getWeight\",\"inputs\":[{\"name\":\"validationID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"initialize\",\"inputs\":[{\"name\":\"settings\",\"type\":\"tuple\",\"internalType\":\"structPoSValidatorManagerSettings\",\"components\":[{\"name\":\"baseSettings\",\"type\":\"tuple\",\"internalType\":\"structValidatorManagerSettings\",\"components\":[{\"name\":\"pChainBlockchainID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"subnetID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"maximumHourlyChurn\",\"type\":\"uint8\",\"internalType\":\"uint8\"}]},{\"name\":\"minimumStakeAmount\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"maximumStakeAmount\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"minimumStakeDuration\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"rewardCalculator\",\"type\":\"address\",\"internalType\":\"contractIRewardCalculator\"}]},{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"contractIERC20\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"initializeDelegatorRegistration\",\"inputs\":[{\"name\":\"validationID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"delegationAmount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"initializeEndDelegation\",\"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\":\"initializeEndValidation\",\"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\":\"initializeValidatorRegistration\",\"inputs\":[{\"name\":\"stakeAmount\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"nodeID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"registrationExpiry\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"blsPublicKey\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[{\"name\":\"validationID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"resendDelegatorRegistration\",\"inputs\":[{\"name\":\"delegationID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"resendEndDelegation\",\"inputs\":[{\"name\":\"delegationID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"resendEndValidatorMessage\",\"inputs\":[{\"name\":\"validationID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"resendRegisterValidatorMessage\",\"inputs\":[{\"name\":\"validationID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"valueToWeight\",\"inputs\":[{\"name\":\"value\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"stateMutability\":\"pure\"},{\"type\":\"function\",\"name\":\"weightToValue\",\"inputs\":[{\"name\":\"weight\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"pure\"},{\"type\":\"event\",\"name\":\"DelegationEnded\",\"inputs\":[{\"name\":\"delegationID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"validationID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"nonce\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"DelegatorAdded\",\"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\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"DelegatorRegistered\",\"inputs\":[{\"name\":\"delegationID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"validationID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"nonce\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"startTime\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"DelegatorRemovalInitialized\",\"inputs\":[{\"name\":\"delegationID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"validationID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"nonce\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"validatorWeight\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"},{\"name\":\"endTime\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"},{\"name\":\"setWeightMessageID\",\"type\":\"bytes32\",\"indexed\":false,\"internalType\":\"bytes32\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Initialized\",\"inputs\":[{\"name\":\"version\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ValidationPeriodCreated\",\"inputs\":[{\"name\":\"validationID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"nodeID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"registerValidationMessageID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"weight\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"},{\"name\":\"registrationExpiry\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ValidationPeriodEnded\",\"inputs\":[{\"name\":\"validationID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"status\",\"type\":\"uint8\",\"indexed\":true,\"internalType\":\"enumValidatorStatus\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ValidationPeriodRegistered\",\"inputs\":[{\"name\":\"validationID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"weight\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"},{\"name\":\"timestamp\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ValidatorRemovalInitialized\",\"inputs\":[{\"name\":\"validationID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"setWeightMessageID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"weight\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"},{\"name\":\"endTime\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"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\":\"FailedInnerCall\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"IncorrectInputLength\",\"inputs\":[{\"name\":\"expected\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"actual\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"InvalidInitialization\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"NotInitializing\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"ReentrancyGuardReentrantCall\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"SafeERC20FailedOperation\",\"inputs\":[{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"address\"}]}]", + Bin: "0x608060405234801561000f575f80fd5b5060405161406538038061406583398101604081905261002e91610107565b60018160018111156100425761004261012c565b0361004f5761004f610055565b50610140565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000900460ff16156100a55760405163f92ee8a960e01b815260040160405180910390fd5b80546001600160401b03908116146101045780546001600160401b0319166001600160401b0390811782556040519081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50565b5f60208284031215610117575f80fd5b815160028110610125575f80fd5b9392505050565b634e487b7160e01b5f52602160045260245ffd5b613f188061014d5f395ff3fe608060405234801561000f575f80fd5b5060043610610111575f3560e01c806366435abf1161009e57806398f3e2b41161006e57806398f3e2b4146102645780639e1bc4ef14610277578063a3a65e481461028a578063b771b3bc1461029d578063bee0a03f146102c3575f80fd5b806366435abf146102185780636d0e43fa1461022b57806376f786211461023e578063872fda6414610251575f80fd5b806327f39ca8116100e457806327f39ca8146101a15780632e2194d8146101b4578063467ef06f146101df5780635297fae6146101f25780636206585614610205575f80fd5b80630118acc4146101155780630322ed981461012a5780630cdd09851461013d578063162f1f611461018e575b5f80fd5b610128610123366004613522565b6102d6565b005b61012861013836600461355d565b61076a565b61017b61014b36600461355d565b5f9081527fe92546d698950ddd38910d2e15ed1d923cd0a7b3dde9e2a6a3f380565559cb08602052604090205490565b6040519081526020015b60405180910390f35b61012861019c36600461355d565b6108c6565b6101286101af366004613588565b610933565b6101c76101c236600461355d565b610a17565b6040516001600160401b039091168152602001610185565b6101286101ed3660046135c5565b610a2d565b6101286102003660046135de565b610db0565b61017b61021336600461361c565b610fa1565b6101c761022636600461355d565b610fba565b61012861023936600461355d565b610fce565b61012861024c366004613522565b61103b565b61017b61025f3660046136c7565b611056565b6101286102723660046135de565b61107b565b61017b610285366004613763565b61121b565b6101286102983660046135c5565b61122e565b6102ab6005600160991b0181565b6040516001600160a01b039091168152602001610185565b6101286102d136600461355d565b6113eb565b5f8381527f4317713f7ecbdddd4bc99e95d903adedaa883b2e7c2551610bd13e2c7e473d0360205260408120600101545f80516020613e6c8339815191529184156103285761032582856114ba565b90505b5f868152600384016020526040808220815161010081019092528054829060ff16600481111561035a5761035a613783565b600481111561036b5761036b613783565b8152815461010090046001600160a01b031660208201526001820154604082015260028201546001600160401b038082166060840152600160401b820481166080840152600160801b8204811660a0840152600160c01b909104811660c083015260039092015490911660e0909101529050336001600160a01b031681602001516001600160a01b0316146104505760405162461bcd60e51b815260206004820152603360248201525f80516020613e8c8339815191526044820152723737ba1037bbb732b210313c9039b2b73232b960691b60648201526084015b60405180910390fd5b60028151600481111561046557610465613783565b146104b25760405162461bcd60e51b815260206004820152602a60248201525f80516020613e8c8339815191526044820152696e6f742061637469766560b01b6064820152608401610447565b5f6104bc84611756565b60038084526001600160401b0342811660a0860152821660e08501525f8a815290870160205260409020835181549293508492829060ff1916600183600481111561050957610509613783565b021790555060208201518154610100600160a81b0319166101006001600160a01b0390921691909102178155604082015160018201556060820151600282018054608085015160a086015160c08701516001600160401b039586166001600160801b031990941693909317600160401b92861692909202919091176001600160801b0316600160801b918516919091026001600160c01b031617600160c01b9184169190910217905560e0909201516003909101805467ffffffffffffffff1916919092161790555f6105db856117ca565b905082606001516001600160401b03168160a001516001600160401b0316116106525760405162461bcd60e51b815260206004820152602360248201527f506f5356616c696461746f724d616e616765723a20496e76616c69642077656960448201526219da1d60ea1b6064820152608401610447565b5f83606001518260a0015161066791906137ab565b905061067386826118db565b5f61067f878584611923565b5f8c815260058a016020526040902090915061069b8282613855565b5060405163ee5b48eb60e01b81525f906005600160991b019063ee5b48eb906106c8908590600401613936565b6020604051808303815f875af11580156106e4573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906107089190613968565b604080516001600160401b03868116825242602083015291810183905291925086169089908e907f5318ab4d7cdf77056db2db5b539a08fe7d1a63d6885ecee8236a0dbda2843b4e9060600160405180910390a4505050505050505050505050565b5f8181527fe92546d698950ddd38910d2e15ed1d923cd0a7b3dde9e2a6a3f380565559cb066020526040812080545f80516020613eac8339815191529291906107b2906137d2565b90501180156107e4575060035f83815260078301602052604090205460ff1660058111156107e2576107e2613783565b145b6108485760405162461bcd60e51b815260206004820152602f60248201527f56616c696461746f724d616e616765723a2056616c696461746f72206e6f742060448201526e1c195b991a5b99c81c995b5bdd985b608a1b6064820152608401610447565b5f82815260068201602052604090819020905163ee5b48eb60e01b81526005600160991b019163ee5b48eb91610881919060040161397f565b6020604051808303815f875af115801561089d573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108c19190613968565b505050565b6108cf81611972565b5f8181527f4317713f7ecbdddd4bc99e95d903adedaa883b2e7c2551610bd13e2c7e473d05602052604090819020905163ee5b48eb60e01b81525f80516020613e6c833981519152916005600160991b019163ee5b48eb916108819160040161397f565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805460029190600160401b900460ff168061097c575080546001600160401b03808416911610155b1561099a5760405163f92ee8a960e01b815260040160405180910390fd5b805468ffffffffffffffffff19166001600160401b03831617600160401b1781556109c58484611a45565b805468ff0000000000000000191681556040516001600160401b03831681527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a150505050565b5f610a2764e8d4a5100083613a1d565b92915050565b5f80516020613eac8339815191525f610a4583611a5f565b90505f80610a568360400151611c40565b915091508015610abb5760405162461bcd60e51b815260206004820152602a60248201527f56616c696461746f724d616e616765723a20726567697374726174696f6e20736044820152691d1a5b1b081d985b1a5960b21b6064820152608401610447565b5f828152600785016020526040808220815161010081019092528054829060ff166005811115610aed57610aed613783565b6005811115610afe57610afe613783565b81526001820154602082015260028201546001600160a01b03811660408301526001600160401b03600160a01b909104811660608301526003928301548082166080840152600160401b8104821660a0840152600160801b8104821660c0840152600160c01b90041660e0909101529091505f9082516005811115610b8557610b85613783565b1480610ba35750600182516005811115610ba157610ba1613783565b145b610c025760405162461bcd60e51b815260206004820152602a60248201527f56616c696461746f724d616e616765723a20696e76616c69642076616c696461604482015269746f722073746174757360b01b6064820152608401610447565b600382516005811115610c1757610c17613783565b03610c3e57505f8381526006860160205260408120600491610c3991906134b3565b610c42565b5060055b6020808301515f90815260088801909152604081205581816005811115610c6b57610c6b613783565b90816005811115610c7e57610c7e613783565b9052505f84815260078701602052604090208251815484929190829060ff19166001836005811115610cb257610cb2613783565b021790555060208201516001820155604082015160028201805460608501516001600160401b03908116600160a01b026001600160e01b03199092166001600160a01b039094169390931717905560808301516003909201805460a085015160c086015160e0909601518416600160c01b026001600160c01b03968516600160801b02969096166001600160801b03918516600160401b026001600160801b0319909316959094169490941717929092161791909117905581516005811115610d7d57610d7d613783565b60405185907f1c08e59656f1a18dc2da76826cdc52805c43e897a17c50faefb8ab3c1526cc16905f90a350505050505050565b5f80516020613e6c8339815191525f610dc884611a5f565b90505f80610dd98360400151611cd3565b5091509150610de785611d6c565b5f8581526004850160205260408120610dff916134b3565b5f610e09836117ca565b9050816001600160401b031681608001516001600160401b03161015610e415760405162461bcd60e51b815260040161044790613a30565b5f8681526003860160205260409020600201546001600160401b03808416600160c01b909204161115610e865760405162461bcd60e51b815260040161044790613a72565b60015f87815260038701602052604090205460ff166004811115610eac57610eac613783565b14610f155760405162461bcd60e51b815260206004820152603360248201527f506f5356616c696461746f724d616e616765723a2064656c65676174696f6e4960448201527211081b9bdd081c195b991a5b99c81859191959606a1b6064820152608401610447565b5f868152600386016020908152604091829020805460ff1916600290811782550180546001600160401b0342818116600160401b0267ffffffffffffffff60401b19909316929092179092559251928352841691859189917f245fc69b36e168426e0306fc8d8300661b9af297c7958820dbf804f9f63e7064910160405180910390a450505050505050565b5f610a276001600160401b03831664e8d4a51000613abb565b5f610fc4826117ca565b60a0015192915050565b610fd781611d6c565b5f8181527f4317713f7ecbdddd4bc99e95d903adedaa883b2e7c2551610bd13e2c7e473d04602052604090819020905163ee5b48eb60e01b81525f80516020613e6c833981519152916005600160991b019163ee5b48eb916108819160040161397f565b811561104d5761104b83826114ba565b505b6108c183611e45565b5f80611061866121fd565b905061106f858286866122aa565b9150505b949350505050565b5f80516020613e6c8339815191525f61109384611a5f565b90505f806110a48360400151611cd3565b50915091506110b285611972565b5f85815260058501602052604081206110ca916134b3565b5f6110d4836117ca565b9050816001600160401b031681608001516001600160401b0316101561110c5760405162461bcd60e51b815260040161044790613a30565b5f8681526003808701602052604090912001546001600160401b038084169116111561114a5760405162461bcd60e51b815260040161044790613a72565b60035f87815260038701602052604090205460ff16600481111561117057611170613783565b146111c45760405162461bcd60e51b815260206004820152603160248201525f80516020613e8c8339815191526044820152701b9bdd081c195b991a5b99c81859191959607a1b6064820152608401610447565b5f868152600386016020526040808220805460ff19166004179055516001600160401b03841691859189917f52e9b1eaef84d46cda83ccb9d427267bc4d04f756b4a32c8302722b79e5c65ab91a450505050505050565b5f6112278333846126ff565b9392505050565b5f80516020613eac8339815191525f61124683611a5f565b90505f806112578360400151611c40565b91509150806112b95760405162461bcd60e51b815260206004820152602860248201527f56616c696461746f724d616e616765723a20526567697374726174696f6e206e6044820152671bdd081d985b1a5960c21b6064820152608401610447565b5f828152600585016020526040812080546112d3906137d2565b9050118015611305575060015f83815260078601602052604090205460ff16600581111561130357611303613783565b145b6113215760405162461bcd60e51b815260040161044790613ad2565b5f8281526005850160205260408120611339916134b3565b5f8281526007850160208181526040808420805460ff191660021781556003810180546001600160401b0342818116600160801b0267ffffffffffffffff60801b19909316929092178355600190930154875260088b0185528387208990559588905293835292548151600160401b90910490931683529082019290925283917ff8fd1c90fb9cfa2ca2358fdf5806b086ad43315d92b221c929efc7f105ce7568910160405180910390a25050505050565b5f8181527fe92546d698950ddd38910d2e15ed1d923cd0a7b3dde9e2a6a3f380565559cb056020526040812080545f80516020613eac833981519152929190611433906137d2565b9050118015611465575060015f83815260078301602052604090205460ff16600581111561146357611463613783565b145b6114815760405162461bcd60e51b815260040161044790613ad2565b5f82815260058201602052604090819020905163ee5b48eb60e01b81526005600160991b019163ee5b48eb91610881919060040161397f565b6040516306f8253560e41b815263ffffffff821660048201525f90819081906005600160991b0190636f825350906024015f60405180830381865afa158015611505573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f1916820160405261152c9190810190613b24565b915091508061158f5760405162461bcd60e51b815260206004820152602960248201527f506f5356616c696461746f724d616e616765723a20696e76616c69642077617260448201526870206d65737361676560b81b6064820152608401610447565b6005600160991b016001600160a01b0316634213cf786040518163ffffffff1660e01b8152600401602060405180830381865afa1580156115d2573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906115f69190613968565b82511461165a5760405162461bcd60e51b815260206004820152602c60248201527f506f5356616c696461746f724d616e616765723a20696e76616c696420736f7560448201526b1c98d94818da185a5b88125160a21b6064820152608401610447565b60208201516001600160a01b0316156116d05760405162461bcd60e51b815260206004820152603260248201527f506f5356616c696461746f724d616e616765723a20696e76616c6964206f726960448201527167696e2073656e646572206164647265737360701b6064820152608401610447565b5f806116df8460400151612aba565b9150915081871461174c5760405162461bcd60e51b815260206004820152603160248201527f506f5356616c696461746f724d616e616765723a20696e76616c6964207570746044820152701a5b59481d985b1a59185d1a5bdb881251607a1b6064820152608401610447565b9695505050505050565b5f8181525f80516020613eec8339815191526020526040812060030180545f80516020613eac833981519152916001600160401b039091169081908461179b83613bf6565b91906101000a8154816001600160401b0302191690836001600160401b03160217905550508092505050919050565b6040805161010080820183525f8083526020808401829052838501829052606084018290526080840182905260a0840182905260c0840182905260e084018290528582525f80516020613eec83398151915290528390208351918201909352825491925f80516020613eac83398151915292829060ff16600581111561185257611852613783565b600581111561186357611863613783565b81526001820154602082015260028201546001600160a01b03811660408301526001600160401b03600160a01b909104811660608301526003909201548083166080830152600160401b8104831660a0830152600160801b8104831660c0830152600160c01b900490911660e0909101529392505050565b5f9182525f80516020613eec833981519152602052604090912060030180546001600160401b03909216600160401b0267ffffffffffffffff60401b19909216919091179055565b604080515f6020820152600160e01b602282015260268101949094526001600160c01b031960c093841b811660468601529190921b16604e830152805180830360360181526056909201905290565b5f8181527f4317713f7ecbdddd4bc99e95d903adedaa883b2e7c2551610bd13e2c7e473d056020526040812080545f80516020613e6c8339815191529291906119ba906137d2565b90501180156119ec575060035f83815260038301602052604090205460ff1660048111156119ea576119ea613783565b145b611a415760405162461bcd60e51b815260206004820152603360248201525f80516020613e8c83398151915260448201527272656d6f76616c206e6f742070656e64696e6760681b6064820152608401610447565b5050565b611a4d612b4b565b611a5682612b96565b611a4181612bdc565b60408051606080820183525f8083526020830181905292820152905f80516020613eac8339815191526040516306f8253560e41b815263ffffffff851660048201529091505f9081906005600160991b0190636f825350906024015f60405180830381865afa158015611ad4573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052611afb9190810190613b24565b9150915080611b625760405162461bcd60e51b815260206004820152602d60248201527f56616c696461746f724d616e616765723a20496e76696e76616c6964616c696460448201526c2077617270206d65737361676560981b6064820152608401610447565b8254825114611bc55760405162461bcd60e51b815260206004820152602960248201527f56616c696461746f724d616e616765723a20696e76616c696420736f757263656044820152680818da185a5b88125160ba1b6064820152608401610447565b60208201516001600160a01b031615611c385760405162461bcd60e51b815260206004820152602f60248201527f56616c696461746f724d616e616765723a20696e76616c6964206f726967696e60448201526e2073656e646572206164647265737360881b6064820152608401610447565b509392505050565b5f808251602714611c635760405162461bcd60e51b815260040161044790613c1b565b5f805f80611c7087612c90565b9296509094509250905060f084901c15611c9c5760405162461bcd60e51b815260040161044790613c64565b60e083901c600214611cc05760405162461bcd60e51b815260040161044790613ca7565b909660f89190911c151595509350505050565b5f805f8351603614611cf75760405162461bcd60e51b815260040161044790613c1b565b5f805f805f611d0589612ce3565b93985091965094509250905060f085901c15611d335760405162461bcd60e51b815260040161044790613c64565b60e084901c600314611d575760405162461bcd60e51b815260040161044790613ca7565b919860c091821c985091901c95509350505050565b5f8181527f4317713f7ecbdddd4bc99e95d903adedaa883b2e7c2551610bd13e2c7e473d046020526040812080545f80516020613e6c833981519152929190611db4906137d2565b9050118015611de6575060015f83815260038301602052604090205460ff166004811115611de457611de4613783565b145b611a415760405162461bcd60e51b815260206004820152603860248201525f80516020613e8c83398151915260448201527f726567697374726174696f6e206e6f742070656e64696e6700000000000000006064820152608401610447565b5f8181525f80516020613eec83398151915260205260408082208151610100810190925280545f80516020613eac83398151915293929190829060ff166005811115611e9357611e93613783565b6005811115611ea457611ea4613783565b8152600182015460208201526002808301546001600160a01b03811660408401526001600160401b03600160a01b909104811660608401526003909301548084166080840152600160401b8104841660a0840152600160801b8104841660c0840152600160c01b900490921660e09091015290915081516005811115611f2c57611f2c613783565b14611f885760405162461bcd60e51b815260206004820152602660248201527f56616c696461746f724d616e616765723a2076616c696461746f72206e6f742060448201526561637469766560d01b6064820152608401610447565b60408101516001600160a01b0316336001600160a01b0316146120025760405162461bcd60e51b815260206004820152602c60248201527f56616c696461746f724d616e616765723a2073656e646572206e6f742076616c60448201526b34b230ba37b91037bbb732b960a11b6064820152608401610447565b61200f8160a00151612d3f565b60038152426001600160401b031660e08201525f83815260078301602052604090208151815483929190829060ff1916600183600581111561205357612053613783565b021790555060208201516001820155604082015160028201805460608501516001600160401b03908116600160a01b026001600160e01b03199092166001600160a01b039094169390931717905560808301516003909201805460a085015160c086015160e0909601518416600160c01b026001600160c01b03968516600160801b02969096166001600160801b03918516600160401b026001600160801b031990931695909416949094171792909216179190911790555f61211f8461211981611756565b5f611923565b5f858152600685016020526040902090915061213b8282613855565b5060405163ee5b48eb60e01b81525f906005600160991b019063ee5b48eb90612168908590600401613936565b6020604051808303815f875af1158015612184573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906121a89190613968565b60a0840151604080516001600160401b039092168252426020830152919250829187917f13d58394cf269d48bcf927959a29a5ffee7c9924dafff8927ecdf3c48ffa7c67910160405180910390a35050505050565b5f5f80516020613e6c8339815191528161221684612ee0565b90505f61222282610a17565b83549091506001600160401b0382161080159061224c57508260010154816001600160401b031611155b6110735760405162461bcd60e51b815260206004820152602960248201527f506f5356616c696461746f724d616e616765723a20696e76616c6964207374616044820152681ad948185b5bdd5b9d60ba1b6064820152608401610447565b5f6122b3612f16565b5f80516020613eac833981519152426001600160401b0385161180156122ed57506001600160401b0384166122eb426202a300613cee565b115b61234f5760405162461bcd60e51b815260206004820152602d60248201527f56616c696461746f724d616e616765723a20696e76616c69642072656769737460448201526c726174696f6e2065787069727960981b6064820152608401610447565b856123a65760405162461bcd60e51b815260206004820152602160248201527f56616c696461746f724d616e616765723a20696e76616c6964206e6f646520496044820152601160fa1b6064820152608401610447565b5f868152600882016020526040902054156124145760405162461bcd60e51b815260206004820152602860248201527f56616c696461746f724d616e616765723a206e6f646520494420616c72656164604482015267792061637469766560c01b6064820152608401610447565b825160301461247b5760405162461bcd60e51b815260206004820152602d60248201527f56616c696461746f724d616e616765723a20696e76616c696420626c7350756260448201526c0d8d2c696caf240d8cadccee8d609b1b6064820152608401610447565b61248485612d3f565b5f806124cb6040518060a00160405280856001015481526020018a8152602001896001600160401b03168152602001886001600160401b0316815260200187815250612f4d565b5f828152600586016020526040902091935091506124e98282613855565b5060405163ee5b48eb60e01b81525f906005600160991b019063ee5b48eb90612516908590600401613936565b6020604051808303815f875af1158015612532573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906125569190613968565b604080516101008101825260018152602081018c90529192508101336001600160a01b031681526001600160401b038a1660208083018290525f604080850182905260608501939093526080840181905260a0909301839052868352600788019052902081518154829060ff191660018360058111156125d8576125d8613783565b021790555060208201516001820155604082015160028201805460608501516001600160401b03908116600160a01b026001600160e01b03199092166001600160a01b039094169390931717905560808301516003909201805460a085015160c086015160e0909601518416600160c01b026001600160c01b03968516600160801b02969096166001600160801b03918516600160401b026001600160801b0319909316959094169490941717929092161791909117905561269983611756565b50604080516001600160401b03808b1682528916602082015282918b9186917f79b81620b81daf2c08cd5bb3dbb79e75d2d7a87f52171fde5aadc8c47823026e910160405180910390a450909250505061107360015f80516020613ecc83398151915255565b5f612708612f16565b5f6127156101c284612ee0565b90505f80516020613e6c8339815191525f61272f876117ca565b905060028151600581111561274657612746613783565b146127a55760405162461bcd60e51b815260206004820152602960248201527f506f5356616c696461746f724d616e616765723a2076616c696461746f72206e6044820152686f742061637469766560b81b6064820152608401610447565b5f838260a001516127b69190613d01565b90506127c288826118db565b5f6127cc89611756565b90505f8989836040516020016128149392919092835260609190911b6bffffffffffffffffffffffff1916602083015260c01b6001600160c01b0319166034820152603c0190565b60405160208183030381529060405280519060200120905061283586612d3f565b5f6128418b8486611923565b5f838152600488016020526040902090915061285d8282613855565b5060405163ee5b48eb60e01b81525f906005600160991b019063ee5b48eb9061288a908590600401613936565b6020604051808303815f875af11580156128a6573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906128ca9190613968565b60408051610100810190915290915080600181526020018c6001600160a01b031681526020018d8152602001896001600160401b031681526020015f6001600160401b031681526020015f6001600160401b03168152602001856001600160401b031681526020015f6001600160401b0316815250876003015f8581526020019081526020015f205f820151815f015f6101000a81548160ff0219169083600481111561297957612979613783565b02179055506020828101518254610100600160a81b0319166101006001600160a01b039283160217835560408085015160018501556060808601516002860180546080808a015160a08b015160c08c01516001600160401b039687166001600160801b031990951694909417600160401b92871692909202919091176001600160801b0316600160801b918616919091026001600160c01b031617600160c01b928516929092029190911790915560e0909701516003909601805467ffffffffffffffff19169682169690961790955581518a861681528b861694810194909452938d1690830152918101849052908d16918e9186917fb0024b263bc3a0b728a6edea50a69efa841189f8d32ee8af9d1c2b1a1a223426910160405180910390a45090965050505050505061122760015f80516020613ecc83398151915255565b5f808251602e14612add5760405162461bcd60e51b815260040161044790613c1b565b5f805f80612aea87613063565b9296509094509250905060f084901c15612b165760405162461bcd60e51b815260040161044790613c64565b60e083901c600414612b3a5760405162461bcd60e51b815260040161044790613ca7565b909660c09190911c95509350505050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054600160401b900460ff16612b9457604051631afcd79f60e31b815260040160405180910390fd5b565b612b9e612b4b565b612ba781613095565b612bd960608201356080830135612bc460c0850160a0860161361c565b612bd460e0860160c08701613d21565b6130b6565b50565b612be4612b4b565b7f6e5bdfcce15e53c3406ea67bfce37dcd26f5152d5492824e43fd5e3c8ac5ab006001600160a01b038216612c705760405162461bcd60e51b815260206004820152602c60248201527f4552433230546f6b656e5374616b696e674d616e616765723a207a65726f207460448201526b6f6b656e206164647265737360a01b6064820152608401610447565b80546001600160a01b0319166001600160a01b0392909216919091179055565b5f805f808451602714612cc25784516040516241835b60e31b8152600481019190915260276024820152604401610447565b50505050602081015160228201516026830151604690930151919390929190565b5f805f805f8551603614612d165785516040516241835b60e31b8152600481019190915260366024820152604401610447565b505050506020820151602283015160268401516046850151604e90950151929591949093509190565b7fe92546d698950ddd38910d2e15ed1d923cd0a7b3dde9e2a6a3f380565559cb02545f80516020613eac8339815191529060ff165f03612d7d575050565b60408051606081018252600383015480825260048401546001600160401b038082166020850152600160401b9091041692820192909252904290610e1090612dc59083613d3c565b10612de1576001600160401b0384166040830152808252612e00565b8382604001818151612df39190613d01565b6001600160401b03169052505b5f826020015183604001516064612e179190613d4f565b612e219190613d7a565b600285015490915060ff9081169082161115612e9c5760405162461bcd60e51b815260206004820152603460248201527f56616c696461746f724d616e616765723a206d6178696d756d20686f75726c796044820152730818da1d5c9b881c985d1948195e18d95959195960621b6064820152608401610447565b5050805160038301556020810151600490920180546040909201516001600160401b03908116600160401b026001600160801b031990931693169290921717905550565b5f610a27827f6e5bdfcce15e53c3406ea67bfce37dcd26f5152d5492824e43fd5e3c8ac5ab00546001600160a01b031690613111565b5f80516020613ecc833981519152805460011901612f4757604051633ee5aeb560e01b815260040160405180910390fd5b60029055565b5f6060826080015151603014612fb75760405162461bcd60e51b815260206004820152602960248201527f5374616b696e674d657373616765733a20696e76616c6964207369676e6174756044820152680e4ca40d8cadccee8d60bb1b6064820152608401610447565b5f805f855f01518660200151876040015188608001518960600151604051602001612fe89796959493929190613d9f565b60405160208183030381529060405290506002816040516130099190613e15565b602060405180830381855afa158015613024573d5f803e3d5ffd5b5050506040513d601f19601f820116820180604052508101906130479190613968565b94909350915050565b60015f80516020613ecc83398151915255565b5f805f808451602e14612cc25784516040516241835b60e31b81526004810191909152602e6024820152604401610447565b61309d612b4b565b6130a5613273565b6130ad613283565b612bd98161328b565b6130be612b4b565b5f5f80516020613e6c833981519152948555506001840192909255600290920180546001600160a01b03909216600160401b026001600160e01b03199092166001600160401b0390931692909217179055565b6040516370a0823160e01b81523060048201525f9081906001600160a01b038516906370a0823190602401602060405180830381865afa158015613157573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061317b9190613968565b90506131926001600160a01b0385163330866132f7565b6040516370a0823160e01b81523060048201525f906001600160a01b038616906370a0823190602401602060405180830381865afa1580156131d6573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906131fa9190613968565b90508181116132605760405162461bcd60e51b815260206004820152602c60248201527f5361666545524332305472616e7366657246726f6d3a2062616c616e6365206e60448201526b1bdd081a5b98dc99585cd95960a21b6064820152608401610447565b61326a8282613d3c565b95945050505050565b61327b612b4b565b612b94613357565b612b94612b4b565b613293612b4b565b80355f80516020613eac83398151915290815560208201357fe92546d698950ddd38910d2e15ed1d923cd0a7b3dde9e2a6a3f380565559cb01556132dd6060830160408401613e30565b600291909101805460ff191660ff90921691909117905550565b604080516001600160a01b0385811660248301528416604482015260648082018490528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b17905261335190859061335f565b50505050565b613050612b4b565b5f6133736001600160a01b038416836133c0565b905080515f141580156133975750808060200190518101906133959190613e50565b155b156108c157604051635274afe760e01b81526001600160a01b0384166004820152602401610447565b606061122783835f845f80856001600160a01b031684866040516133e49190613e15565b5f6040518083038185875af1925050503d805f811461341e576040519150601f19603f3d011682016040523d82523d5f602084013e613423565b606091505b509150915061174c8683836060826134435761343e8261348a565b611227565b815115801561345a57506001600160a01b0384163b155b1561348357604051639996b31560e01b81526001600160a01b0385166004820152602401610447565b5080611227565b80511561349a5780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b5080546134bf906137d2565b5f825580601f106134ce575050565b601f0160209004905f5260205f2090810190612bd991905b808211156134f9575f81556001016134e6565b5090565b8015158114612bd9575f80fd5b803563ffffffff8116811461351d575f80fd5b919050565b5f805f60608486031215613534575f80fd5b833592506020840135613546816134fd565b91506135546040850161350a565b90509250925092565b5f6020828403121561356d575f80fd5b5035919050565b6001600160a01b0381168114612bd9575f80fd5b5f8082840361010081121561359b575f80fd5b60e08112156135a8575f80fd5b5082915060e08301356135ba81613574565b809150509250929050565b5f602082840312156135d5575f80fd5b6112278261350a565b5f80604083850312156135ef575f80fd5b6135f88361350a565b946020939093013593505050565b80356001600160401b038116811461351d575f80fd5b5f6020828403121561362c575f80fd5b61122782613606565b634e487b7160e01b5f52604160045260245ffd5b604051606081016001600160401b038111828210171561366b5761366b613635565b60405290565b604051601f8201601f191681016001600160401b038111828210171561369957613699613635565b604052919050565b5f6001600160401b038211156136b9576136b9613635565b50601f01601f191660200190565b5f805f80608085870312156136da575f80fd5b84359350602085013592506136f160408601613606565b915060608501356001600160401b0381111561370b575f80fd5b8501601f8101871361371b575f80fd5b803561372e613729826136a1565b613671565b818152886020838501011115613742575f80fd5b816020840160208301375f6020838301015280935050505092959194509250565b5f8060408385031215613774575f80fd5b50508035926020909101359150565b634e487b7160e01b5f52602160045260245ffd5b634e487b7160e01b5f52601160045260245ffd5b6001600160401b038281168282160390808211156137cb576137cb613797565b5092915050565b600181811c908216806137e657607f821691505b60208210810361380457634e487b7160e01b5f52602260045260245ffd5b50919050565b601f8211156108c157805f5260205f20601f840160051c8101602085101561382f5750805b601f840160051c820191505b8181101561384e575f815560010161383b565b5050505050565b81516001600160401b0381111561386e5761386e613635565b6138828161387c84546137d2565b8461380a565b602080601f8311600181146138b5575f841561389e5750858301515b5f19600386901b1c1916600185901b17855561390c565b5f85815260208120601f198616915b828110156138e3578886015182559484019460019091019084016138c4565b508582101561390057878501515f19600388901b60f8161c191681555b505060018460011b0185555b505050505050565b5f5b8381101561392e578181015183820152602001613916565b50505f910152565b602081525f8251806020840152613954816040850160208701613914565b601f01601f19169190910160400192915050565b5f60208284031215613978575f80fd5b5051919050565b5f60208083525f8454613991816137d2565b806020870152604060018084165f81146139b257600181146139ce576139fb565b60ff19851660408a0152604084151560051b8a010195506139fb565b895f5260205f205f5b858110156139f25781548b82018601529083019088016139d7565b8a016040019650505b509398975050505050505050565b634e487b7160e01b5f52601260045260245ffd5b5f82613a2b57613a2b613a09565b500490565b60208082526022908201527f506f5356616c696461746f724d616e616765723a20696e76616c6964206e6f6e604082015261636560f01b606082015260800190565b60208082526029908201527f506f5356616c696461746f724d616e616765723a206e6f6e636520646f6573206040820152680dcdee840dac2e8c6d60bb1b606082015260800190565b8082028115828204841417610a2757610a27613797565b60208082526027908201527f56616c696461746f724d616e616765723a20696e76616c69642076616c6964616040820152661d1a5bdb88125160ca1b606082015260800190565b805161351d816134fd565b5f8060408385031215613b35575f80fd5b82516001600160401b0380821115613b4b575f80fd5b9084019060608287031215613b5e575f80fd5b613b66613649565b82518152602080840151613b7981613574565b82820152604084015183811115613b8e575f80fd5b80850194505087601f850112613ba2575f80fd5b83519250613bb2613729846136a1565b8381528882858701011115613bc5575f80fd5b613bd484838301848801613914565b80604084015250819550613be9818801613b19565b9450505050509250929050565b5f6001600160401b03808316818103613c1157613c11613797565b6001019392505050565b60208082526029908201527f56616c696461746f724d657373616765733a20696e76616c6964206d657373616040820152680ceca40d8cadccee8d60bb1b606082015260800190565b60208082526023908201527f56616c696461746f724d657373616765733a20696e76616c696420636f64656360408201526208125160ea1b606082015260800190565b60208082526027908201527f56616c696461746f724d657373616765733a20696e76616c6964206d657373616040820152666765207479706560c81b606082015260800190565b80820180821115610a2757610a27613797565b6001600160401b038181168382160190808211156137cb576137cb613797565b5f60208284031215613d31575f80fd5b813561122781613574565b81810381811115610a2757610a27613797565b6001600160401b03818116838216028082169190828114613d7257613d72613797565b505092915050565b5f6001600160401b0380841680613d9357613d93613a09565b92169190910492915050565b61ffff60f01b8860f01b16815263ffffffff60e01b8760e01b1660028201528560068201528460268201525f6001600160401b0360c01b808660c01b1660468401528451613df481604e860160208901613914565b60c09490941b1691909201604e810191909152605601979650505050505050565b5f8251613e26818460208701613914565b9190910192915050565b5f60208284031215613e40575f80fd5b813560ff81168114611227575f80fd5b5f60208284031215613e60575f80fd5b8151611227816134fd56fe4317713f7ecbdddd4bc99e95d903adedaa883b2e7c2551610bd13e2c7e473d00506f5356616c696461746f724d616e616765723a2064656c65676174696f6e20e92546d698950ddd38910d2e15ed1d923cd0a7b3dde9e2a6a3f380565559cb009b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00e92546d698950ddd38910d2e15ed1d923cd0a7b3dde9e2a6a3f380565559cb07a164736f6c6343000819000a", } // ERC20TokenStakingManagerABI is the input ABI used to generate the binding from. diff --git a/abi-bindings/go/staking/NativeTokenStakingManager/NativeTokenStakingManager.go b/abi-bindings/go/staking/NativeTokenStakingManager/NativeTokenStakingManager.go index dc2baffd2..05c0f942a 100644 --- a/abi-bindings/go/staking/NativeTokenStakingManager/NativeTokenStakingManager.go +++ b/abi-bindings/go/staking/NativeTokenStakingManager/NativeTokenStakingManager.go @@ -47,8 +47,8 @@ type ValidatorManagerSettings struct { // NativeTokenStakingManagerMetaData contains all meta data concerning the NativeTokenStakingManager contract. var NativeTokenStakingManagerMetaData = &bind.MetaData{ - ABI: "[{\"type\":\"constructor\",\"inputs\":[{\"name\":\"init\",\"type\":\"uint8\",\"internalType\":\"enumICMInitializable\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"WARP_MESSENGER\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"contractIWarpMessenger\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"activeValidators\",\"inputs\":[{\"name\":\"nodeID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"completeDelegatorRegistration\",\"inputs\":[{\"name\":\"messageIndex\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"delegationID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"completeEndDelegation\",\"inputs\":[{\"name\":\"messageIndex\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"delegationID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"completeEndValidation\",\"inputs\":[{\"name\":\"messageIndex\",\"type\":\"uint32\",\"internalType\":\"uint32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"completeValidatorRegistration\",\"inputs\":[{\"name\":\"messageIndex\",\"type\":\"uint32\",\"internalType\":\"uint32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"getWeight\",\"inputs\":[{\"name\":\"validationID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"initialize\",\"inputs\":[{\"name\":\"settings\",\"type\":\"tuple\",\"internalType\":\"structPoSValidatorManagerSettings\",\"components\":[{\"name\":\"baseSettings\",\"type\":\"tuple\",\"internalType\":\"structValidatorManagerSettings\",\"components\":[{\"name\":\"pChainBlockchainID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"subnetID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"maximumHourlyChurn\",\"type\":\"uint8\",\"internalType\":\"uint8\"}]},{\"name\":\"minimumStakeAmount\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"maximumStakeAmount\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"minimumStakeDuration\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"rewardCalculator\",\"type\":\"address\",\"internalType\":\"contractIRewardCalculator\"}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"initializeDelegatorRegistration\",\"inputs\":[{\"name\":\"validationID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"initializeEndDelegation\",\"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\":\"initializeEndValidation\",\"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\":\"initializeValidatorRegistration\",\"inputs\":[{\"name\":\"nodeID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"registrationExpiry\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"blsPublicKey\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"resendDelegatorRegistration\",\"inputs\":[{\"name\":\"delegationID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"resendEndDelegation\",\"inputs\":[{\"name\":\"delegationID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"resendEndValidatorMessage\",\"inputs\":[{\"name\":\"validationID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"resendRegisterValidatorMessage\",\"inputs\":[{\"name\":\"validationID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"valueToWeight\",\"inputs\":[{\"name\":\"value\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"stateMutability\":\"pure\"},{\"type\":\"function\",\"name\":\"weightToValue\",\"inputs\":[{\"name\":\"weight\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"pure\"},{\"type\":\"event\",\"name\":\"DelegationEnded\",\"inputs\":[{\"name\":\"delegationID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"validationID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"nonce\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"DelegatorAdded\",\"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\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"DelegatorRegistered\",\"inputs\":[{\"name\":\"delegationID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"validationID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"nonce\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"startTime\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"DelegatorRemovalInitialized\",\"inputs\":[{\"name\":\"delegationID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"validationID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"nonce\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"validatorWeight\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"},{\"name\":\"endTime\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"},{\"name\":\"setWeightMessageID\",\"type\":\"bytes32\",\"indexed\":false,\"internalType\":\"bytes32\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Initialized\",\"inputs\":[{\"name\":\"version\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ValidationPeriodCreated\",\"inputs\":[{\"name\":\"validationID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"nodeID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"registerValidationMessageID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"weight\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"},{\"name\":\"registrationExpiry\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ValidationPeriodEnded\",\"inputs\":[{\"name\":\"validationID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"status\",\"type\":\"uint8\",\"indexed\":true,\"internalType\":\"enumValidatorStatus\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ValidationPeriodRegistered\",\"inputs\":[{\"name\":\"validationID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"weight\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"},{\"name\":\"timestamp\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ValidatorRemovalInitialized\",\"inputs\":[{\"name\":\"validationID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"setWeightMessageID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"weight\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"},{\"name\":\"endTime\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"error\",\"name\":\"InvalidInitialization\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"NotInitializing\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"ReentrancyGuardReentrantCall\",\"inputs\":[]}]", - Bin: "0x608060405234801561000f575f80fd5b506040516143b13803806143b183398101604081905261002e91610107565b60018160018111156100425761004261012c565b0361004f5761004f610055565b50610140565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000900460ff16156100a55760405163f92ee8a960e01b815260040160405180910390fd5b80546001600160401b03908116146101045780546001600160401b0319166001600160401b0390811782556040519081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50565b5f60208284031215610117575f80fd5b815160028110610125575f80fd5b9392505050565b634e487b7160e01b5f52602160045260245ffd5b6142648061014d5f395ff3fe608060405260043610610104575f3560e01c806366435abf11610092578063a3a65e4811610062578063a3a65e48146102f3578063b771b3bc14610312578063bee0a03f14610344578063c599e24f14610363578063f40797d714610376575f80fd5b806366435abf146102775780636d0e43fa1461029657806376f78621146102b557806398f3e2b4146102d4575f80fd5b8063162f1f61116100d8578063162f1f61146101c45780632e2194d8146101e3578063467ef06f1461021a5780635297fae6146102395780636206585614610258575f80fd5b8062e41792146101085780630118acc4146101295780630322ed98146101485780630cdd098514610167575b5f80fd5b348015610113575f80fd5b5061012761012236600461391d565b610389565b005b348015610134575f80fd5b50610127610143366004613958565b61046b565b348015610153575f80fd5b50610127610162366004613993565b6108ff565b348015610172575f80fd5b506101b1610181366004613993565b5f9081527fe92546d698950ddd38910d2e15ed1d923cd0a7b3dde9e2a6a3f380565559cb08602052604090205490565b6040519081526020015b60405180910390f35b3480156101cf575f80fd5b506101276101de366004613993565b610a5b565b3480156101ee575f80fd5b506102026101fd366004613993565b610ac8565b6040516001600160401b0390911681526020016101bb565b348015610225575f80fd5b506101276102343660046139aa565b610ade565b348015610244575f80fd5b506101276102533660046139c3565b610e61565b348015610263575f80fd5b506101b1610272366004613a01565b611052565b348015610282575f80fd5b50610202610291366004613993565b61106b565b3480156102a1575f80fd5b506101276102b0366004613993565b61107f565b3480156102c0575f80fd5b506101276102cf366004613958565b6110ec565b3480156102df575f80fd5b506101276102ee3660046139c3565b611107565b3480156102fe575f80fd5b5061012761030d3660046139aa565b6112a7565b34801561031d575f80fd5b5061032c6005600160991b0181565b6040516001600160a01b0390911681526020016101bb565b34801561034f575f80fd5b5061012761035e366004613993565b611464565b6101b1610371366004613993565b611533565b6101b1610384366004613aac565b61153f565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805460029190600160401b900460ff16806103d2575080546001600160401b03808416911610155b156103f05760405163f92ee8a960e01b815260040160405180910390fd5b805468ffffffffffffffffff19166001600160401b03831617600160401b17815561041a83611563565b805468ff0000000000000000191681556040516001600160401b03831681527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a1505050565b5f8381527f4317713f7ecbdddd4bc99e95d903adedaa883b2e7c2551610bd13e2c7e473d0360205260408120600101545f805160206141b88339815191529184156104bd576104ba8285611577565b90505b5f868152600384016020526040808220815161010081019092528054829060ff1660048111156104ef576104ef613b3e565b600481111561050057610500613b3e565b8152815461010090046001600160a01b031660208201526001820154604082015260028201546001600160401b038082166060840152600160401b820481166080840152600160801b8204811660a0840152600160c01b909104811660c083015260039092015490911660e0909101529050336001600160a01b031681602001516001600160a01b0316146105e55760405162461bcd60e51b815260206004820152603360248201525f805160206141d88339815191526044820152723737ba1037bbb732b210313c9039b2b73232b960691b60648201526084015b60405180910390fd5b6002815160048111156105fa576105fa613b3e565b146106475760405162461bcd60e51b815260206004820152602a60248201525f805160206141d88339815191526044820152696e6f742061637469766560b01b60648201526084016105dc565b5f61065184611813565b60038084526001600160401b0342811660a0860152821660e08501525f8a815290870160205260409020835181549293508492829060ff1916600183600481111561069e5761069e613b3e565b021790555060208201518154610100600160a81b0319166101006001600160a01b0390921691909102178155604082015160018201556060820151600282018054608085015160a086015160c08701516001600160401b039586166001600160801b031990941693909317600160401b92861692909202919091176001600160801b0316600160801b918516919091026001600160c01b031617600160c01b9184169190910217905560e0909201516003909101805467ffffffffffffffff1916919092161790555f61077085611887565b905082606001516001600160401b03168160a001516001600160401b0316116107e75760405162461bcd60e51b815260206004820152602360248201527f506f5356616c696461746f724d616e616765723a20496e76616c69642077656960448201526219da1d60ea1b60648201526084016105dc565b5f83606001518260a001516107fc9190613b66565b90506108088682611998565b5f6108148785846119e0565b5f8c815260058a01602052604090209091506108308282613c0a565b5060405163ee5b48eb60e01b81525f906005600160991b019063ee5b48eb9061085d908590600401613ceb565b6020604051808303815f875af1158015610879573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061089d9190613d1d565b604080516001600160401b03868116825242602083015291810183905291925086169089908e907f5318ab4d7cdf77056db2db5b539a08fe7d1a63d6885ecee8236a0dbda2843b4e9060600160405180910390a4505050505050505050505050565b5f8181527fe92546d698950ddd38910d2e15ed1d923cd0a7b3dde9e2a6a3f380565559cb066020526040812080545f805160206141f883398151915292919061094790613b8d565b9050118015610979575060035f83815260078301602052604090205460ff16600581111561097757610977613b3e565b145b6109dd5760405162461bcd60e51b815260206004820152602f60248201527f56616c696461746f724d616e616765723a2056616c696461746f72206e6f742060448201526e1c195b991a5b99c81c995b5bdd985b608a1b60648201526084016105dc565b5f82815260068201602052604090819020905163ee5b48eb60e01b81526005600160991b019163ee5b48eb91610a169190600401613d34565b6020604051808303815f875af1158015610a32573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a569190613d1d565b505050565b610a6481611bfd565b5f8181527f4317713f7ecbdddd4bc99e95d903adedaa883b2e7c2551610bd13e2c7e473d05602052604090819020905163ee5b48eb60e01b81525f805160206141b8833981519152916005600160991b019163ee5b48eb91610a1691600401613d34565b5f610ad864e8d4a5100083613dd2565b92915050565b5f805160206141f88339815191525f610af683611cd0565b90505f80610b078360400151611eb1565b915091508015610b6c5760405162461bcd60e51b815260206004820152602a60248201527f56616c696461746f724d616e616765723a20726567697374726174696f6e20736044820152691d1a5b1b081d985b1a5960b21b60648201526084016105dc565b5f828152600785016020526040808220815161010081019092528054829060ff166005811115610b9e57610b9e613b3e565b6005811115610baf57610baf613b3e565b81526001820154602082015260028201546001600160a01b03811660408301526001600160401b03600160a01b909104811660608301526003928301548082166080840152600160401b8104821660a0840152600160801b8104821660c0840152600160c01b90041660e0909101529091505f9082516005811115610c3657610c36613b3e565b1480610c545750600182516005811115610c5257610c52613b3e565b145b610cb35760405162461bcd60e51b815260206004820152602a60248201527f56616c696461746f724d616e616765723a20696e76616c69642076616c696461604482015269746f722073746174757360b01b60648201526084016105dc565b600382516005811115610cc857610cc8613b3e565b03610cef57505f8381526006860160205260408120600491610cea91906138d3565b610cf3565b5060055b6020808301515f90815260088801909152604081205581816005811115610d1c57610d1c613b3e565b90816005811115610d2f57610d2f613b3e565b9052505f84815260078701602052604090208251815484929190829060ff19166001836005811115610d6357610d63613b3e565b021790555060208201516001820155604082015160028201805460608501516001600160401b03908116600160a01b026001600160e01b03199092166001600160a01b039094169390931717905560808301516003909201805460a085015160c086015160e0909601518416600160c01b026001600160c01b03968516600160801b02969096166001600160801b03918516600160401b026001600160801b0319909316959094169490941717929092161791909117905581516005811115610e2e57610e2e613b3e565b60405185907f1c08e59656f1a18dc2da76826cdc52805c43e897a17c50faefb8ab3c1526cc16905f90a350505050505050565b5f805160206141b88339815191525f610e7984611cd0565b90505f80610e8a8360400151612052565b5091509150610e988561228d565b5f8581526004850160205260408120610eb0916138d3565b5f610eba83611887565b9050816001600160401b031681608001516001600160401b03161015610ef25760405162461bcd60e51b81526004016105dc90613de5565b5f8681526003860160205260409020600201546001600160401b03808416600160c01b909204161115610f375760405162461bcd60e51b81526004016105dc90613e27565b60015f87815260038701602052604090205460ff166004811115610f5d57610f5d613b3e565b14610fc65760405162461bcd60e51b815260206004820152603360248201527f506f5356616c696461746f724d616e616765723a2064656c65676174696f6e4960448201527211081b9bdd081c195b991a5b99c81859191959606a1b60648201526084016105dc565b5f868152600386016020908152604091829020805460ff1916600290811782550180546001600160401b0342818116600160401b0267ffffffffffffffff60401b19909316929092179092559251928352841691859189917f245fc69b36e168426e0306fc8d8300661b9af297c7958820dbf804f9f63e7064910160405180910390a450505050505050565b5f610ad86001600160401b03831664e8d4a51000613e70565b5f61107582611887565b60a0015192915050565b6110888161228d565b5f8181527f4317713f7ecbdddd4bc99e95d903adedaa883b2e7c2551610bd13e2c7e473d04602052604090819020905163ee5b48eb60e01b81525f805160206141b8833981519152916005600160991b019163ee5b48eb91610a1691600401613d34565b81156110fe576110fc8382611577565b505b610a5683612366565b5f805160206141b88339815191525f61111f84611cd0565b90505f806111308360400151612052565b509150915061113e85611bfd565b5f8581526005850160205260408120611156916138d3565b5f61116083611887565b9050816001600160401b031681608001516001600160401b031610156111985760405162461bcd60e51b81526004016105dc90613de5565b5f8681526003808701602052604090912001546001600160401b03808416911611156111d65760405162461bcd60e51b81526004016105dc90613e27565b60035f87815260038701602052604090205460ff1660048111156111fc576111fc613b3e565b146112505760405162461bcd60e51b815260206004820152603160248201525f805160206141d88339815191526044820152701b9bdd081c195b991a5b99c81859191959607a1b60648201526084016105dc565b5f868152600386016020526040808220805460ff19166004179055516001600160401b03841691859189917f52e9b1eaef84d46cda83ccb9d427267bc4d04f756b4a32c8302722b79e5c65ab91a450505050505050565b5f805160206141f88339815191525f6112bf83611cd0565b90505f806112d08360400151611eb1565b91509150806113325760405162461bcd60e51b815260206004820152602860248201527f56616c696461746f724d616e616765723a20526567697374726174696f6e206e6044820152671bdd081d985b1a5960c21b60648201526084016105dc565b5f8281526005850160205260408120805461134c90613b8d565b905011801561137e575060015f83815260078601602052604090205460ff16600581111561137c5761137c613b3e565b145b61139a5760405162461bcd60e51b81526004016105dc90613e87565b5f82815260058501602052604081206113b2916138d3565b5f8281526007850160208181526040808420805460ff191660021781556003810180546001600160401b0342818116600160801b0267ffffffffffffffff60801b19909316929092178355600190930154875260088b0185528387208990559588905293835292548151600160401b90910490931683529082019290925283917ff8fd1c90fb9cfa2ca2358fdf5806b086ad43315d92b221c929efc7f105ce7568910160405180910390a25050505050565b5f8181527fe92546d698950ddd38910d2e15ed1d923cd0a7b3dde9e2a6a3f380565559cb056020526040812080545f805160206141f88339815191529291906114ac90613b8d565b90501180156114de575060015f83815260078301602052604090205460ff1660058111156114dc576114dc613b3e565b145b6114fa5760405162461bcd60e51b81526004016105dc90613e87565b5f82815260058201602052604090819020905163ee5b48eb60e01b81526005600160991b019163ee5b48eb91610a169190600401613d34565b5f610ad882333461271e565b5f8061154a34612ad6565b905061155885828686612b80565b9150505b9392505050565b61156b612fd5565b61157481613020565b50565b6040516306f8253560e41b815263ffffffff821660048201525f90819081906005600160991b0190636f825350906024015f60405180830381865afa1580156115c2573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526115e99190810190613eed565b915091508061164c5760405162461bcd60e51b815260206004820152602960248201527f506f5356616c696461746f724d616e616765723a20696e76616c69642077617260448201526870206d65737361676560b81b60648201526084016105dc565b6005600160991b016001600160a01b0316634213cf786040518163ffffffff1660e01b8152600401602060405180830381865afa15801561168f573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906116b39190613d1d565b8251146117175760405162461bcd60e51b815260206004820152602c60248201527f506f5356616c696461746f724d616e616765723a20696e76616c696420736f7560448201526b1c98d94818da185a5b88125160a21b60648201526084016105dc565b60208201516001600160a01b03161561178d5760405162461bcd60e51b815260206004820152603260248201527f506f5356616c696461746f724d616e616765723a20696e76616c6964206f726960448201527167696e2073656e646572206164647265737360701b60648201526084016105dc565b5f8061179c8460400151613063565b915091508187146118095760405162461bcd60e51b815260206004820152603160248201527f506f5356616c696461746f724d616e616765723a20696e76616c6964207570746044820152701a5b59481d985b1a59185d1a5bdb881251607a1b60648201526084016105dc565b9695505050505050565b5f8181525f805160206142388339815191526020526040812060030180545f805160206141f8833981519152916001600160401b039091169081908461185883613fbf565b91906101000a8154816001600160401b0302191690836001600160401b03160217905550508092505050919050565b6040805161010080820183525f8083526020808401829052838501829052606084018290526080840182905260a0840182905260c0840182905260e084018290528582525f8051602061423883398151915290528390208351918201909352825491925f805160206141f883398151915292829060ff16600581111561190f5761190f613b3e565b600581111561192057611920613b3e565b81526001820154602082015260028201546001600160a01b03811660408301526001600160401b03600160a01b909104811660608301526003909201548083166080830152600160401b8104831660a0830152600160801b8104831660c0830152600160c01b900490911660e0909101529392505050565b5f9182525f80516020614238833981519152602052604090912060030180546001600160401b03909216600160401b0267ffffffffffffffff60401b19909216919091179055565b60408051603680825260608281019093525f91906020820181803683370190505090505f5b6002811015611a5957611a19816001613fe4565b611a24906008613e70565b5081515f90839083908110611a3b57611a3b613ff7565b60200101906001600160f81b03191690815f1a905350600101611a05565b505f5b6004811015611abc57611a70816003613fe4565b611a7b906008613e70565b6001901c60f81b82611a8e83600261400b565b81518110611a9e57611a9e613ff7565b60200101906001600160f81b03191690815f1a905350600101611a5c565b505f5b6020811015611b1e57611ad381601f613fe4565b611ade906008613e70565b86901c60f81b82611af083600661400b565b81518110611b0057611b00613ff7565b60200101906001600160f81b03191690815f1a905350600101611abf565b505f5b6008811015611b8957611b35816007613fe4565b611b40906008613e70565b6001600160401b038616901c60f81b82611b5b83602661400b565b81518110611b6b57611b6b613ff7565b60200101906001600160f81b03191690815f1a905350600101611b21565b505f5b6008811015611bf457611ba0816007613fe4565b611bab906008613e70565b6001600160401b038516901c60f81b82611bc683602e61400b565b81518110611bd657611bd6613ff7565b60200101906001600160f81b03191690815f1a905350600101611b8c565b50949350505050565b5f8181527f4317713f7ecbdddd4bc99e95d903adedaa883b2e7c2551610bd13e2c7e473d056020526040812080545f805160206141b8833981519152929190611c4590613b8d565b9050118015611c77575060035f83815260038301602052604090205460ff166004811115611c7557611c75613b3e565b145b611ccc5760405162461bcd60e51b815260206004820152603360248201525f805160206141d883398151915260448201527272656d6f76616c206e6f742070656e64696e6760681b60648201526084016105dc565b5050565b60408051606080820183525f8083526020830181905292820152905f805160206141f88339815191526040516306f8253560e41b815263ffffffff851660048201529091505f9081906005600160991b0190636f825350906024015f60405180830381865afa158015611d45573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052611d6c9190810190613eed565b9150915080611dd35760405162461bcd60e51b815260206004820152602d60248201527f56616c696461746f724d616e616765723a20496e76696e76616c6964616c696460448201526c2077617270206d65737361676560981b60648201526084016105dc565b8254825114611e365760405162461bcd60e51b815260206004820152602960248201527f56616c696461746f724d616e616765723a20696e76616c696420736f757263656044820152680818da185a5b88125160ba1b60648201526084016105dc565b60208201516001600160a01b031615611ea95760405162461bcd60e51b815260206004820152602f60248201527f56616c696461746f724d616e616765723a20696e76616c6964206f726967696e60448201526e2073656e646572206164647265737360881b60648201526084016105dc565b509392505050565b5f808251602714611ed45760405162461bcd60e51b81526004016105dc9061401e565b5f805b6002811015611f2357611eeb816001613fe4565b611ef6906008613e70565b61ffff16858281518110611f0c57611f0c613ff7565b016020015160f81c901b9190911790600101611ed7565b5061ffff811615611f465760405162461bcd60e51b81526004016105dc90614067565b5f805b6004811015611fa157611f5d816003613fe4565b611f68906008613e70565b63ffffffff1686611f7a83600261400b565b81518110611f8a57611f8a613ff7565b016020015160f81c901b9190911790600101611f49565b5063ffffffff8116600214611fc85760405162461bcd60e51b81526004016105dc906140aa565b5f805b602081101561201d57611fdf81601f613fe4565b611fea906008613e70565b87611ff683600661400b565b8151811061200657612006613ff7565b016020015160f81c901b9190911790600101611fcb565b505f8660268151811061203257612032613ff7565b016020015191976001600160f81b03199092161515965090945050505050565b5f805f83516036146120765760405162461bcd60e51b81526004016105dc9061401e565b5f805b60028110156120c55761208d816001613fe4565b612098906008613e70565b61ffff168682815181106120ae576120ae613ff7565b016020015160f81c901b9190911790600101612079565b5061ffff8116156120e85760405162461bcd60e51b81526004016105dc90614067565b5f805b6004811015612143576120ff816003613fe4565b61210a906008613e70565b63ffffffff168761211c83600261400b565b8151811061212c5761212c613ff7565b016020015160f81c901b91909117906001016120eb565b5063ffffffff811660031461216a5760405162461bcd60e51b81526004016105dc906140aa565b5f805b60208110156121bf5761218181601f613fe4565b61218c906008613e70565b8861219883600661400b565b815181106121a8576121a8613ff7565b016020015160f81c901b919091179060010161216d565b505f805b600881101561221e576121d7816007613fe4565b6121e2906008613e70565b6001600160401b0316896121f783602661400b565b8151811061220757612207613ff7565b016020015160f81c901b91909117906001016121c3565b505f805b600881101561227d57612236816007613fe4565b612241906008613e70565b6001600160401b03168a61225683602e61400b565b8151811061226657612266613ff7565b016020015160f81c901b9190911790600101612222565b5091989097509095509350505050565b5f8181527f4317713f7ecbdddd4bc99e95d903adedaa883b2e7c2551610bd13e2c7e473d046020526040812080545f805160206141b88339815191529291906122d590613b8d565b9050118015612307575060015f83815260038301602052604090205460ff16600481111561230557612305613b3e565b145b611ccc5760405162461bcd60e51b815260206004820152603860248201525f805160206141d883398151915260448201527f726567697374726174696f6e206e6f742070656e64696e67000000000000000060648201526084016105dc565b5f8181525f8051602061423883398151915260205260408082208151610100810190925280545f805160206141f883398151915293929190829060ff1660058111156123b4576123b4613b3e565b60058111156123c5576123c5613b3e565b8152600182015460208201526002808301546001600160a01b03811660408401526001600160401b03600160a01b909104811660608401526003909301548084166080840152600160401b8104841660a0840152600160801b8104841660c0840152600160c01b900490921660e0909101529091508151600581111561244d5761244d613b3e565b146124a95760405162461bcd60e51b815260206004820152602660248201527f56616c696461746f724d616e616765723a2076616c696461746f72206e6f742060448201526561637469766560d01b60648201526084016105dc565b60408101516001600160a01b0316336001600160a01b0316146125235760405162461bcd60e51b815260206004820152602c60248201527f56616c696461746f724d616e616765723a2073656e646572206e6f742076616c60448201526b34b230ba37b91037bbb732b960a11b60648201526084016105dc565b6125308160a0015161323b565b60038152426001600160401b031660e08201525f83815260078301602052604090208151815483929190829060ff1916600183600581111561257457612574613b3e565b021790555060208201516001820155604082015160028201805460608501516001600160401b03908116600160a01b026001600160e01b03199092166001600160a01b039094169390931717905560808301516003909201805460a085015160c086015160e0909601518416600160c01b026001600160c01b03968516600160801b02969096166001600160801b03918516600160401b026001600160801b031990931695909416949094171792909216179190911790555f6126408461263a81611813565b5f6119e0565b5f858152600685016020526040902090915061265c8282613c0a565b5060405163ee5b48eb60e01b81525f906005600160991b019063ee5b48eb90612689908590600401613ceb565b6020604051808303815f875af11580156126a5573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906126c99190613d1d565b60a0840151604080516001600160401b039092168252426020830152919250829187917f13d58394cf269d48bcf927959a29a5ffee7c9924dafff8927ecdf3c48ffa7c67910160405180910390a35050505050565b5f6127276133dc565b5f61273183610ac8565b90505f805160206141b88339815191525f61274b87611887565b905060028151600581111561276257612762613b3e565b146127c15760405162461bcd60e51b815260206004820152602960248201527f506f5356616c696461746f724d616e616765723a2076616c696461746f72206e6044820152686f742061637469766560b81b60648201526084016105dc565b5f838260a001516127d291906140f1565b90506127de8882611998565b5f6127e889611813565b90505f8989836040516020016128309392919092835260609190911b6bffffffffffffffffffffffff1916602083015260c01b6001600160c01b0319166034820152603c0190565b6040516020818303038152906040528051906020012090506128518661323b565b5f61285d8b84866119e0565b5f83815260048801602052604090209091506128798282613c0a565b5060405163ee5b48eb60e01b81525f906005600160991b019063ee5b48eb906128a6908590600401613ceb565b6020604051808303815f875af11580156128c2573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906128e69190613d1d565b60408051610100810190915290915080600181526020018c6001600160a01b031681526020018d8152602001896001600160401b031681526020015f6001600160401b031681526020015f6001600160401b03168152602001856001600160401b031681526020015f6001600160401b0316815250876003015f8581526020019081526020015f205f820151815f015f6101000a81548160ff0219169083600481111561299557612995613b3e565b02179055506020828101518254610100600160a81b0319166101006001600160a01b039283160217835560408085015160018501556060808601516002860180546080808a015160a08b015160c08c01516001600160401b039687166001600160801b031990951694909417600160401b92871692909202919091176001600160801b0316600160801b918616919091026001600160c01b031617600160c01b928516929092029190911790915560e0909701516003909601805467ffffffffffffffff19169682169690961790955581518a861681528b861694810194909452938d1690830152918101849052908d16918e9186917fb0024b263bc3a0b728a6edea50a69efa841189f8d32ee8af9d1c2b1a1a223426910160405180910390a45090965050505050505061155c60015f8051602061421883398151915255565b5f5f805160206141b88339815191528282612af082610ac8565b83549091506001600160401b03821610801590612b1a57508260010154816001600160401b031611155b612b785760405162461bcd60e51b815260206004820152602960248201527f506f5356616c696461746f724d616e616765723a20696e76616c6964207374616044820152681ad948185b5bdd5b9d60ba1b60648201526084016105dc565b949350505050565b5f612b896133dc565b5f805160206141f8833981519152426001600160401b038516118015612bc357506001600160401b038416612bc1426202a30061400b565b115b612c255760405162461bcd60e51b815260206004820152602d60248201527f56616c696461746f724d616e616765723a20696e76616c69642072656769737460448201526c726174696f6e2065787069727960981b60648201526084016105dc565b85612c7c5760405162461bcd60e51b815260206004820152602160248201527f56616c696461746f724d616e616765723a20696e76616c6964206e6f646520496044820152601160fa1b60648201526084016105dc565b5f86815260088201602052604090205415612cea5760405162461bcd60e51b815260206004820152602860248201527f56616c696461746f724d616e616765723a206e6f646520494420616c72656164604482015267792061637469766560c01b60648201526084016105dc565b8251603014612d515760405162461bcd60e51b815260206004820152602d60248201527f56616c696461746f724d616e616765723a20696e76616c696420626c7350756260448201526c0d8d2c696caf240d8cadccee8d609b1b60648201526084016105dc565b612d5a8561323b565b5f80612da16040518060a00160405280856001015481526020018a8152602001896001600160401b03168152602001886001600160401b0316815260200187815250613426565b5f82815260058601602052604090209193509150612dbf8282613c0a565b5060405163ee5b48eb60e01b81525f906005600160991b019063ee5b48eb90612dec908590600401613ceb565b6020604051808303815f875af1158015612e08573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612e2c9190613d1d565b604080516101008101825260018152602081018c90529192508101336001600160a01b031681526001600160401b038a1660208083018290525f604080850182905260608501939093526080840181905260a0909301839052868352600788019052902081518154829060ff19166001836005811115612eae57612eae613b3e565b021790555060208201516001820155604082015160028201805460608501516001600160401b03908116600160a01b026001600160e01b03199092166001600160a01b039094169390931717905560808301516003909201805460a085015160c086015160e0909601518416600160c01b026001600160c01b03968516600160801b02969096166001600160801b03918516600160401b026001600160801b03199093169590941694909417179290921617919091179055612f6f83611813565b50604080516001600160401b03808b1682528916602082015282918b9186917f79b81620b81daf2c08cd5bb3dbb79e75d2d7a87f52171fde5aadc8c47823026e910160405180910390a4509092505050612b7860015f8051602061421883398151915255565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054600160401b900460ff1661301e57604051631afcd79f60e31b815260040160405180910390fd5b565b613028612fd5565b613031816137cb565b6115746060820135608083013561304e60c0850160a08601613a01565b61305e60e0860160c08701614111565b6137ec565b5f808251602e146130865760405162461bcd60e51b81526004016105dc9061401e565b5f805b60028110156130d55761309d816001613fe4565b6130a8906008613e70565b61ffff168582815181106130be576130be613ff7565b016020015160f81c901b9190911790600101613089565b5061ffff8116156130f85760405162461bcd60e51b81526004016105dc90614067565b5f805b60048110156131535761310f816003613fe4565b61311a906008613e70565b63ffffffff168661312c83600261400b565b8151811061313c5761313c613ff7565b016020015160f81c901b91909117906001016130fb565b5063ffffffff811660041461317a5760405162461bcd60e51b81526004016105dc906140aa565b5f805b60208110156131cf5761319181601f613fe4565b61319c906008613e70565b876131a883600661400b565b815181106131b8576131b8613ff7565b016020015160f81c901b919091179060010161317d565b505f805b600881101561322e576131e7816007613fe4565b6131f2906008613e70565b6001600160401b03168861320783602661400b565b8151811061321757613217613ff7565b016020015160f81c901b91909117906001016131d3565b5090969095509350505050565b7fe92546d698950ddd38910d2e15ed1d923cd0a7b3dde9e2a6a3f380565559cb02545f805160206141f88339815191529060ff165f03613279575050565b60408051606081018252600383015480825260048401546001600160401b038082166020850152600160401b9091041692820192909252904290610e10906132c19083613fe4565b106132dd576001600160401b03841660408301528082526132fc565b83826040018181516132ef91906140f1565b6001600160401b03169052505b5f826020015183604001516064613313919061412c565b61331d9190614157565b600285015490915060ff90811690821611156133985760405162461bcd60e51b815260206004820152603460248201527f56616c696461746f724d616e616765723a206d6178696d756d20686f75726c796044820152730818da1d5c9b881c985d1948195e18d95959195960621b60648201526084016105dc565b5050805160038301556020810151600490920180546040909201516001600160401b03908116600160401b026001600160801b031990931693169290921717905550565b5f8051602061421883398151915280546001190161340d57604051633ee5aeb560e01b815260040160405180910390fd5b60029055565b60015f8051602061421883398151915255565b5f60608260800151516030146134905760405162461bcd60e51b815260206004820152602960248201527f5374616b696e674d657373616765733a20696e76616c6964207369676e6174756044820152680e4ca40d8cadccee8d60bb1b60648201526084016105dc565b60408051608680825260c082019092525f916020820181803683370190505090505f5b6002811015613507576134c7816001613fe4565b6134d2906008613e70565b5081515f908390839081106134e9576134e9613ff7565b60200101906001600160f81b03191690815f1a9053506001016134b3565b505f5b60048110156135655761351e816003613fe4565b613529906008613e70565b505f8261353783600261400b565b8151811061354757613547613ff7565b60200101906001600160f81b03191690815f1a90535060010161350a565b505f5b60208110156135c2578451816020811061358457613584613ff7565b1a60f81b8261359483600661400b565b815181106135a4576135a4613ff7565b60200101906001600160f81b03191690815f1a905350600101613568565b505f5b602081101561362257846020015181602081106135e4576135e4613ff7565b1a60f81b826135f483602661400b565b8151811061360457613604613ff7565b60200101906001600160f81b03191690815f1a9053506001016135c5565b505f5b600881101561369657613639816007613fe4565b613644906008613e70565b60ff1685604001516001600160401b0316901c60f81b82826046613668919061400b565b8151811061367857613678613ff7565b60200101906001600160f81b03191690815f1a905350600101613625565b505f5b603081101561370157846080015181815181106136b8576136b8613ff7565b01602001516001600160f81b031916826136d383604e61400b565b815181106136e3576136e3613ff7565b60200101906001600160f81b03191690815f1a905350600101613699565b505f5b600881101561377357613718816007613fe4565b613723906008613e70565b60608601516001600160401b0390811691161c60f81b8261374583607e61400b565b8151811061375557613755613ff7565b60200101906001600160f81b03191690815f1a905350600101613704565b50600281604051613784919061417c565b602060405180830381855afa15801561379f573d5f803e3d5ffd5b5050506040513d601f19601f820116820180604052508101906137c29190613d1d565b94909350915050565b6137d3612fd5565b6137db613847565b6137e3613857565b6115748161385f565b6137f4612fd5565b5f5f805160206141b8833981519152948555506001840192909255600290920180546001600160a01b03909216600160401b026001600160e01b03199092166001600160401b0390931692909217179055565b61384f612fd5565b61301e6138cb565b61301e612fd5565b613867612fd5565b80355f805160206141f883398151915290815560208201357fe92546d698950ddd38910d2e15ed1d923cd0a7b3dde9e2a6a3f380565559cb01556138b16060830160408401614197565b600291909101805460ff191660ff90921691909117905550565b613413612fd5565b5080546138df90613b8d565b5f825580601f106138ee575050565b601f0160209004905f5260205f209081019061157491905b80821115613919575f8155600101613906565b5090565b5f60e0828403121561392d575f80fd5b50919050565b8015158114611574575f80fd5b803563ffffffff81168114613953575f80fd5b919050565b5f805f6060848603121561396a575f80fd5b83359250602084013561397c81613933565b915061398a60408501613940565b90509250925092565b5f602082840312156139a3575f80fd5b5035919050565b5f602082840312156139ba575f80fd5b61155c82613940565b5f80604083850312156139d4575f80fd5b6139dd83613940565b946020939093013593505050565b80356001600160401b0381168114613953575f80fd5b5f60208284031215613a11575f80fd5b61155c826139eb565b634e487b7160e01b5f52604160045260245ffd5b604051606081016001600160401b0381118282101715613a5057613a50613a1a565b60405290565b604051601f8201601f191681016001600160401b0381118282101715613a7e57613a7e613a1a565b604052919050565b5f6001600160401b03821115613a9e57613a9e613a1a565b50601f01601f191660200190565b5f805f60608486031215613abe575f80fd5b83359250613ace602085016139eb565b915060408401356001600160401b03811115613ae8575f80fd5b8401601f81018613613af8575f80fd5b8035613b0b613b0682613a86565b613a56565b818152876020838501011115613b1f575f80fd5b816020840160208301375f602083830101528093505050509250925092565b634e487b7160e01b5f52602160045260245ffd5b634e487b7160e01b5f52601160045260245ffd5b6001600160401b03828116828216039080821115613b8657613b86613b52565b5092915050565b600181811c90821680613ba157607f821691505b60208210810361392d57634e487b7160e01b5f52602260045260245ffd5b601f821115610a5657805f5260205f20601f840160051c81016020851015613be45750805b601f840160051c820191505b81811015613c03575f8155600101613bf0565b5050505050565b81516001600160401b03811115613c2357613c23613a1a565b613c3781613c318454613b8d565b84613bbf565b602080601f831160018114613c6a575f8415613c535750858301515b5f19600386901b1c1916600185901b178555613cc1565b5f85815260208120601f198616915b82811015613c9857888601518255948401946001909101908401613c79565b5085821015613cb557878501515f19600388901b60f8161c191681555b505060018460011b0185555b505050505050565b5f5b83811015613ce3578181015183820152602001613ccb565b50505f910152565b602081525f8251806020840152613d09816040850160208701613cc9565b601f01601f19169190910160400192915050565b5f60208284031215613d2d575f80fd5b5051919050565b5f60208083525f8454613d4681613b8d565b806020870152604060018084165f8114613d675760018114613d8357613db0565b60ff19851660408a0152604084151560051b8a01019550613db0565b895f5260205f205f5b85811015613da75781548b8201860152908301908801613d8c565b8a016040019650505b509398975050505050505050565b634e487b7160e01b5f52601260045260245ffd5b5f82613de057613de0613dbe565b500490565b60208082526022908201527f506f5356616c696461746f724d616e616765723a20696e76616c6964206e6f6e604082015261636560f01b606082015260800190565b60208082526029908201527f506f5356616c696461746f724d616e616765723a206e6f6e636520646f6573206040820152680dcdee840dac2e8c6d60bb1b606082015260800190565b8082028115828204841417610ad857610ad8613b52565b60208082526027908201527f56616c696461746f724d616e616765723a20696e76616c69642076616c6964616040820152661d1a5bdb88125160ca1b606082015260800190565b6001600160a01b0381168114611574575f80fd5b805161395381613933565b5f8060408385031215613efe575f80fd5b82516001600160401b0380821115613f14575f80fd5b9084019060608287031215613f27575f80fd5b613f2f613a2e565b82518152602080840151613f4281613ece565b82820152604084015183811115613f57575f80fd5b80850194505087601f850112613f6b575f80fd5b83519250613f7b613b0684613a86565b8381528882858701011115613f8e575f80fd5b613f9d84838301848801613cc9565b80604084015250819550613fb2818801613ee2565b9450505050509250929050565b5f6001600160401b03808316818103613fda57613fda613b52565b6001019392505050565b81810381811115610ad857610ad8613b52565b634e487b7160e01b5f52603260045260245ffd5b80820180821115610ad857610ad8613b52565b60208082526029908201527f56616c696461746f724d657373616765733a20696e76616c6964206d657373616040820152680ceca40d8cadccee8d60bb1b606082015260800190565b60208082526023908201527f56616c696461746f724d657373616765733a20696e76616c696420636f64656360408201526208125160ea1b606082015260800190565b60208082526027908201527f56616c696461746f724d657373616765733a20696e76616c6964206d657373616040820152666765207479706560c81b606082015260800190565b6001600160401b03818116838216019080821115613b8657613b86613b52565b5f60208284031215614121575f80fd5b813561155c81613ece565b6001600160401b0381811683821602808216919082811461414f5761414f613b52565b505092915050565b5f6001600160401b038084168061417057614170613dbe565b92169190910492915050565b5f825161418d818460208701613cc9565b9190910192915050565b5f602082840312156141a7575f80fd5b813560ff8116811461155c575f80fdfe4317713f7ecbdddd4bc99e95d903adedaa883b2e7c2551610bd13e2c7e473d00506f5356616c696461746f724d616e616765723a2064656c65676174696f6e20e92546d698950ddd38910d2e15ed1d923cd0a7b3dde9e2a6a3f380565559cb009b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00e92546d698950ddd38910d2e15ed1d923cd0a7b3dde9e2a6a3f380565559cb07a164736f6c6343000819000a", + ABI: "[{\"type\":\"constructor\",\"inputs\":[{\"name\":\"init\",\"type\":\"uint8\",\"internalType\":\"enumICMInitializable\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"WARP_MESSENGER\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"contractIWarpMessenger\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"activeValidators\",\"inputs\":[{\"name\":\"nodeID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"completeDelegatorRegistration\",\"inputs\":[{\"name\":\"messageIndex\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"delegationID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"completeEndDelegation\",\"inputs\":[{\"name\":\"messageIndex\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"delegationID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"completeEndValidation\",\"inputs\":[{\"name\":\"messageIndex\",\"type\":\"uint32\",\"internalType\":\"uint32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"completeValidatorRegistration\",\"inputs\":[{\"name\":\"messageIndex\",\"type\":\"uint32\",\"internalType\":\"uint32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"getWeight\",\"inputs\":[{\"name\":\"validationID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"initialize\",\"inputs\":[{\"name\":\"settings\",\"type\":\"tuple\",\"internalType\":\"structPoSValidatorManagerSettings\",\"components\":[{\"name\":\"baseSettings\",\"type\":\"tuple\",\"internalType\":\"structValidatorManagerSettings\",\"components\":[{\"name\":\"pChainBlockchainID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"subnetID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"maximumHourlyChurn\",\"type\":\"uint8\",\"internalType\":\"uint8\"}]},{\"name\":\"minimumStakeAmount\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"maximumStakeAmount\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"minimumStakeDuration\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"rewardCalculator\",\"type\":\"address\",\"internalType\":\"contractIRewardCalculator\"}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"initializeDelegatorRegistration\",\"inputs\":[{\"name\":\"validationID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"initializeEndDelegation\",\"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\":\"initializeEndValidation\",\"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\":\"initializeValidatorRegistration\",\"inputs\":[{\"name\":\"nodeID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"registrationExpiry\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"blsPublicKey\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"resendDelegatorRegistration\",\"inputs\":[{\"name\":\"delegationID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"resendEndDelegation\",\"inputs\":[{\"name\":\"delegationID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"resendEndValidatorMessage\",\"inputs\":[{\"name\":\"validationID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"resendRegisterValidatorMessage\",\"inputs\":[{\"name\":\"validationID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"valueToWeight\",\"inputs\":[{\"name\":\"value\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"stateMutability\":\"pure\"},{\"type\":\"function\",\"name\":\"weightToValue\",\"inputs\":[{\"name\":\"weight\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"pure\"},{\"type\":\"event\",\"name\":\"DelegationEnded\",\"inputs\":[{\"name\":\"delegationID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"validationID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"nonce\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"DelegatorAdded\",\"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\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"DelegatorRegistered\",\"inputs\":[{\"name\":\"delegationID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"validationID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"nonce\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"startTime\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"DelegatorRemovalInitialized\",\"inputs\":[{\"name\":\"delegationID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"validationID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"nonce\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"validatorWeight\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"},{\"name\":\"endTime\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"},{\"name\":\"setWeightMessageID\",\"type\":\"bytes32\",\"indexed\":false,\"internalType\":\"bytes32\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Initialized\",\"inputs\":[{\"name\":\"version\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ValidationPeriodCreated\",\"inputs\":[{\"name\":\"validationID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"nodeID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"registerValidationMessageID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"weight\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"},{\"name\":\"registrationExpiry\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ValidationPeriodEnded\",\"inputs\":[{\"name\":\"validationID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"status\",\"type\":\"uint8\",\"indexed\":true,\"internalType\":\"enumValidatorStatus\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ValidationPeriodRegistered\",\"inputs\":[{\"name\":\"validationID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"weight\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"},{\"name\":\"timestamp\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ValidatorRemovalInitialized\",\"inputs\":[{\"name\":\"validationID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"setWeightMessageID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"weight\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"},{\"name\":\"endTime\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"error\",\"name\":\"IncorrectInputLength\",\"inputs\":[{\"name\":\"expected\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"actual\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"InvalidInitialization\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"NotInitializing\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"ReentrancyGuardReentrantCall\",\"inputs\":[]}]", + Bin: "0x608060405234801561000f575f80fd5b50604051613c8d380380613c8d83398101604081905261002e91610107565b60018160018111156100425761004261012c565b0361004f5761004f610055565b50610140565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000900460ff16156100a55760405163f92ee8a960e01b815260040160405180910390fd5b80546001600160401b03908116146101045780546001600160401b0319166001600160401b0390811782556040519081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50565b5f60208284031215610117575f80fd5b815160028110610125575f80fd5b9392505050565b634e487b7160e01b5f52602160045260245ffd5b613b408061014d5f395ff3fe608060405260043610610104575f3560e01c806366435abf11610092578063a3a65e4811610062578063a3a65e48146102f3578063b771b3bc14610312578063bee0a03f14610344578063c599e24f14610363578063f40797d714610376575f80fd5b806366435abf146102775780636d0e43fa1461029657806376f78621146102b557806398f3e2b4146102d4575f80fd5b8063162f1f61116100d8578063162f1f61146101c45780632e2194d8146101e3578063467ef06f1461021a5780635297fae6146102395780636206585614610258575f80fd5b8062e41792146101085780630118acc4146101295780630322ed98146101485780630cdd098514610167575b5f80fd5b348015610113575f80fd5b50610127610122366004613197565b610389565b005b348015610134575f80fd5b506101276101433660046131d2565b61046b565b348015610153575f80fd5b5061012761016236600461320d565b6108ff565b348015610172575f80fd5b506101b161018136600461320d565b5f9081527fe92546d698950ddd38910d2e15ed1d923cd0a7b3dde9e2a6a3f380565559cb08602052604090205490565b6040519081526020015b60405180910390f35b3480156101cf575f80fd5b506101276101de36600461320d565b610a5b565b3480156101ee575f80fd5b506102026101fd36600461320d565b610ac8565b6040516001600160401b0390911681526020016101bb565b348015610225575f80fd5b50610127610234366004613224565b610ade565b348015610244575f80fd5b5061012761025336600461323d565b610e61565b348015610263575f80fd5b506101b161027236600461327b565b611052565b348015610282575f80fd5b5061020261029136600461320d565b61106b565b3480156102a1575f80fd5b506101276102b036600461320d565b61107f565b3480156102c0575f80fd5b506101276102cf3660046131d2565b6110ec565b3480156102df575f80fd5b506101276102ee36600461323d565b611107565b3480156102fe575f80fd5b5061012761030d366004613224565b6112a7565b34801561031d575f80fd5b5061032c6005600160991b0181565b6040516001600160a01b0390911681526020016101bb565b34801561034f575f80fd5b5061012761035e36600461320d565b611464565b6101b161037136600461320d565b611533565b6101b1610384366004613326565b61153f565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805460029190600160401b900460ff16806103d2575080546001600160401b03808416911610155b156103f05760405163f92ee8a960e01b815260040160405180910390fd5b805468ffffffffffffffffff19166001600160401b03831617600160401b17815561041a83611563565b805468ff0000000000000000191681556040516001600160401b03831681527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a1505050565b5f8381527f4317713f7ecbdddd4bc99e95d903adedaa883b2e7c2551610bd13e2c7e473d0360205260408120600101545f80516020613a948339815191529184156104bd576104ba8285611577565b90505b5f868152600384016020526040808220815161010081019092528054829060ff1660048111156104ef576104ef6133b8565b6004811115610500576105006133b8565b8152815461010090046001600160a01b031660208201526001820154604082015260028201546001600160401b038082166060840152600160401b820481166080840152600160801b8204811660a0840152600160c01b909104811660c083015260039092015490911660e0909101529050336001600160a01b031681602001516001600160a01b0316146105e55760405162461bcd60e51b815260206004820152603360248201525f80516020613ab48339815191526044820152723737ba1037bbb732b210313c9039b2b73232b960691b60648201526084015b60405180910390fd5b6002815160048111156105fa576105fa6133b8565b146106475760405162461bcd60e51b815260206004820152602a60248201525f80516020613ab48339815191526044820152696e6f742061637469766560b01b60648201526084016105dc565b5f61065184611813565b60038084526001600160401b0342811660a0860152821660e08501525f8a815290870160205260409020835181549293508492829060ff1916600183600481111561069e5761069e6133b8565b021790555060208201518154610100600160a81b0319166101006001600160a01b0390921691909102178155604082015160018201556060820151600282018054608085015160a086015160c08701516001600160401b039586166001600160801b031990941693909317600160401b92861692909202919091176001600160801b0316600160801b918516919091026001600160c01b031617600160c01b9184169190910217905560e0909201516003909101805467ffffffffffffffff1916919092161790555f61077085611887565b905082606001516001600160401b03168160a001516001600160401b0316116107e75760405162461bcd60e51b815260206004820152602360248201527f506f5356616c696461746f724d616e616765723a20496e76616c69642077656960448201526219da1d60ea1b60648201526084016105dc565b5f83606001518260a001516107fc91906133e0565b90506108088682611998565b5f6108148785846119e0565b5f8c815260058a01602052604090209091506108308282613484565b5060405163ee5b48eb60e01b81525f906005600160991b019063ee5b48eb9061085d908590600401613565565b6020604051808303815f875af1158015610879573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061089d9190613597565b604080516001600160401b03868116825242602083015291810183905291925086169089908e907f5318ab4d7cdf77056db2db5b539a08fe7d1a63d6885ecee8236a0dbda2843b4e9060600160405180910390a4505050505050505050505050565b5f8181527fe92546d698950ddd38910d2e15ed1d923cd0a7b3dde9e2a6a3f380565559cb066020526040812080545f80516020613ad483398151915292919061094790613407565b9050118015610979575060035f83815260078301602052604090205460ff166005811115610977576109776133b8565b145b6109dd5760405162461bcd60e51b815260206004820152602f60248201527f56616c696461746f724d616e616765723a2056616c696461746f72206e6f742060448201526e1c195b991a5b99c81c995b5bdd985b608a1b60648201526084016105dc565b5f82815260068201602052604090819020905163ee5b48eb60e01b81526005600160991b019163ee5b48eb91610a1691906004016135ae565b6020604051808303815f875af1158015610a32573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a569190613597565b505050565b610a6481611a2f565b5f8181527f4317713f7ecbdddd4bc99e95d903adedaa883b2e7c2551610bd13e2c7e473d05602052604090819020905163ee5b48eb60e01b81525f80516020613a94833981519152916005600160991b019163ee5b48eb91610a16916004016135ae565b5f610ad864e8d4a510008361364c565b92915050565b5f80516020613ad48339815191525f610af683611b02565b90505f80610b078360400151611ce3565b915091508015610b6c5760405162461bcd60e51b815260206004820152602a60248201527f56616c696461746f724d616e616765723a20726567697374726174696f6e20736044820152691d1a5b1b081d985b1a5960b21b60648201526084016105dc565b5f828152600785016020526040808220815161010081019092528054829060ff166005811115610b9e57610b9e6133b8565b6005811115610baf57610baf6133b8565b81526001820154602082015260028201546001600160a01b03811660408301526001600160401b03600160a01b909104811660608301526003928301548082166080840152600160401b8104821660a0840152600160801b8104821660c0840152600160c01b90041660e0909101529091505f9082516005811115610c3657610c366133b8565b1480610c545750600182516005811115610c5257610c526133b8565b145b610cb35760405162461bcd60e51b815260206004820152602a60248201527f56616c696461746f724d616e616765723a20696e76616c69642076616c696461604482015269746f722073746174757360b01b60648201526084016105dc565b600382516005811115610cc857610cc86133b8565b03610cef57505f8381526006860160205260408120600491610cea919061314d565b610cf3565b5060055b6020808301515f90815260088801909152604081205581816005811115610d1c57610d1c6133b8565b90816005811115610d2f57610d2f6133b8565b9052505f84815260078701602052604090208251815484929190829060ff19166001836005811115610d6357610d636133b8565b021790555060208201516001820155604082015160028201805460608501516001600160401b03908116600160a01b026001600160e01b03199092166001600160a01b039094169390931717905560808301516003909201805460a085015160c086015160e0909601518416600160c01b026001600160c01b03968516600160801b02969096166001600160801b03918516600160401b026001600160801b0319909316959094169490941717929092161791909117905581516005811115610e2e57610e2e6133b8565b60405185907f1c08e59656f1a18dc2da76826cdc52805c43e897a17c50faefb8ab3c1526cc16905f90a350505050505050565b5f80516020613a948339815191525f610e7984611b02565b90505f80610e8a8360400151611d76565b5091509150610e9885611e0f565b5f8581526004850160205260408120610eb09161314d565b5f610eba83611887565b9050816001600160401b031681608001516001600160401b03161015610ef25760405162461bcd60e51b81526004016105dc9061365f565b5f8681526003860160205260409020600201546001600160401b03808416600160c01b909204161115610f375760405162461bcd60e51b81526004016105dc906136a1565b60015f87815260038701602052604090205460ff166004811115610f5d57610f5d6133b8565b14610fc65760405162461bcd60e51b815260206004820152603360248201527f506f5356616c696461746f724d616e616765723a2064656c65676174696f6e4960448201527211081b9bdd081c195b991a5b99c81859191959606a1b60648201526084016105dc565b5f868152600386016020908152604091829020805460ff1916600290811782550180546001600160401b0342818116600160401b0267ffffffffffffffff60401b19909316929092179092559251928352841691859189917f245fc69b36e168426e0306fc8d8300661b9af297c7958820dbf804f9f63e7064910160405180910390a450505050505050565b5f610ad86001600160401b03831664e8d4a510006136ea565b5f61107582611887565b60a0015192915050565b61108881611e0f565b5f8181527f4317713f7ecbdddd4bc99e95d903adedaa883b2e7c2551610bd13e2c7e473d04602052604090819020905163ee5b48eb60e01b81525f80516020613a94833981519152916005600160991b019163ee5b48eb91610a16916004016135ae565b81156110fe576110fc8382611577565b505b610a5683611ee8565b5f80516020613a948339815191525f61111f84611b02565b90505f806111308360400151611d76565b509150915061113e85611a2f565b5f85815260058501602052604081206111569161314d565b5f61116083611887565b9050816001600160401b031681608001516001600160401b031610156111985760405162461bcd60e51b81526004016105dc9061365f565b5f8681526003808701602052604090912001546001600160401b03808416911611156111d65760405162461bcd60e51b81526004016105dc906136a1565b60035f87815260038701602052604090205460ff1660048111156111fc576111fc6133b8565b146112505760405162461bcd60e51b815260206004820152603160248201525f80516020613ab48339815191526044820152701b9bdd081c195b991a5b99c81859191959607a1b60648201526084016105dc565b5f868152600386016020526040808220805460ff19166004179055516001600160401b03841691859189917f52e9b1eaef84d46cda83ccb9d427267bc4d04f756b4a32c8302722b79e5c65ab91a450505050505050565b5f80516020613ad48339815191525f6112bf83611b02565b90505f806112d08360400151611ce3565b91509150806113325760405162461bcd60e51b815260206004820152602860248201527f56616c696461746f724d616e616765723a20526567697374726174696f6e206e6044820152671bdd081d985b1a5960c21b60648201526084016105dc565b5f8281526005850160205260408120805461134c90613407565b905011801561137e575060015f83815260078601602052604090205460ff16600581111561137c5761137c6133b8565b145b61139a5760405162461bcd60e51b81526004016105dc90613701565b5f82815260058501602052604081206113b29161314d565b5f8281526007850160208181526040808420805460ff191660021781556003810180546001600160401b0342818116600160801b0267ffffffffffffffff60801b19909316929092178355600190930154875260088b0185528387208990559588905293835292548151600160401b90910490931683529082019290925283917ff8fd1c90fb9cfa2ca2358fdf5806b086ad43315d92b221c929efc7f105ce7568910160405180910390a25050505050565b5f8181527fe92546d698950ddd38910d2e15ed1d923cd0a7b3dde9e2a6a3f380565559cb056020526040812080545f80516020613ad48339815191529291906114ac90613407565b90501180156114de575060015f83815260078301602052604090205460ff1660058111156114dc576114dc6133b8565b145b6114fa5760405162461bcd60e51b81526004016105dc90613701565b5f82815260058201602052604090819020905163ee5b48eb60e01b81526005600160991b019163ee5b48eb91610a1691906004016135ae565b5f610ad88233346122a0565b5f8061154a34612658565b905061155885828686612702565b9150505b9392505050565b61156b612b57565b61157481612ba2565b50565b6040516306f8253560e41b815263ffffffff821660048201525f90819081906005600160991b0190636f825350906024015f60405180830381865afa1580156115c2573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526115e99190810190613767565b915091508061164c5760405162461bcd60e51b815260206004820152602960248201527f506f5356616c696461746f724d616e616765723a20696e76616c69642077617260448201526870206d65737361676560b81b60648201526084016105dc565b6005600160991b016001600160a01b0316634213cf786040518163ffffffff1660e01b8152600401602060405180830381865afa15801561168f573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906116b39190613597565b8251146117175760405162461bcd60e51b815260206004820152602c60248201527f506f5356616c696461746f724d616e616765723a20696e76616c696420736f7560448201526b1c98d94818da185a5b88125160a21b60648201526084016105dc565b60208201516001600160a01b03161561178d5760405162461bcd60e51b815260206004820152603260248201527f506f5356616c696461746f724d616e616765723a20696e76616c6964206f726960448201527167696e2073656e646572206164647265737360701b60648201526084016105dc565b5f8061179c8460400151612be5565b915091508187146118095760405162461bcd60e51b815260206004820152603160248201527f506f5356616c696461746f724d616e616765723a20696e76616c6964207570746044820152701a5b59481d985b1a59185d1a5bdb881251607a1b60648201526084016105dc565b9695505050505050565b5f8181525f80516020613b148339815191526020526040812060030180545f80516020613ad4833981519152916001600160401b039091169081908461185883613839565b91906101000a8154816001600160401b0302191690836001600160401b03160217905550508092505050919050565b6040805161010080820183525f8083526020808401829052838501829052606084018290526080840182905260a0840182905260c0840182905260e084018290528582525f80516020613b1483398151915290528390208351918201909352825491925f80516020613ad483398151915292829060ff16600581111561190f5761190f6133b8565b6005811115611920576119206133b8565b81526001820154602082015260028201546001600160a01b03811660408301526001600160401b03600160a01b909104811660608301526003909201548083166080830152600160401b8104831660a0830152600160801b8104831660c0830152600160c01b900490911660e0909101529392505050565b5f9182525f80516020613b14833981519152602052604090912060030180546001600160401b03909216600160401b0267ffffffffffffffff60401b19909216919091179055565b604080515f6020820152600160e01b602282015260268101949094526001600160c01b031960c093841b811660468601529190921b16604e830152805180830360360181526056909201905290565b5f8181527f4317713f7ecbdddd4bc99e95d903adedaa883b2e7c2551610bd13e2c7e473d056020526040812080545f80516020613a94833981519152929190611a7790613407565b9050118015611aa9575060035f83815260038301602052604090205460ff166004811115611aa757611aa76133b8565b145b611afe5760405162461bcd60e51b815260206004820152603360248201525f80516020613ab483398151915260448201527272656d6f76616c206e6f742070656e64696e6760681b60648201526084016105dc565b5050565b60408051606080820183525f8083526020830181905292820152905f80516020613ad48339815191526040516306f8253560e41b815263ffffffff851660048201529091505f9081906005600160991b0190636f825350906024015f60405180830381865afa158015611b77573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052611b9e9190810190613767565b9150915080611c055760405162461bcd60e51b815260206004820152602d60248201527f56616c696461746f724d616e616765723a20496e76696e76616c6964616c696460448201526c2077617270206d65737361676560981b60648201526084016105dc565b8254825114611c685760405162461bcd60e51b815260206004820152602960248201527f56616c696461746f724d616e616765723a20696e76616c696420736f757263656044820152680818da185a5b88125160ba1b60648201526084016105dc565b60208201516001600160a01b031615611cdb5760405162461bcd60e51b815260206004820152602f60248201527f56616c696461746f724d616e616765723a20696e76616c6964206f726967696e60448201526e2073656e646572206164647265737360881b60648201526084016105dc565b509392505050565b5f808251602714611d065760405162461bcd60e51b81526004016105dc9061385e565b5f805f80611d1387612c76565b9296509094509250905060f084901c15611d3f5760405162461bcd60e51b81526004016105dc906138a7565b60e083901c600214611d635760405162461bcd60e51b81526004016105dc906138ea565b909660f89190911c151595509350505050565b5f805f8351603614611d9a5760405162461bcd60e51b81526004016105dc9061385e565b5f805f805f611da889612cc9565b93985091965094509250905060f085901c15611dd65760405162461bcd60e51b81526004016105dc906138a7565b60e084901c600314611dfa5760405162461bcd60e51b81526004016105dc906138ea565b919860c091821c985091901c95509350505050565b5f8181527f4317713f7ecbdddd4bc99e95d903adedaa883b2e7c2551610bd13e2c7e473d046020526040812080545f80516020613a94833981519152929190611e5790613407565b9050118015611e89575060015f83815260038301602052604090205460ff166004811115611e8757611e876133b8565b145b611afe5760405162461bcd60e51b815260206004820152603860248201525f80516020613ab483398151915260448201527f726567697374726174696f6e206e6f742070656e64696e67000000000000000060648201526084016105dc565b5f8181525f80516020613b1483398151915260205260408082208151610100810190925280545f80516020613ad483398151915293929190829060ff166005811115611f3657611f366133b8565b6005811115611f4757611f476133b8565b8152600182015460208201526002808301546001600160a01b03811660408401526001600160401b03600160a01b909104811660608401526003909301548084166080840152600160401b8104841660a0840152600160801b8104841660c0840152600160c01b900490921660e09091015290915081516005811115611fcf57611fcf6133b8565b1461202b5760405162461bcd60e51b815260206004820152602660248201527f56616c696461746f724d616e616765723a2076616c696461746f72206e6f742060448201526561637469766560d01b60648201526084016105dc565b60408101516001600160a01b0316336001600160a01b0316146120a55760405162461bcd60e51b815260206004820152602c60248201527f56616c696461746f724d616e616765723a2073656e646572206e6f742076616c60448201526b34b230ba37b91037bbb732b960a11b60648201526084016105dc565b6120b28160a00151612d25565b60038152426001600160401b031660e08201525f83815260078301602052604090208151815483929190829060ff191660018360058111156120f6576120f66133b8565b021790555060208201516001820155604082015160028201805460608501516001600160401b03908116600160a01b026001600160e01b03199092166001600160a01b039094169390931717905560808301516003909201805460a085015160c086015160e0909601518416600160c01b026001600160c01b03968516600160801b02969096166001600160801b03918516600160401b026001600160801b031990931695909416949094171792909216179190911790555f6121c2846121bc81611813565b5f6119e0565b5f85815260068501602052604090209091506121de8282613484565b5060405163ee5b48eb60e01b81525f906005600160991b019063ee5b48eb9061220b908590600401613565565b6020604051808303815f875af1158015612227573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061224b9190613597565b60a0840151604080516001600160401b039092168252426020830152919250829187917f13d58394cf269d48bcf927959a29a5ffee7c9924dafff8927ecdf3c48ffa7c67910160405180910390a35050505050565b5f6122a9612ec6565b5f6122b383610ac8565b90505f80516020613a948339815191525f6122cd87611887565b90506002815160058111156122e4576122e46133b8565b146123435760405162461bcd60e51b815260206004820152602960248201527f506f5356616c696461746f724d616e616765723a2076616c696461746f72206e6044820152686f742061637469766560b81b60648201526084016105dc565b5f838260a001516123549190613931565b90506123608882611998565b5f61236a89611813565b90505f8989836040516020016123b29392919092835260609190911b6bffffffffffffffffffffffff1916602083015260c01b6001600160c01b0319166034820152603c0190565b6040516020818303038152906040528051906020012090506123d386612d25565b5f6123df8b84866119e0565b5f83815260048801602052604090209091506123fb8282613484565b5060405163ee5b48eb60e01b81525f906005600160991b019063ee5b48eb90612428908590600401613565565b6020604051808303815f875af1158015612444573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906124689190613597565b60408051610100810190915290915080600181526020018c6001600160a01b031681526020018d8152602001896001600160401b031681526020015f6001600160401b031681526020015f6001600160401b03168152602001856001600160401b031681526020015f6001600160401b0316815250876003015f8581526020019081526020015f205f820151815f015f6101000a81548160ff02191690836004811115612517576125176133b8565b02179055506020828101518254610100600160a81b0319166101006001600160a01b039283160217835560408085015160018501556060808601516002860180546080808a015160a08b015160c08c01516001600160401b039687166001600160801b031990951694909417600160401b92871692909202919091176001600160801b0316600160801b918616919091026001600160c01b031617600160c01b928516929092029190911790915560e0909701516003909601805467ffffffffffffffff19169682169690961790955581518a861681528b861694810194909452938d1690830152918101849052908d16918e9186917fb0024b263bc3a0b728a6edea50a69efa841189f8d32ee8af9d1c2b1a1a223426910160405180910390a45090965050505050505061155c60015f80516020613af483398151915255565b5f5f80516020613a94833981519152828261267282610ac8565b83549091506001600160401b0382161080159061269c57508260010154816001600160401b031611155b6126fa5760405162461bcd60e51b815260206004820152602960248201527f506f5356616c696461746f724d616e616765723a20696e76616c6964207374616044820152681ad948185b5bdd5b9d60ba1b60648201526084016105dc565b949350505050565b5f61270b612ec6565b5f80516020613ad4833981519152426001600160401b03851611801561274557506001600160401b038416612743426202a300613951565b115b6127a75760405162461bcd60e51b815260206004820152602d60248201527f56616c696461746f724d616e616765723a20696e76616c69642072656769737460448201526c726174696f6e2065787069727960981b60648201526084016105dc565b856127fe5760405162461bcd60e51b815260206004820152602160248201527f56616c696461746f724d616e616765723a20696e76616c6964206e6f646520496044820152601160fa1b60648201526084016105dc565b5f8681526008820160205260409020541561286c5760405162461bcd60e51b815260206004820152602860248201527f56616c696461746f724d616e616765723a206e6f646520494420616c72656164604482015267792061637469766560c01b60648201526084016105dc565b82516030146128d35760405162461bcd60e51b815260206004820152602d60248201527f56616c696461746f724d616e616765723a20696e76616c696420626c7350756260448201526c0d8d2c696caf240d8cadccee8d609b1b60648201526084016105dc565b6128dc85612d25565b5f806129236040518060a00160405280856001015481526020018a8152602001896001600160401b03168152602001886001600160401b0316815260200187815250612f10565b5f828152600586016020526040902091935091506129418282613484565b5060405163ee5b48eb60e01b81525f906005600160991b019063ee5b48eb9061296e908590600401613565565b6020604051808303815f875af115801561298a573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906129ae9190613597565b604080516101008101825260018152602081018c90529192508101336001600160a01b031681526001600160401b038a1660208083018290525f604080850182905260608501939093526080840181905260a0909301839052868352600788019052902081518154829060ff19166001836005811115612a3057612a306133b8565b021790555060208201516001820155604082015160028201805460608501516001600160401b03908116600160a01b026001600160e01b03199092166001600160a01b039094169390931717905560808301516003909201805460a085015160c086015160e0909601518416600160c01b026001600160c01b03968516600160801b02969096166001600160801b03918516600160401b026001600160801b03199093169590941694909417179290921617919091179055612af183611813565b50604080516001600160401b03808b1682528916602082015282918b9186917f79b81620b81daf2c08cd5bb3dbb79e75d2d7a87f52171fde5aadc8c47823026e910160405180910390a45090925050506126fa60015f80516020613af483398151915255565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054600160401b900460ff16612ba057604051631afcd79f60e31b815260040160405180910390fd5b565b612baa612b57565b612bb381613013565b61157460608201356080830135612bd060c0850160a0860161327b565b612be060e0860160c08701613964565b613034565b5f808251602e14612c085760405162461bcd60e51b81526004016105dc9061385e565b5f805f80612c158761308f565b9296509094509250905060f084901c15612c415760405162461bcd60e51b81526004016105dc906138a7565b60e083901c600414612c655760405162461bcd60e51b81526004016105dc906138ea565b909660c09190911c95509350505050565b5f805f808451602714612ca85784516040516241835b60e31b81526004810191909152602760248201526044016105dc565b50505050602081015160228201516026830151604690930151919390929190565b5f805f805f8551603614612cfc5785516040516241835b60e31b81526004810191909152603660248201526044016105dc565b505050506020820151602283015160268401516046850151604e90950151929591949093509190565b7fe92546d698950ddd38910d2e15ed1d923cd0a7b3dde9e2a6a3f380565559cb02545f80516020613ad48339815191529060ff165f03612d63575050565b60408051606081018252600383015480825260048401546001600160401b038082166020850152600160401b9091041692820192909252904290610e1090612dab908361397f565b10612dc7576001600160401b0384166040830152808252612de6565b8382604001818151612dd99190613931565b6001600160401b03169052505b5f826020015183604001516064612dfd9190613992565b612e0791906139bd565b600285015490915060ff9081169082161115612e825760405162461bcd60e51b815260206004820152603460248201527f56616c696461746f724d616e616765723a206d6178696d756d20686f75726c796044820152730818da1d5c9b881c985d1948195e18d95959195960621b60648201526084016105dc565b5050805160038301556020810151600490920180546040909201516001600160401b03908116600160401b026001600160801b031990931693169290921717905550565b5f80516020613af4833981519152805460011901612ef757604051633ee5aeb560e01b815260040160405180910390fd5b60029055565b60015f80516020613af483398151915255565b5f6060826080015151603014612f7a5760405162461bcd60e51b815260206004820152602960248201527f5374616b696e674d657373616765733a20696e76616c6964207369676e6174756044820152680e4ca40d8cadccee8d60bb1b60648201526084016105dc565b5f805f855f01518660200151876040015188608001518960600151604051602001612fab97969594939291906139e2565b6040516020818303038152906040529050600281604051612fcc9190613a58565b602060405180830381855afa158015612fe7573d5f803e3d5ffd5b5050506040513d601f19601f8201168201806040525081019061300a9190613597565b94909350915050565b61301b612b57565b6130236130c1565b61302b6130d1565b611574816130d9565b61303c612b57565b5f5f80516020613a94833981519152948555506001840192909255600290920180546001600160a01b03909216600160401b026001600160e01b03199092166001600160401b0390931692909217179055565b5f805f808451602e14612ca85784516040516241835b60e31b81526004810191909152602e60248201526044016105dc565b6130c9612b57565b612ba0613145565b612ba0612b57565b6130e1612b57565b80355f80516020613ad483398151915290815560208201357fe92546d698950ddd38910d2e15ed1d923cd0a7b3dde9e2a6a3f380565559cb015561312b6060830160408401613a73565b600291909101805460ff191660ff90921691909117905550565b612efd612b57565b50805461315990613407565b5f825580601f10613168575050565b601f0160209004905f5260205f209081019061157491905b80821115613193575f8155600101613180565b5090565b5f60e082840312156131a7575f80fd5b50919050565b8015158114611574575f80fd5b803563ffffffff811681146131cd575f80fd5b919050565b5f805f606084860312156131e4575f80fd5b8335925060208401356131f6816131ad565b9150613204604085016131ba565b90509250925092565b5f6020828403121561321d575f80fd5b5035919050565b5f60208284031215613234575f80fd5b61155c826131ba565b5f806040838503121561324e575f80fd5b613257836131ba565b946020939093013593505050565b80356001600160401b03811681146131cd575f80fd5b5f6020828403121561328b575f80fd5b61155c82613265565b634e487b7160e01b5f52604160045260245ffd5b604051606081016001600160401b03811182821017156132ca576132ca613294565b60405290565b604051601f8201601f191681016001600160401b03811182821017156132f8576132f8613294565b604052919050565b5f6001600160401b0382111561331857613318613294565b50601f01601f191660200190565b5f805f60608486031215613338575f80fd5b8335925061334860208501613265565b915060408401356001600160401b03811115613362575f80fd5b8401601f81018613613372575f80fd5b803561338561338082613300565b6132d0565b818152876020838501011115613399575f80fd5b816020840160208301375f602083830101528093505050509250925092565b634e487b7160e01b5f52602160045260245ffd5b634e487b7160e01b5f52601160045260245ffd5b6001600160401b03828116828216039080821115613400576134006133cc565b5092915050565b600181811c9082168061341b57607f821691505b6020821081036131a757634e487b7160e01b5f52602260045260245ffd5b601f821115610a5657805f5260205f20601f840160051c8101602085101561345e5750805b601f840160051c820191505b8181101561347d575f815560010161346a565b5050505050565b81516001600160401b0381111561349d5761349d613294565b6134b1816134ab8454613407565b84613439565b602080601f8311600181146134e4575f84156134cd5750858301515b5f19600386901b1c1916600185901b17855561353b565b5f85815260208120601f198616915b82811015613512578886015182559484019460019091019084016134f3565b508582101561352f57878501515f19600388901b60f8161c191681555b505060018460011b0185555b505050505050565b5f5b8381101561355d578181015183820152602001613545565b50505f910152565b602081525f8251806020840152613583816040850160208701613543565b601f01601f19169190910160400192915050565b5f602082840312156135a7575f80fd5b5051919050565b5f60208083525f84546135c081613407565b806020870152604060018084165f81146135e157600181146135fd5761362a565b60ff19851660408a0152604084151560051b8a0101955061362a565b895f5260205f205f5b858110156136215781548b8201860152908301908801613606565b8a016040019650505b509398975050505050505050565b634e487b7160e01b5f52601260045260245ffd5b5f8261365a5761365a613638565b500490565b60208082526022908201527f506f5356616c696461746f724d616e616765723a20696e76616c6964206e6f6e604082015261636560f01b606082015260800190565b60208082526029908201527f506f5356616c696461746f724d616e616765723a206e6f6e636520646f6573206040820152680dcdee840dac2e8c6d60bb1b606082015260800190565b8082028115828204841417610ad857610ad86133cc565b60208082526027908201527f56616c696461746f724d616e616765723a20696e76616c69642076616c6964616040820152661d1a5bdb88125160ca1b606082015260800190565b6001600160a01b0381168114611574575f80fd5b80516131cd816131ad565b5f8060408385031215613778575f80fd5b82516001600160401b038082111561378e575f80fd5b90840190606082870312156137a1575f80fd5b6137a96132a8565b825181526020808401516137bc81613748565b828201526040840151838111156137d1575f80fd5b80850194505087601f8501126137e5575f80fd5b835192506137f561338084613300565b8381528882858701011115613808575f80fd5b61381784838301848801613543565b8060408401525081955061382c81880161375c565b9450505050509250929050565b5f6001600160401b03808316818103613854576138546133cc565b6001019392505050565b60208082526029908201527f56616c696461746f724d657373616765733a20696e76616c6964206d657373616040820152680ceca40d8cadccee8d60bb1b606082015260800190565b60208082526023908201527f56616c696461746f724d657373616765733a20696e76616c696420636f64656360408201526208125160ea1b606082015260800190565b60208082526027908201527f56616c696461746f724d657373616765733a20696e76616c6964206d657373616040820152666765207479706560c81b606082015260800190565b6001600160401b03818116838216019080821115613400576134006133cc565b80820180821115610ad857610ad86133cc565b5f60208284031215613974575f80fd5b813561155c81613748565b81810381811115610ad857610ad86133cc565b6001600160401b038181168382160280821691908281146139b5576139b56133cc565b505092915050565b5f6001600160401b03808416806139d6576139d6613638565b92169190910492915050565b61ffff60f01b8860f01b16815263ffffffff60e01b8760e01b1660028201528560068201528460268201525f6001600160401b0360c01b808660c01b1660468401528451613a3781604e860160208901613543565b60c09490941b1691909201604e810191909152605601979650505050505050565b5f8251613a69818460208701613543565b9190910192915050565b5f60208284031215613a83575f80fd5b813560ff8116811461155c575f80fdfe4317713f7ecbdddd4bc99e95d903adedaa883b2e7c2551610bd13e2c7e473d00506f5356616c696461746f724d616e616765723a2064656c65676174696f6e20e92546d698950ddd38910d2e15ed1d923cd0a7b3dde9e2a6a3f380565559cb009b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00e92546d698950ddd38910d2e15ed1d923cd0a7b3dde9e2a6a3f380565559cb07a164736f6c6343000819000a", } // NativeTokenStakingManagerABI is the input ABI used to generate the binding from. diff --git a/abi-bindings/go/staking/PoAValidatorManager/PoAValidatorManager.go b/abi-bindings/go/staking/PoAValidatorManager/PoAValidatorManager.go index 86a87b7fd..be4518adc 100644 --- a/abi-bindings/go/staking/PoAValidatorManager/PoAValidatorManager.go +++ b/abi-bindings/go/staking/PoAValidatorManager/PoAValidatorManager.go @@ -38,8 +38,8 @@ type ValidatorManagerSettings struct { // PoAValidatorManagerMetaData contains all meta data concerning the PoAValidatorManager contract. var PoAValidatorManagerMetaData = &bind.MetaData{ - ABI: "[{\"type\":\"constructor\",\"inputs\":[{\"name\":\"init\",\"type\":\"uint8\",\"internalType\":\"enumICMInitializable\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"WARP_MESSENGER\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"contractIWarpMessenger\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"activeValidators\",\"inputs\":[{\"name\":\"nodeID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"completeEndValidation\",\"inputs\":[{\"name\":\"messageIndex\",\"type\":\"uint32\",\"internalType\":\"uint32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"completeValidatorRegistration\",\"inputs\":[{\"name\":\"messageIndex\",\"type\":\"uint32\",\"internalType\":\"uint32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"getWeight\",\"inputs\":[{\"name\":\"validationID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"initialize\",\"inputs\":[{\"name\":\"settings\",\"type\":\"tuple\",\"internalType\":\"structValidatorManagerSettings\",\"components\":[{\"name\":\"pChainBlockchainID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"subnetID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"maximumHourlyChurn\",\"type\":\"uint8\",\"internalType\":\"uint8\"}]},{\"name\":\"initialOwner\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"initializeEndValidation\",\"inputs\":[{\"name\":\"validationID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"initializeValidatorRegistration\",\"inputs\":[{\"name\":\"weight\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"nodeID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"registrationExpiry\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"signature\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[{\"name\":\"validationID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"owner\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"renounceOwnership\",\"inputs\":[],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"resendEndValidatorMessage\",\"inputs\":[{\"name\":\"validationID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"resendRegisterValidatorMessage\",\"inputs\":[{\"name\":\"validationID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"transferOwnership\",\"inputs\":[{\"name\":\"newOwner\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"event\",\"name\":\"Initialized\",\"inputs\":[{\"name\":\"version\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"OwnershipTransferred\",\"inputs\":[{\"name\":\"previousOwner\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"newOwner\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ValidationPeriodCreated\",\"inputs\":[{\"name\":\"validationID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"nodeID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"registerValidationMessageID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"weight\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"},{\"name\":\"registrationExpiry\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ValidationPeriodEnded\",\"inputs\":[{\"name\":\"validationID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"status\",\"type\":\"uint8\",\"indexed\":true,\"internalType\":\"enumValidatorStatus\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ValidationPeriodRegistered\",\"inputs\":[{\"name\":\"validationID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"weight\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"},{\"name\":\"timestamp\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ValidatorRemovalInitialized\",\"inputs\":[{\"name\":\"validationID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"setWeightMessageID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"weight\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"},{\"name\":\"endTime\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"error\",\"name\":\"InvalidInitialization\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"NotInitializing\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"OwnableInvalidOwner\",\"inputs\":[{\"name\":\"owner\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"OwnableUnauthorizedAccount\",\"inputs\":[{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"ReentrancyGuardReentrantCall\",\"inputs\":[]}]", - Bin: "0x608060405234801561000f575f80fd5b50604051612bb4380380612bb483398101604081905261002e91610107565b60018160018111156100425761004261012c565b0361004f5761004f610055565b50610140565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000900460ff16156100a55760405163f92ee8a960e01b815260040160405180910390fd5b80546001600160401b03908116146101045780546001600160401b0319166001600160401b0390811782556040519081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50565b5f60208284031215610117575f80fd5b815160028110610125575f80fd5b9392505050565b634e487b7160e01b5f52602160045260245ffd5b612a678061014d5f395ff3fe608060405234801561000f575f80fd5b50600436106100cb575f3560e01c80638da5cb5b11610088578063b771b3bc11610063578063b771b3bc146101f8578063bee0a03f14610206578063c151c0b914610219578063f2fde38b1461022c575f80fd5b80638da5cb5b1461018e57806397fb70d4146101d2578063a3a65e48146101e5575f80fd5b80630322ed98146100cf5780630cdd0985146100e45780633aaa9f2514610135578063467ef06f1461014857806366435abf1461015b578063715018a614610186575b5f80fd5b6100e26100dd36600461237d565b61023f565b005b6101226100f236600461237d565b5f9081527fe92546d698950ddd38910d2e15ed1d923cd0a7b3dde9e2a6a3f380565559cb08602052604090205490565b6040519081526020015b60405180910390f35b610122610143366004612441565b6103a0565b6100e26101563660046124e4565b6103c0565b61016e61016936600461237d565b610743565b6040516001600160401b03909116815260200161012c565b6100e2610757565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b03165b6040516001600160a01b03909116815260200161012c565b6100e26101e036600461237d565b61076a565b6100e26101f33660046124e4565b610776565b6101ba6005600160991b0181565b6100e261021436600461237d565b610933565b6100e2610227366004612522565b610a02565b6100e261023a36600461255e565b610b10565b5f8181527fe92546d698950ddd38910d2e15ed1d923cd0a7b3dde9e2a6a3f380565559cb066020526040812080545f80516020612a3b83398151915292919061028790612579565b90501180156102b9575060035f83815260078301602052604090205460ff1660058111156102b7576102b76125b1565b145b6103225760405162461bcd60e51b815260206004820152602f60248201527f56616c696461746f724d616e616765723a2056616c696461746f72206e6f742060448201526e1c195b991a5b99c81c995b5bdd985b608a1b60648201526084015b60405180910390fd5b5f82815260068201602052604090819020905163ee5b48eb60e01b81526005600160991b019163ee5b48eb9161035b91906004016125c5565b6020604051808303815f875af1158015610377573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061039b919061264f565b505050565b5f6103a9610b4a565b6103b584868585610ba5565b90505b949350505050565b5f80516020612a3b8339815191525f6103d88361100d565b90505f806103e983604001516111ee565b91509150801561044e5760405162461bcd60e51b815260206004820152602a60248201527f56616c696461746f724d616e616765723a20726567697374726174696f6e20736044820152691d1a5b1b081d985b1a5960b21b6064820152608401610319565b5f828152600785016020526040808220815161010081019092528054829060ff166005811115610480576104806125b1565b6005811115610491576104916125b1565b81526001820154602082015260028201546001600160a01b03811660408301526001600160401b03600160a01b909104811660608301526003928301548082166080840152600160401b8104821660a0840152600160801b8104821660c0840152600160c01b90041660e0909101529091505f9082516005811115610518576105186125b1565b14806105365750600182516005811115610534576105346125b1565b145b6105955760405162461bcd60e51b815260206004820152602a60248201527f56616c696461746f724d616e616765723a20696e76616c69642076616c696461604482015269746f722073746174757360b01b6064820152608401610319565b6003825160058111156105aa576105aa6125b1565b036105d157505f83815260068601602052604081206004916105cc9190612333565b6105d5565b5060055b6020808301515f908152600888019091526040812055818160058111156105fe576105fe6125b1565b90816005811115610611576106116125b1565b9052505f84815260078701602052604090208251815484929190829060ff19166001836005811115610645576106456125b1565b021790555060208201516001820155604082015160028201805460608501516001600160401b03908116600160a01b026001600160e01b03199092166001600160a01b039094169390931717905560808301516003909201805460a085015160c086015160e0909601518416600160c01b026001600160c01b03968516600160801b02969096166001600160801b03918516600160401b026001600160801b0319909316959094169490941717929092161791909117905581516005811115610710576107106125b1565b60405185907f1c08e59656f1a18dc2da76826cdc52805c43e897a17c50faefb8ab3c1526cc16905f90a350505050505050565b5f61074d8261144d565b60a0015192915050565b61075f610b4a565b6107685f611571565b565b610773816115e1565b50565b5f80516020612a3b8339815191525f61078e8361100d565b90505f8061079f83604001516111ee565b91509150806108015760405162461bcd60e51b815260206004820152602860248201527f56616c696461746f724d616e616765723a20526567697374726174696f6e206e6044820152671bdd081d985b1a5960c21b6064820152608401610319565b5f8281526005850160205260408120805461081b90612579565b905011801561084d575060015f83815260078601602052604090205460ff16600581111561084b5761084b6125b1565b145b6108695760405162461bcd60e51b815260040161031990612666565b5f828152600585016020526040812061088191612333565b5f8281526007850160208181526040808420805460ff191660021781556003810180546001600160401b0342818116600160801b0267ffffffffffffffff60801b19909316929092178355600190930154875260088b0185528387208990559588905293835292548151600160401b90910490931683529082019290925283917ff8fd1c90fb9cfa2ca2358fdf5806b086ad43315d92b221c929efc7f105ce7568910160405180910390a25050505050565b5f8181527fe92546d698950ddd38910d2e15ed1d923cd0a7b3dde9e2a6a3f380565559cb056020526040812080545f80516020612a3b83398151915292919061097b90612579565b90501180156109ad575060015f83815260078301602052604090205460ff1660058111156109ab576109ab6125b1565b145b6109c95760405162461bcd60e51b815260040161031990612666565b5f82815260058201602052604090819020905163ee5b48eb60e01b81526005600160991b019163ee5b48eb9161035b91906004016125c5565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a008054600160401b810460ff1615906001600160401b03165f81158015610a465750825b90505f826001600160401b03166001148015610a615750303b155b905081158015610a6f575080155b15610a8d5760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff191660011785558315610ab757845460ff60401b1916600160401b1785555b610ac187876119ac565b8315610b0757845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50505050505050565b610b18610b4a565b6001600160a01b038116610b4157604051631e4fbdf760e01b81525f6004820152602401610319565b61077381611571565b33610b7c7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031690565b6001600160a01b0316146107685760405163118cdaa760e01b8152336004820152602401610319565b5f610bae6119ca565b5f80516020612a3b833981519152426001600160401b038516118015610be857506001600160401b038416610be6426202a3006126c1565b115b610c4a5760405162461bcd60e51b815260206004820152602d60248201527f56616c696461746f724d616e616765723a20696e76616c69642072656769737460448201526c726174696f6e2065787069727960981b6064820152608401610319565b85610ca15760405162461bcd60e51b815260206004820152602160248201527f56616c696461746f724d616e616765723a20696e76616c6964206e6f646520496044820152601160fa1b6064820152608401610319565b5f86815260088201602052604090205415610d0f5760405162461bcd60e51b815260206004820152602860248201527f56616c696461746f724d616e616765723a206e6f646520494420616c72656164604482015267792061637469766560c01b6064820152608401610319565b8251603014610d765760405162461bcd60e51b815260206004820152602d60248201527f56616c696461746f724d616e616765723a20696e76616c696420626c7350756260448201526c0d8d2c696caf240d8cadccee8d609b1b6064820152608401610319565b610d7f85611a14565b5f80610dc66040518060a00160405280856001015481526020018a8152602001896001600160401b03168152602001886001600160401b0316815260200187815250611bb5565b5f82815260058601602052604090209193509150610de48282612725565b5060405163ee5b48eb60e01b81525f906005600160991b019063ee5b48eb90610e11908590600401612806565b6020604051808303815f875af1158015610e2d573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e51919061264f565b604080516101008101825260018152602081018c90529192508101336001600160a01b031681526001600160401b038a1660208083018290525f604080850182905260608501939093526080840181905260a0909301839052868352600788019052902081518154829060ff19166001836005811115610ed357610ed36125b1565b021790555060208201516001820155604082015160028201805460608501516001600160401b03908116600160a01b026001600160e01b03199092166001600160a01b039094169390931717905560808301516003909201805460a085015160c086015160e0909601518416600160c01b026001600160c01b03968516600160801b02969096166001600160801b03918516600160401b026001600160801b03199093169590941694909417179290921617919091179055610f9483611f5a565b50604080516001600160401b03808b1682528916602082015282918b9186917f79b81620b81daf2c08cd5bb3dbb79e75d2d7a87f52171fde5aadc8c47823026e910160405180910390a45090925050506103b860017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f0055565b60408051606080820183525f8083526020830181905292820152905f80516020612a3b8339815191526040516306f8253560e41b815263ffffffff851660048201529091505f9081906005600160991b0190636f825350906024015f60405180830381865afa158015611082573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526110a99190810190612847565b91509150806111105760405162461bcd60e51b815260206004820152602d60248201527f56616c696461746f724d616e616765723a20496e76696e76616c6964616c696460448201526c2077617270206d65737361676560981b6064820152608401610319565b82548251146111735760405162461bcd60e51b815260206004820152602960248201527f56616c696461746f724d616e616765723a20696e76616c696420736f757263656044820152680818da185a5b88125160ba1b6064820152608401610319565b60208201516001600160a01b0316156111e65760405162461bcd60e51b815260206004820152602f60248201527f56616c696461746f724d616e616765723a20696e76616c6964206f726967696e60448201526e2073656e646572206164647265737360881b6064820152608401610319565b509392505050565b5f8082516027146112535760405162461bcd60e51b815260206004820152602960248201527f56616c696461746f724d657373616765733a20696e76616c6964206d657373616044820152680ceca40d8cadccee8d60bb1b6064820152608401610319565b5f805b60028110156112a25761126a816001612919565b61127590600861292c565b61ffff1685828151811061128b5761128b612943565b016020015160f81c901b9190911790600101611256565b5061ffff8116156113015760405162461bcd60e51b815260206004820152602360248201527f56616c696461746f724d657373616765733a20696e76616c696420636f64656360448201526208125160ea1b6064820152608401610319565b5f805b600481101561135c57611318816003612919565b61132390600861292c565b63ffffffff16866113358360026126c1565b8151811061134557611345612943565b016020015160f81c901b9190911790600101611304565b5063ffffffff81166002146113c35760405162461bcd60e51b815260206004820152602760248201527f56616c696461746f724d657373616765733a20696e76616c6964206d657373616044820152666765207479706560c81b6064820152608401610319565b5f805b6020811015611418576113da81601f612919565b6113e590600861292c565b876113f18360066126c1565b8151811061140157611401612943565b016020015160f81c901b91909117906001016113c6565b505f8660268151811061142d5761142d612943565b016020015191976001600160f81b03199092161515965090945050505050565b6040805161010080820183525f8083526020808401829052838501829052606084018290526080840182905260a0840182905260c0840182905260e084018290528582527fe92546d698950ddd38910d2e15ed1d923cd0a7b3dde9e2a6a3f380565559cb0790528390208351918201909352825491925f80516020612a3b83398151915292829060ff1660058111156114e8576114e86125b1565b60058111156114f9576114f96125b1565b81526001820154602082015260028201546001600160a01b03811660408301526001600160401b03600160a01b909104811660608301526003909201548083166080830152600160401b8104831660a0830152600160801b8104831660c0830152600160c01b900490911660e0909101529392505050565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930080546001600160a01b031981166001600160a01b03848116918217845560405192169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a3505050565b5f8181527fe92546d698950ddd38910d2e15ed1d923cd0a7b3dde9e2a6a3f380565559cb0760205260408082208151610100810190925280545f80516020612a3b83398151915293929190829060ff166005811115611642576116426125b1565b6005811115611653576116536125b1565b8152600182015460208201526002808301546001600160a01b03811660408401526001600160401b03600160a01b909104811660608401526003909301548084166080840152600160401b8104841660a0840152600160801b8104841660c0840152600160c01b900490921660e090910152909150815160058111156116db576116db6125b1565b146117375760405162461bcd60e51b815260206004820152602660248201527f56616c696461746f724d616e616765723a2076616c696461746f72206e6f742060448201526561637469766560d01b6064820152608401610319565b60408101516001600160a01b0316336001600160a01b0316146117b15760405162461bcd60e51b815260206004820152602c60248201527f56616c696461746f724d616e616765723a2073656e646572206e6f742076616c60448201526b34b230ba37b91037bbb732b960a11b6064820152608401610319565b6117be8160a00151611a14565b60038152426001600160401b031660e08201525f83815260078301602052604090208151815483929190829060ff19166001836005811115611802576118026125b1565b021790555060208201516001820155604082015160028201805460608501516001600160401b03908116600160a01b026001600160e01b03199092166001600160a01b039094169390931717905560808301516003909201805460a085015160c086015160e0909601518416600160c01b026001600160c01b03968516600160801b02969096166001600160801b03918516600160401b026001600160801b031990931695909416949094171792909216179190911790555f6118ce846118c881611f5a565b5f612007565b5f85815260068501602052604090209091506118ea8282612725565b5060405163ee5b48eb60e01b81525f906005600160991b019063ee5b48eb90611917908590600401612806565b6020604051808303815f875af1158015611933573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611957919061264f565b60a0840151604080516001600160401b039092168252426020830152919250829187917f13d58394cf269d48bcf927959a29a5ffee7c9924dafff8927ecdf3c48ffa7c67910160405180910390a35050505050565b6119b4612224565b6119bd8261226d565b6119c68161228e565b5050565b7f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00805460011901611a0e57604051633ee5aeb560e01b815260040160405180910390fd5b60029055565b7fe92546d698950ddd38910d2e15ed1d923cd0a7b3dde9e2a6a3f380565559cb02545f80516020612a3b8339815191529060ff165f03611a52575050565b60408051606081018252600383015480825260048401546001600160401b038082166020850152600160401b9091041692820192909252904290610e1090611a9a9083612919565b10611ab6576001600160401b0384166040830152808252611ad5565b8382604001818151611ac89190612957565b6001600160401b03169052505b5f826020015183604001516064611aec919061297e565b611af691906129a9565b600285015490915060ff9081169082161115611b715760405162461bcd60e51b815260206004820152603460248201527f56616c696461746f724d616e616765723a206d6178696d756d20686f75726c796044820152730818da1d5c9b881c985d1948195e18d95959195960621b6064820152608401610319565b5050805160038301556020810151600490920180546040909201516001600160401b03908116600160401b026001600160801b031990931693169290921717905550565b5f6060826080015151603014611c1f5760405162461bcd60e51b815260206004820152602960248201527f5374616b696e674d657373616765733a20696e76616c6964207369676e6174756044820152680e4ca40d8cadccee8d60bb1b6064820152608401610319565b60408051608680825260c082019092525f916020820181803683370190505090505f5b6002811015611c9657611c56816001612919565b611c6190600861292c565b5081515f90839083908110611c7857611c78612943565b60200101906001600160f81b03191690815f1a905350600101611c42565b505f5b6004811015611cf457611cad816003612919565b611cb890600861292c565b505f82611cc68360026126c1565b81518110611cd657611cd6612943565b60200101906001600160f81b03191690815f1a905350600101611c99565b505f5b6020811015611d515784518160208110611d1357611d13612943565b1a60f81b82611d238360066126c1565b81518110611d3357611d33612943565b60200101906001600160f81b03191690815f1a905350600101611cf7565b505f5b6020811015611db15784602001518160208110611d7357611d73612943565b1a60f81b82611d838360266126c1565b81518110611d9357611d93612943565b60200101906001600160f81b03191690815f1a905350600101611d54565b505f5b6008811015611e2557611dc8816007612919565b611dd390600861292c565b60ff1685604001516001600160401b0316901c60f81b82826046611df791906126c1565b81518110611e0757611e07612943565b60200101906001600160f81b03191690815f1a905350600101611db4565b505f5b6030811015611e905784608001518181518110611e4757611e47612943565b01602001516001600160f81b03191682611e6283604e6126c1565b81518110611e7257611e72612943565b60200101906001600160f81b03191690815f1a905350600101611e28565b505f5b6008811015611f0257611ea7816007612919565b611eb290600861292c565b60608601516001600160401b0390811691161c60f81b82611ed483607e6126c1565b81518110611ee457611ee4612943565b60200101906001600160f81b03191690815f1a905350600101611e93565b50600281604051611f1391906129da565b602060405180830381855afa158015611f2e573d5f803e3d5ffd5b5050506040513d601f19601f82011682018060405250810190611f51919061264f565b94909350915050565b5f8181527fe92546d698950ddd38910d2e15ed1d923cd0a7b3dde9e2a6a3f380565559cb076020526040812060030180545f80516020612a3b833981519152916001600160401b0390911690819084611fb2836129f5565b91906101000a8154816001600160401b0302191690836001600160401b03160217905550508092505050919050565b60017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f0055565b60408051603680825260608281019093525f91906020820181803683370190505090505f5b600281101561208057612040816001612919565b61204b90600861292c565b5081515f9083908390811061206257612062612943565b60200101906001600160f81b03191690815f1a90535060010161202c565b505f5b60048110156120e357612097816003612919565b6120a290600861292c565b6001901c60f81b826120b58360026126c1565b815181106120c5576120c5612943565b60200101906001600160f81b03191690815f1a905350600101612083565b505f5b6020811015612145576120fa81601f612919565b61210590600861292c565b86901c60f81b826121178360066126c1565b8151811061212757612127612943565b60200101906001600160f81b03191690815f1a9053506001016120e6565b505f5b60088110156121b05761215c816007612919565b61216790600861292c565b6001600160401b038616901c60f81b826121828360266126c1565b8151811061219257612192612943565b60200101906001600160f81b03191690815f1a905350600101612148565b505f5b600881101561221b576121c7816007612919565b6121d290600861292c565b6001600160401b038516901c60f81b826121ed83602e6126c1565b815181106121fd576121fd612943565b60200101906001600160f81b03191690815f1a9053506001016121b3565b50949350505050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054600160401b900460ff1661076857604051631afcd79f60e31b815260040160405180910390fd5b612275612224565b61227d61229f565b6122856122af565b610773816122b7565b612296612224565b61077381612323565b6122a7612224565b61076861232b565b610768612224565b6122bf612224565b80355f80516020612a3b83398151915290815560208201357fe92546d698950ddd38910d2e15ed1d923cd0a7b3dde9e2a6a3f380565559cb01556123096060830160408401612a1a565b600291909101805460ff191660ff90921691909117905550565b610b18612224565b611fe1612224565b50805461233f90612579565b5f825580601f1061234e575050565b601f0160209004905f5260205f209081019061077391905b80821115612379575f8155600101612366565b5090565b5f6020828403121561238d575f80fd5b5035919050565b80356001600160401b03811681146123aa575f80fd5b919050565b634e487b7160e01b5f52604160045260245ffd5b604051606081016001600160401b03811182821017156123e5576123e56123af565b60405290565b604051601f8201601f191681016001600160401b0381118282101715612413576124136123af565b604052919050565b5f6001600160401b03821115612433576124336123af565b50601f01601f191660200190565b5f805f8060808587031215612454575f80fd5b61245d85612394565b93506020850135925061247260408601612394565b915060608501356001600160401b0381111561248c575f80fd5b8501601f8101871361249c575f80fd5b80356124af6124aa8261241b565b6123eb565b8181528860208385010111156124c3575f80fd5b816020840160208301375f6020838301015280935050505092959194509250565b5f602082840312156124f4575f80fd5b813563ffffffff81168114612507575f80fd5b9392505050565b6001600160a01b0381168114610773575f80fd5b5f808284036080811215612534575f80fd5b6060811215612541575f80fd5b5082915060608301356125538161250e565b809150509250929050565b5f6020828403121561256e575f80fd5b81356125078161250e565b600181811c9082168061258d57607f821691505b6020821081036125ab57634e487b7160e01b5f52602260045260245ffd5b50919050565b634e487b7160e01b5f52602160045260245ffd5b5f60208083525f84546125d781612579565b806020870152604060018084165f81146125f8576001811461261457612641565b60ff19851660408a0152604084151560051b8a01019550612641565b895f5260205f205f5b858110156126385781548b820186015290830190880161261d565b8a016040019650505b509398975050505050505050565b5f6020828403121561265f575f80fd5b5051919050565b60208082526027908201527f56616c696461746f724d616e616765723a20696e76616c69642076616c6964616040820152661d1a5bdb88125160ca1b606082015260800190565b634e487b7160e01b5f52601160045260245ffd5b808201808211156126d4576126d46126ad565b92915050565b601f82111561039b57805f5260205f20601f840160051c810160208510156126ff5750805b601f840160051c820191505b8181101561271e575f815560010161270b565b5050505050565b81516001600160401b0381111561273e5761273e6123af565b6127528161274c8454612579565b846126da565b602080601f831160018114612785575f841561276e5750858301515b5f19600386901b1c1916600185901b1785556127dc565b5f85815260208120601f198616915b828110156127b357888601518255948401946001909101908401612794565b50858210156127d057878501515f19600388901b60f8161c191681555b505060018460011b0185555b505050505050565b5f5b838110156127fe5781810151838201526020016127e6565b50505f910152565b602081525f82518060208401526128248160408501602087016127e4565b601f01601f19169190910160400192915050565b805180151581146123aa575f80fd5b5f8060408385031215612858575f80fd5b82516001600160401b038082111561286e575f80fd5b9084019060608287031215612881575f80fd5b6128896123c3565b8251815260208084015161289c8161250e565b828201526040840151838111156128b1575f80fd5b80850194505087601f8501126128c5575f80fd5b835192506128d56124aa8461241b565b83815288828587010111156128e8575f80fd5b6128f7848383018488016127e4565b8060408401525081955061290c818801612838565b9450505050509250929050565b818103818111156126d4576126d46126ad565b80820281158282048414176126d4576126d46126ad565b634e487b7160e01b5f52603260045260245ffd5b6001600160401b03818116838216019080821115612977576129776126ad565b5092915050565b6001600160401b038181168382160280821691908281146129a1576129a16126ad565b505092915050565b5f6001600160401b03808416806129ce57634e487b7160e01b5f52601260045260245ffd5b92169190910492915050565b5f82516129eb8184602087016127e4565b9190910192915050565b5f6001600160401b03808316818103612a1057612a106126ad565b6001019392505050565b5f60208284031215612a2a575f80fd5b813560ff81168114612507575f80fdfee92546d698950ddd38910d2e15ed1d923cd0a7b3dde9e2a6a3f380565559cb00a164736f6c6343000819000a", + ABI: "[{\"type\":\"constructor\",\"inputs\":[{\"name\":\"init\",\"type\":\"uint8\",\"internalType\":\"enumICMInitializable\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"WARP_MESSENGER\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"contractIWarpMessenger\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"activeValidators\",\"inputs\":[{\"name\":\"nodeID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"completeEndValidation\",\"inputs\":[{\"name\":\"messageIndex\",\"type\":\"uint32\",\"internalType\":\"uint32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"completeValidatorRegistration\",\"inputs\":[{\"name\":\"messageIndex\",\"type\":\"uint32\",\"internalType\":\"uint32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"getWeight\",\"inputs\":[{\"name\":\"validationID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"initialize\",\"inputs\":[{\"name\":\"settings\",\"type\":\"tuple\",\"internalType\":\"structValidatorManagerSettings\",\"components\":[{\"name\":\"pChainBlockchainID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"subnetID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"maximumHourlyChurn\",\"type\":\"uint8\",\"internalType\":\"uint8\"}]},{\"name\":\"initialOwner\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"initializeEndValidation\",\"inputs\":[{\"name\":\"validationID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"initializeValidatorRegistration\",\"inputs\":[{\"name\":\"weight\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"nodeID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"registrationExpiry\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"signature\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[{\"name\":\"validationID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"owner\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"renounceOwnership\",\"inputs\":[],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"resendEndValidatorMessage\",\"inputs\":[{\"name\":\"validationID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"resendRegisterValidatorMessage\",\"inputs\":[{\"name\":\"validationID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"transferOwnership\",\"inputs\":[{\"name\":\"newOwner\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"event\",\"name\":\"Initialized\",\"inputs\":[{\"name\":\"version\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"OwnershipTransferred\",\"inputs\":[{\"name\":\"previousOwner\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"newOwner\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ValidationPeriodCreated\",\"inputs\":[{\"name\":\"validationID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"nodeID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"registerValidationMessageID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"weight\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"},{\"name\":\"registrationExpiry\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ValidationPeriodEnded\",\"inputs\":[{\"name\":\"validationID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"status\",\"type\":\"uint8\",\"indexed\":true,\"internalType\":\"enumValidatorStatus\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ValidationPeriodRegistered\",\"inputs\":[{\"name\":\"validationID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"weight\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"},{\"name\":\"timestamp\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ValidatorRemovalInitialized\",\"inputs\":[{\"name\":\"validationID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"setWeightMessageID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"weight\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"},{\"name\":\"endTime\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"error\",\"name\":\"IncorrectInputLength\",\"inputs\":[{\"name\":\"expected\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"actual\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"InvalidInitialization\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"NotInitializing\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"OwnableInvalidOwner\",\"inputs\":[{\"name\":\"owner\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"OwnableUnauthorizedAccount\",\"inputs\":[{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"ReentrancyGuardReentrantCall\",\"inputs\":[]}]", + Bin: "0x608060405234801561000f575f80fd5b506040516126d03803806126d083398101604081905261002e91610107565b60018160018111156100425761004261012c565b0361004f5761004f610055565b50610140565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000900460ff16156100a55760405163f92ee8a960e01b815260040160405180910390fd5b80546001600160401b03908116146101045780546001600160401b0319166001600160401b0390811782556040519081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50565b5f60208284031215610117575f80fd5b815160028110610125575f80fd5b9392505050565b634e487b7160e01b5f52602160045260245ffd5b6125838061014d5f395ff3fe608060405234801561000f575f80fd5b50600436106100cb575f3560e01c80638da5cb5b11610088578063b771b3bc11610063578063b771b3bc146101f8578063bee0a03f14610206578063c151c0b914610219578063f2fde38b1461022c575f80fd5b80638da5cb5b1461018e57806397fb70d4146101d2578063a3a65e48146101e5575f80fd5b80630322ed98146100cf5780630cdd0985146100e45780633aaa9f2514610135578063467ef06f1461014857806366435abf1461015b578063715018a614610186575b5f80fd5b6100e26100dd366004611e4e565b61023f565b005b6101226100f2366004611e4e565b5f9081527fe92546d698950ddd38910d2e15ed1d923cd0a7b3dde9e2a6a3f380565559cb08602052604090205490565b6040519081526020015b60405180910390f35b610122610143366004611f12565b6103a0565b6100e2610156366004611fb5565b6103c0565b61016e610169366004611e4e565b610743565b6040516001600160401b03909116815260200161012c565b6100e2610757565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b03165b6040516001600160a01b03909116815260200161012c565b6100e26101e0366004611e4e565b61076a565b6100e26101f3366004611fb5565b610776565b6101ba6005600160991b0181565b6100e2610214366004611e4e565b610933565b6100e2610227366004611ff3565b610a02565b6100e261023a36600461202f565b610b10565b5f8181527fe92546d698950ddd38910d2e15ed1d923cd0a7b3dde9e2a6a3f380565559cb066020526040812080545f805160206125578339815191529291906102879061204a565b90501180156102b9575060035f83815260078301602052604090205460ff1660058111156102b7576102b7612082565b145b6103225760405162461bcd60e51b815260206004820152602f60248201527f56616c696461746f724d616e616765723a2056616c696461746f72206e6f742060448201526e1c195b991a5b99c81c995b5bdd985b608a1b60648201526084015b60405180910390fd5b5f82815260068201602052604090819020905163ee5b48eb60e01b81526005600160991b019163ee5b48eb9161035b9190600401612096565b6020604051808303815f875af1158015610377573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061039b9190612120565b505050565b5f6103a9610b4a565b6103b584868585610ba5565b90505b949350505050565b5f805160206125578339815191525f6103d88361100d565b90505f806103e983604001516111ee565b91509150801561044e5760405162461bcd60e51b815260206004820152602a60248201527f56616c696461746f724d616e616765723a20726567697374726174696f6e20736044820152691d1a5b1b081d985b1a5960b21b6064820152608401610319565b5f828152600785016020526040808220815161010081019092528054829060ff16600581111561048057610480612082565b600581111561049157610491612082565b81526001820154602082015260028201546001600160a01b03811660408301526001600160401b03600160a01b909104811660608301526003928301548082166080840152600160401b8104821660a0840152600160801b8104821660c0840152600160c01b90041660e0909101529091505f908251600581111561051857610518612082565b1480610536575060018251600581111561053457610534612082565b145b6105955760405162461bcd60e51b815260206004820152602a60248201527f56616c696461746f724d616e616765723a20696e76616c69642076616c696461604482015269746f722073746174757360b01b6064820152608401610319565b6003825160058111156105aa576105aa612082565b036105d157505f83815260068601602052604081206004916105cc9190611e04565b6105d5565b5060055b6020808301515f908152600888019091526040812055818160058111156105fe576105fe612082565b9081600581111561061157610611612082565b9052505f84815260078701602052604090208251815484929190829060ff1916600183600581111561064557610645612082565b021790555060208201516001820155604082015160028201805460608501516001600160401b03908116600160a01b026001600160e01b03199092166001600160a01b039094169390931717905560808301516003909201805460a085015160c086015160e0909601518416600160c01b026001600160c01b03968516600160801b02969096166001600160801b03918516600160401b026001600160801b031990931695909416949094171792909216179190911790558151600581111561071057610710612082565b60405185907f1c08e59656f1a18dc2da76826cdc52805c43e897a17c50faefb8ab3c1526cc16905f90a350505050505050565b5f61074d8261133f565b60a0015192915050565b61075f610b4a565b6107685f611463565b565b610773816114d3565b50565b5f805160206125578339815191525f61078e8361100d565b90505f8061079f83604001516111ee565b91509150806108015760405162461bcd60e51b815260206004820152602860248201527f56616c696461746f724d616e616765723a20526567697374726174696f6e206e6044820152671bdd081d985b1a5960c21b6064820152608401610319565b5f8281526005850160205260408120805461081b9061204a565b905011801561084d575060015f83815260078601602052604090205460ff16600581111561084b5761084b612082565b145b6108695760405162461bcd60e51b815260040161031990612137565b5f828152600585016020526040812061088191611e04565b5f8281526007850160208181526040808420805460ff191660021781556003810180546001600160401b0342818116600160801b0267ffffffffffffffff60801b19909316929092178355600190930154875260088b0185528387208990559588905293835292548151600160401b90910490931683529082019290925283917ff8fd1c90fb9cfa2ca2358fdf5806b086ad43315d92b221c929efc7f105ce7568910160405180910390a25050505050565b5f8181527fe92546d698950ddd38910d2e15ed1d923cd0a7b3dde9e2a6a3f380565559cb056020526040812080545f8051602061255783398151915292919061097b9061204a565b90501180156109ad575060015f83815260078301602052604090205460ff1660058111156109ab576109ab612082565b145b6109c95760405162461bcd60e51b815260040161031990612137565b5f82815260058201602052604090819020905163ee5b48eb60e01b81526005600160991b019163ee5b48eb9161035b9190600401612096565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a008054600160401b810460ff1615906001600160401b03165f81158015610a465750825b90505f826001600160401b03166001148015610a615750303b155b905081158015610a6f575080155b15610a8d5760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff191660011785558315610ab757845460ff60401b1916600160401b1785555b610ac187876118e9565b8315610b0757845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50505050505050565b610b18610b4a565b6001600160a01b038116610b4157604051631e4fbdf760e01b81525f6004820152602401610319565b61077381611463565b33610b7c7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031690565b6001600160a01b0316146107685760405163118cdaa760e01b8152336004820152602401610319565b5f610bae611907565b5f80516020612557833981519152426001600160401b038516118015610be857506001600160401b038416610be6426202a300612192565b115b610c4a5760405162461bcd60e51b815260206004820152602d60248201527f56616c696461746f724d616e616765723a20696e76616c69642072656769737460448201526c726174696f6e2065787069727960981b6064820152608401610319565b85610ca15760405162461bcd60e51b815260206004820152602160248201527f56616c696461746f724d616e616765723a20696e76616c6964206e6f646520496044820152601160fa1b6064820152608401610319565b5f86815260088201602052604090205415610d0f5760405162461bcd60e51b815260206004820152602860248201527f56616c696461746f724d616e616765723a206e6f646520494420616c72656164604482015267792061637469766560c01b6064820152608401610319565b8251603014610d765760405162461bcd60e51b815260206004820152602d60248201527f56616c696461746f724d616e616765723a20696e76616c696420626c7350756260448201526c0d8d2c696caf240d8cadccee8d609b1b6064820152608401610319565b610d7f85611951565b5f80610dc66040518060a00160405280856001015481526020018a8152602001896001600160401b03168152602001886001600160401b0316815260200187815250611af2565b5f82815260058601602052604090209193509150610de482826121f6565b5060405163ee5b48eb60e01b81525f906005600160991b019063ee5b48eb90610e119085906004016122d7565b6020604051808303815f875af1158015610e2d573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e519190612120565b604080516101008101825260018152602081018c90529192508101336001600160a01b031681526001600160401b038a1660208083018290525f604080850182905260608501939093526080840181905260a0909301839052868352600788019052902081518154829060ff19166001836005811115610ed357610ed3612082565b021790555060208201516001820155604082015160028201805460608501516001600160401b03908116600160a01b026001600160e01b03199092166001600160a01b039094169390931717905560808301516003909201805460a085015160c086015160e0909601518416600160c01b026001600160c01b03968516600160801b02969096166001600160801b03918516600160401b026001600160801b03199093169590941694909417179290921617919091179055610f9483611bf5565b50604080516001600160401b03808b1682528916602082015282918b9186917f79b81620b81daf2c08cd5bb3dbb79e75d2d7a87f52171fde5aadc8c47823026e910160405180910390a45090925050506103b860017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f0055565b60408051606080820183525f8083526020830181905292820152905f805160206125578339815191526040516306f8253560e41b815263ffffffff851660048201529091505f9081906005600160991b0190636f825350906024015f60405180830381865afa158015611082573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526110a99190810190612318565b91509150806111105760405162461bcd60e51b815260206004820152602d60248201527f56616c696461746f724d616e616765723a20496e76696e76616c6964616c696460448201526c2077617270206d65737361676560981b6064820152608401610319565b82548251146111735760405162461bcd60e51b815260206004820152602960248201527f56616c696461746f724d616e616765723a20696e76616c696420736f757263656044820152680818da185a5b88125160ba1b6064820152608401610319565b60208201516001600160a01b0316156111e65760405162461bcd60e51b815260206004820152602f60248201527f56616c696461746f724d616e616765723a20696e76616c6964206f726967696e60448201526e2073656e646572206164647265737360881b6064820152608401610319565b509392505050565b5f8082516027146112535760405162461bcd60e51b815260206004820152602960248201527f56616c696461746f724d657373616765733a20696e76616c6964206d657373616044820152680ceca40d8cadccee8d60bb1b6064820152608401610319565b5f805f8061126087611ca2565b9296509094509250905060f084901c156112c85760405162461bcd60e51b815260206004820152602360248201527f56616c696461746f724d657373616765733a20696e76616c696420636f64656360448201526208125160ea1b6064820152608401610319565b60e083901c60021461132c5760405162461bcd60e51b815260206004820152602760248201527f56616c696461746f724d657373616765733a20696e76616c6964206d657373616044820152666765207479706560c81b6064820152608401610319565b909660f89190911c151595509350505050565b6040805161010080820183525f8083526020808401829052838501829052606084018290526080840182905260a0840182905260c0840182905260e084018290528582527fe92546d698950ddd38910d2e15ed1d923cd0a7b3dde9e2a6a3f380565559cb0790528390208351918201909352825491925f8051602061255783398151915292829060ff1660058111156113da576113da612082565b60058111156113eb576113eb612082565b81526001820154602082015260028201546001600160a01b03811660408301526001600160401b03600160a01b909104811660608301526003909201548083166080830152600160401b8104831660a0830152600160801b8104831660c0830152600160c01b900490911660e0909101529392505050565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930080546001600160a01b031981166001600160a01b03848116918217845560405192169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a3505050565b5f8181527fe92546d698950ddd38910d2e15ed1d923cd0a7b3dde9e2a6a3f380565559cb0760205260408082208151610100810190925280545f8051602061255783398151915293929190829060ff16600581111561153457611534612082565b600581111561154557611545612082565b8152600182015460208201526002808301546001600160a01b03811660408401526001600160401b03600160a01b909104811660608401526003909301548084166080840152600160401b8104841660a0840152600160801b8104841660c0840152600160c01b900490921660e090910152909150815160058111156115cd576115cd612082565b146116295760405162461bcd60e51b815260206004820152602660248201527f56616c696461746f724d616e616765723a2076616c696461746f72206e6f742060448201526561637469766560d01b6064820152608401610319565b60408101516001600160a01b0316336001600160a01b0316146116a35760405162461bcd60e51b815260206004820152602c60248201527f56616c696461746f724d616e616765723a2073656e646572206e6f742076616c60448201526b34b230ba37b91037bbb732b960a11b6064820152608401610319565b6116b08160a00151611951565b60038152426001600160401b031660e08201525f83815260078301602052604090208151815483929190829060ff191660018360058111156116f4576116f4612082565b021790555060208201516001820155604082015160028201805460608501516001600160401b03908116600160a01b026001600160e01b03199092166001600160a01b039094169390931717905560808301516003909201805460a085015160c086015160e0909601518416600160c01b026001600160c01b03968516600160801b02969096166001600160801b03918516600160401b026001600160801b031990931695909416949094171792909216179190911790555f61180b846117ba81611bf5565b5f604080515f6020820152600160e01b6022820152602681019490945260c092831b6001600160c01b031990811660468601529190921b16604e830152805160368184030181526056909201905290565b5f858152600685016020526040902090915061182782826121f6565b5060405163ee5b48eb60e01b81525f906005600160991b019063ee5b48eb906118549085906004016122d7565b6020604051808303815f875af1158015611870573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906118949190612120565b60a0840151604080516001600160401b039092168252426020830152919250829187917f13d58394cf269d48bcf927959a29a5ffee7c9924dafff8927ecdf3c48ffa7c67910160405180910390a35050505050565b6118f1611cf5565b6118fa82611d3e565b61190381611d5f565b5050565b7f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f0080546001190161194b57604051633ee5aeb560e01b815260040160405180910390fd5b60029055565b7fe92546d698950ddd38910d2e15ed1d923cd0a7b3dde9e2a6a3f380565559cb02545f805160206125578339815191529060ff165f0361198f575050565b60408051606081018252600383015480825260048401546001600160401b038082166020850152600160401b9091041692820192909252904290610e10906119d790836123ea565b106119f3576001600160401b0384166040830152808252611a12565b8382604001818151611a0591906123fd565b6001600160401b03169052505b5f826020015183604001516064611a299190612424565b611a33919061244f565b600285015490915060ff9081169082161115611aae5760405162461bcd60e51b815260206004820152603460248201527f56616c696461746f724d616e616765723a206d6178696d756d20686f75726c796044820152730818da1d5c9b881c985d1948195e18d95959195960621b6064820152608401610319565b5050805160038301556020810151600490920180546040909201516001600160401b03908116600160401b026001600160801b031990931693169290921717905550565b5f6060826080015151603014611b5c5760405162461bcd60e51b815260206004820152602960248201527f5374616b696e674d657373616765733a20696e76616c6964207369676e6174756044820152680e4ca40d8cadccee8d60bb1b6064820152608401610319565b5f805f855f01518660200151876040015188608001518960600151604051602001611b8d9796959493929190612480565b6040516020818303038152906040529050600281604051611bae91906124f6565b602060405180830381855afa158015611bc9573d5f803e3d5ffd5b5050506040513d601f19601f82011682018060405250810190611bec9190612120565b94909350915050565b5f8181527fe92546d698950ddd38910d2e15ed1d923cd0a7b3dde9e2a6a3f380565559cb076020526040812060030180545f80516020612557833981519152916001600160401b0390911690819084611c4d83612511565b91906101000a8154816001600160401b0302191690836001600160401b03160217905550508092505050919050565b60017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f0055565b5f805f808451602714611cd45784516040516241835b60e31b8152600481019190915260276024820152604401610319565b50505050602081015160228201516026830151604690930151919390929190565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054600160401b900460ff1661076857604051631afcd79f60e31b815260040160405180910390fd5b611d46611cf5565b611d4e611d70565b611d56611d80565b61077381611d88565b611d67611cf5565b61077381611df4565b611d78611cf5565b610768611dfc565b610768611cf5565b611d90611cf5565b80355f8051602061255783398151915290815560208201357fe92546d698950ddd38910d2e15ed1d923cd0a7b3dde9e2a6a3f380565559cb0155611dda6060830160408401612536565b600291909101805460ff191660ff90921691909117905550565b610b18611cf5565b611c7c611cf5565b508054611e109061204a565b5f825580601f10611e1f575050565b601f0160209004905f5260205f209081019061077391905b80821115611e4a575f8155600101611e37565b5090565b5f60208284031215611e5e575f80fd5b5035919050565b80356001600160401b0381168114611e7b575f80fd5b919050565b634e487b7160e01b5f52604160045260245ffd5b604051606081016001600160401b0381118282101715611eb657611eb6611e80565b60405290565b604051601f8201601f191681016001600160401b0381118282101715611ee457611ee4611e80565b604052919050565b5f6001600160401b03821115611f0457611f04611e80565b50601f01601f191660200190565b5f805f8060808587031215611f25575f80fd5b611f2e85611e65565b935060208501359250611f4360408601611e65565b915060608501356001600160401b03811115611f5d575f80fd5b8501601f81018713611f6d575f80fd5b8035611f80611f7b82611eec565b611ebc565b818152886020838501011115611f94575f80fd5b816020840160208301375f6020838301015280935050505092959194509250565b5f60208284031215611fc5575f80fd5b813563ffffffff81168114611fd8575f80fd5b9392505050565b6001600160a01b0381168114610773575f80fd5b5f808284036080811215612005575f80fd5b6060811215612012575f80fd5b50829150606083013561202481611fdf565b809150509250929050565b5f6020828403121561203f575f80fd5b8135611fd881611fdf565b600181811c9082168061205e57607f821691505b60208210810361207c57634e487b7160e01b5f52602260045260245ffd5b50919050565b634e487b7160e01b5f52602160045260245ffd5b5f60208083525f84546120a88161204a565b806020870152604060018084165f81146120c957600181146120e557612112565b60ff19851660408a0152604084151560051b8a01019550612112565b895f5260205f205f5b858110156121095781548b82018601529083019088016120ee565b8a016040019650505b509398975050505050505050565b5f60208284031215612130575f80fd5b5051919050565b60208082526027908201527f56616c696461746f724d616e616765723a20696e76616c69642076616c6964616040820152661d1a5bdb88125160ca1b606082015260800190565b634e487b7160e01b5f52601160045260245ffd5b808201808211156121a5576121a561217e565b92915050565b601f82111561039b57805f5260205f20601f840160051c810160208510156121d05750805b601f840160051c820191505b818110156121ef575f81556001016121dc565b5050505050565b81516001600160401b0381111561220f5761220f611e80565b6122238161221d845461204a565b846121ab565b602080601f831160018114612256575f841561223f5750858301515b5f19600386901b1c1916600185901b1785556122ad565b5f85815260208120601f198616915b8281101561228457888601518255948401946001909101908401612265565b50858210156122a157878501515f19600388901b60f8161c191681555b505060018460011b0185555b505050505050565b5f5b838110156122cf5781810151838201526020016122b7565b50505f910152565b602081525f82518060208401526122f58160408501602087016122b5565b601f01601f19169190910160400192915050565b80518015158114611e7b575f80fd5b5f8060408385031215612329575f80fd5b82516001600160401b038082111561233f575f80fd5b9084019060608287031215612352575f80fd5b61235a611e94565b8251815260208084015161236d81611fdf565b82820152604084015183811115612382575f80fd5b80850194505087601f850112612396575f80fd5b835192506123a6611f7b84611eec565b83815288828587010111156123b9575f80fd5b6123c8848383018488016122b5565b806040840152508195506123dd818801612309565b9450505050509250929050565b818103818111156121a5576121a561217e565b6001600160401b0381811683821601908082111561241d5761241d61217e565b5092915050565b6001600160401b038181168382160280821691908281146124475761244761217e565b505092915050565b5f6001600160401b038084168061247457634e487b7160e01b5f52601260045260245ffd5b92169190910492915050565b61ffff60f01b8860f01b16815263ffffffff60e01b8760e01b1660028201528560068201528460268201525f6001600160401b0360c01b808660c01b16604684015284516124d581604e8601602089016122b5565b60c09490941b1691909201604e810191909152605601979650505050505050565b5f82516125078184602087016122b5565b9190910192915050565b5f6001600160401b0380831681810361252c5761252c61217e565b6001019392505050565b5f60208284031215612546575f80fd5b813560ff81168114611fd8575f80fdfee92546d698950ddd38910d2e15ed1d923cd0a7b3dde9e2a6a3f380565559cb00a164736f6c6343000819000a", } // PoAValidatorManagerABI is the input ABI used to generate the binding from.