ETH Price: $2,101.47 (+3.78%)

Contract

0xEFc2bFA5DaB062d0Ee4C9dd955536E44D5cE4Db5
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

More Info

Private Name Tags

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To

There are no matching entries

1 Internal Transaction found.

Latest 1 internal transaction

Advanced mode:
Parent Transaction Hash Method Block
From
To
0x6118d061242987012026-01-23 16:33:1167 days ago1769185991  Contract Creation0 ETH
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
CaliberAccountingCCQ

Compiler Version
v0.8.28+commit.7893614a

Optimization Enabled:
Yes with 150 runs

Other Settings:
cancun EvmVersion
// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.28;

import {IWormhole} from "@wormhole/sdk/interfaces/IWormhole.sol";
import {
    EthCallQueryResponse,
    PerChainQueryResponse,
    QueryResponse,
    QueryResponseLib
} from "@wormhole/sdk/libraries/QueryResponse.sol";
import {GuardianSignature} from "@wormhole/sdk/libraries/VaaLib.sol";

import {ICaliberMailbox} from "../interfaces/ICaliberMailbox.sol";
import {Errors} from "./Errors.sol";

library CaliberAccountingCCQ {
    function decodeAndVerifyQueryResponse(
        address wormhole,
        bytes calldata response,
        GuardianSignature[] calldata signatures
    ) external view returns (QueryResponse memory ret) {
        return QueryResponseLib.decodeAndVerifyQueryResponseCd(
            wormhole, response, signatures, IWormhole(wormhole).getCurrentGuardianSetIndex()
        );
    }

    /// @dev Parses the PerChainQueryResponse and retrieves the accounting data for the given caliber mailbox.
    /// @param pcr The PerChainQueryResponse containing the query results.
    /// @param caliberMailbox The address of the queried caliber mailbox.
    /// @return data The accounting data for the given caliber mailbox
    /// @return responseTimestamp The timestamp of the response.
    function getAccountingData(PerChainQueryResponse memory pcr, address caliberMailbox)
        external
        pure
        returns (ICaliberMailbox.SpokeCaliberAccountingData memory, uint256)
    {
        EthCallQueryResponse memory eqr = QueryResponseLib.decodeEthCallQueryResponse(pcr);

        // Validate that only one result is returned.
        if (eqr.results.length != 1) {
            revert Errors.UnexpectedResultLength();
        }

        // Validate addresses and function signatures.
        address[] memory validAddresses = new address[](1);
        bytes4[] memory validFunctionSignatures = new bytes4[](1);
        validAddresses[0] = caliberMailbox;
        validFunctionSignatures[0] = ICaliberMailbox.getSpokeCaliberAccountingData.selector;
        QueryResponseLib.validateEthCallRecord(eqr.results[0], validAddresses, validFunctionSignatures);

        return (
            abi.decode(eqr.results[0].result, (ICaliberMailbox.SpokeCaliberAccountingData)),
            eqr.blockTime / QueryResponseLib.MICROSECONDS_PER_SECOND
        );
    }
}

// SPDX-License-Identifier: Apache 2

pragma solidity ^0.8.0;

interface IWormhole {
  struct GuardianSet {
    address[] keys;
    uint32 expirationTime;
  }

  struct Signature {
    bytes32 r;
    bytes32 s;
    uint8 v;
    uint8 guardianIndex;
  }

  struct VM {
    uint8 version;
    uint32 timestamp;
    uint32 nonce;
    uint16 emitterChainId;
    bytes32 emitterAddress;
    uint64 sequence;
    uint8 consistencyLevel;
    bytes payload;
    uint32 guardianSetIndex;
    Signature[] signatures;
    bytes32 hash;
  }

  struct ContractUpgrade {
    bytes32 module;
    uint8 action;
    uint16 chain;
    address newContract;
  }

  struct GuardianSetUpgrade {
    bytes32 module;
    uint8 action;
    uint16 chain;
    GuardianSet newGuardianSet;
    uint32 newGuardianSetIndex;
  }

  struct SetMessageFee {
    bytes32 module;
    uint8 action;
    uint16 chain;
    uint256 messageFee;
  }

  struct TransferFees {
    bytes32 module;
    uint8 action;
    uint16 chain;
    uint256 amount;
    bytes32 recipient;
  }

  struct RecoverChainId {
    bytes32 module;
    uint8 action;
    uint256 evmChainId;
    uint16 newChainId;
  }

  event LogMessagePublished(
    address indexed sender,
    uint64 sequence,
    uint32 nonce,
    bytes payload,
    uint8 consistencyLevel
  );

  event ContractUpgraded(address indexed oldContract, address indexed newContract);

  event GuardianSetAdded(uint32 indexed index);

  function publishMessage(uint32 nonce, bytes memory payload, uint8 consistencyLevel)
    external
    payable
    returns (uint64 sequence);

  function initialize() external;

  function parseAndVerifyVM(bytes calldata encodedVM)
    external
    view
    returns (VM memory vm, bool valid, string memory reason);

  function verifyVM(VM memory vm) external view returns (bool valid, string memory reason);

  function verifySignatures(
    bytes32 hash,
    Signature[] memory signatures,
    GuardianSet memory guardianSet
  ) external pure returns (bool valid, string memory reason);

  function parseVM(bytes memory encodedVM) external pure returns (VM memory vm);

  function quorum(
    uint256 numGuardians
  ) external pure returns (uint256 numSignaturesRequiredForQuorum);

  function getGuardianSet(uint32 index) external view returns (GuardianSet memory);

  function getCurrentGuardianSetIndex() external view returns (uint32);

  function getGuardianSetExpiry() external view returns (uint32);

  function governanceActionIsConsumed(bytes32 hash) external view returns (bool);

  function isInitialized(address impl) external view returns (bool);

  function chainId() external view returns (uint16);

  function isFork() external view returns (bool);

  function governanceChainId() external view returns (uint16);

  function governanceContract() external view returns (bytes32);

  function messageFee() external view returns (uint256);

  function evmChainId() external view returns (uint256);

  function nextSequence(address emitter) external view returns (uint64);

  function parseContractUpgrade(
    bytes memory encodedUpgrade
  ) external pure returns (ContractUpgrade memory cu);

  function parseGuardianSetUpgrade(
    bytes memory encodedUpgrade
  ) external pure returns (GuardianSetUpgrade memory gsu);

  function parseSetMessageFee(
    bytes memory encodedSetMessageFee
  ) external pure returns (SetMessageFee memory smf);

  function parseTransferFees(
    bytes memory encodedTransferFees
  ) external pure returns (TransferFees memory tf);

  function parseRecoverChainId(
    bytes memory encodedRecoverChainId
  ) external pure returns (RecoverChainId memory rci);

  function submitContractUpgrade(bytes memory _vm) external;

  function submitSetMessageFee(bytes memory _vm) external;

  function submitNewGuardianSet(bytes memory _vm) external;

  function submitTransferFees(bytes memory _vm) external;

  function submitRecoverChainId(bytes memory _vm) external;
}

// SPDX-License-Identifier: Apache 2
pragma solidity ^0.8.4;

import {BytesParsing}                   from "wormhole-sdk/libraries/BytesParsing.sol";
import {CoreBridgeLib}                  from "wormhole-sdk/libraries/CoreBridge.sol";
import {GuardianSignature}              from "wormhole-sdk/libraries/VaaLib.sol";
import {eagerAnd, eagerOr, keccak256Cd} from "wormhole-sdk/Utils.sol";

library QueryType {
  error UnsupportedQueryType(uint8 received);

  //Solidity enums don't permit custom values (i.e. can't start from 1)
  //Also invalid enum conversions result in panics and manual range checking requires assembly
  //  to avoid superfluous double checking.
  //So we're sticking with uint8 constants instead.
  uint8 internal constant ETH_CALL = 1;
  uint8 internal constant ETH_CALL_BY_TIMESTAMP = 2;
  uint8 internal constant ETH_CALL_WITH_FINALITY = 3;
  uint8 internal constant SOLANA_ACCOUNT = 4;
  uint8 internal constant SOLANA_PDA = 5;

  //emulate type(enum).min/max for external consumers (mainly tests)
  function min() internal pure returns (uint8) { return ETH_CALL; }
  function max() internal pure returns (uint8) { return SOLANA_PDA; }

  function checkValid(uint8 queryType) internal pure {
    //slightly more gas efficient than calling `isValid`
    if (eagerOr(queryType == 0, queryType > SOLANA_PDA))
      revert UnsupportedQueryType(queryType);
  }

  function isValid(uint8 queryType) internal pure returns (bool) {
    //see docs/Optimization.md why `< CONST + 1` rather than `<= CONST`
    //see docs/Optimization.md for rationale behind `eagerAnd`
    return eagerAnd(queryType > 0, queryType < SOLANA_PDA + 1);
  }
}

struct QueryResponse {
  uint8 version;
  uint16 senderChainId;
  uint32 nonce;
  bytes requestId; // 65 byte sig for off-chain, 32 byte vaaHash for on-chain
  PerChainQueryResponse[] responses;
}

struct PerChainQueryResponse {
  uint16 chainId;
  uint8 queryType;
  bytes request;
  bytes response;
}

struct EthCallQueryResponse {
  bytes requestBlockId;
  uint64 blockNum;
  uint64 blockTime;
  bytes32 blockHash;
  EthCallRecord[] results;
}

struct EthCallByTimestampQueryResponse {
  bytes requestTargetBlockIdHint;
  bytes requestFollowingBlockIdHint;
  uint64 requestTargetTimestamp;
  uint64 targetBlockNum;
  uint64 targetBlockTime;
  uint64 followingBlockNum;
  bytes32 targetBlockHash;
  bytes32 followingBlockHash;
  uint64 followingBlockTime;
  EthCallRecord[] results;
}

struct EthCallWithFinalityQueryResponse {
  bytes requestBlockId;
  bytes requestFinality;
  uint64 blockNum;
  uint64 blockTime;
  bytes32 blockHash;
  EthCallRecord[] results;
}

struct EthCallRecord {
  address contractAddress;
  bytes callData;
  bytes result;
}

struct SolanaAccountQueryResponse {
  bytes requestCommitment;
  uint64 requestMinContextSlot;
  uint64 requestDataSliceOffset;
  uint64 requestDataSliceLength;
  uint64 slotNumber;
  uint64 blockTime;
  bytes32 blockHash;
  SolanaAccountResult[] results;
}

struct SolanaAccountResult {
  bytes32 account;
  uint64 lamports;
  uint64 rentEpoch;
  bool executable;
  bytes32 owner;
  bytes data;
}

struct SolanaPdaQueryResponse {
  bytes requestCommitment;
  uint64 requestMinContextSlot;
  uint64 requestDataSliceOffset;
  uint64 requestDataSliceLength;
  uint64 slotNumber;
  uint64 blockTime;
  bytes32 blockHash;
  SolanaPdaResult[] results;
}

struct SolanaPdaResult {
  bytes32 programId;
  bytes[] seeds;
  bytes32 account;
  uint64 lamports;
  uint64 rentEpoch;
  bool executable;
  bytes32 owner;
  bytes data;
  uint8 bump;
}

//QueryResponse is a library that implements the decoding and verification of
//  Cross Chain Query (CCQ) responses.
//
//For a detailed discussion of these query responses, please see the white paper:
//  https://github.com/wormhole-foundation/wormhole/blob/main/whitepapers/0013_ccq.md
//
//We only implement Cd and Mem decoding variants for the QueryResponse struct itself because all
//  further decoding will have to operate on the memory bytes anyway since there's no way in plain
//  Solidity to have structs with mixed data location, i.e. a struct in memory that references bytes
//  in calldata.
//  This will at least help cut down the gas cost of decoding/slicing the outer most layer.
library QueryResponseLib {
  using BytesParsing for bytes;

  error WrongQueryType(uint8 received, uint8 expected);
  error InvalidResponseVersion();
  error VersionMismatch();
  error ZeroQueries();
  error NumberOfResponsesMismatch();
  error ChainIdMismatch();
  error RequestTypeMismatch();
  error UnexpectedNumberOfResults();
  error InvalidPayloadLength(uint256 received, uint256 expected);
  error InvalidContractAddress();
  error InvalidFunctionSignature();
  error InvalidChainId();
  error StaleBlockNum();
  error StaleBlockTime();
  error VerificationFailed();

  bytes internal constant RESPONSE_PREFIX = bytes("query_response_0000000000000000000|");
  uint8 internal constant VERSION = 1;
  uint64 internal constant MICROSECONDS_PER_SECOND = 1_000_000;

  function calcPrefixedResponseHashCd(bytes calldata response) internal pure returns (bytes32) {
    return calcPrefixedResponseHash(keccak256Cd(response));
  }

  function calcPrefixedResponseHashMem(bytes memory response) internal pure returns (bytes32) {
    return calcPrefixedResponseHash(keccak256(response));
  }

  function calcPrefixedResponseHash(bytes32 responseHash) internal pure returns (bytes32) {
    return keccak256(abi.encodePacked(RESPONSE_PREFIX, responseHash));
  }

  // -------- decodeAndVerifyQueryResponse --------

  // ---- guardian set index variants
  // will look up the guardian set internally and also try to verify against the latest
  //   guardian set, if the specified guardian set is expired.

  function decodeAndVerifyQueryResponseCd(
    address wormhole,
    bytes calldata response,
    GuardianSignature[] calldata guardianSignatures,
    uint32 guardianSetIndex
  ) internal view returns (QueryResponse memory ret) {
    verifyQueryResponseCd(wormhole, response, guardianSignatures, guardianSetIndex);
    return decodeQueryResponseCd(response);
  }

  function decodeAndVerifyQueryResponseMem(
    address wormhole,
    bytes memory response,
    GuardianSignature[] memory guardianSignatures,
    uint32 guardianSetIndex
  ) internal view returns (QueryResponse memory ret) {
    verifyQueryResponseMem(wormhole, response, guardianSignatures, guardianSetIndex);
    return decodeQueryResponseMem(response);
  }

  function verifyQueryResponseCd(
    address wormhole,
    bytes calldata response,
    GuardianSignature[] calldata guardianSignatures,
    uint32 guardianSetIndex
  ) internal view {
    if (!CoreBridgeLib.isVerifiedByQuorumCd(
      wormhole,
      calcPrefixedResponseHashCd(response),
      guardianSignatures,
      guardianSetIndex
    ))
      revert VerificationFailed();
  }

  function verifyQueryResponseMem(
    address wormhole,
    bytes memory response,
    GuardianSignature[] memory guardianSignatures,
    uint32 guardianSetIndex
  ) internal view {
    if (!CoreBridgeLib.isVerifiedByQuorumMem(
      wormhole,
      calcPrefixedResponseHashMem(response),
      guardianSignatures,
      guardianSetIndex
    ))
      revert VerificationFailed();
  }

  // ---- guardian address variants
  // will only try to verify against the specified guardian addresses only

  function decodeAndVerifyQueryResponseCd(
    bytes calldata response,
    GuardianSignature[] calldata guardianSignatures,
    address[] memory guardians
  ) internal pure returns (QueryResponse memory ret) {
    verifyQueryResponseCd(response, guardianSignatures, guardians);
    return decodeQueryResponseCd(response);
  }

  function decodeAndVerifyQueryResponseMem(
    bytes memory response,
    GuardianSignature[] memory guardianSignatures,
    address[] memory guardians
  ) internal pure returns (QueryResponse memory ret) {
    verifyQueryResponseMem(response, guardianSignatures, guardians);
    return decodeQueryResponseMem(response);
  }

  function verifyQueryResponseCd(
    bytes calldata response,
    GuardianSignature[] calldata guardianSignatures,
    address[] memory guardians
  ) internal pure {
    if (!CoreBridgeLib.isVerifiedByQuorumCd(
      calcPrefixedResponseHashCd(response),
      guardianSignatures,
      guardians
    ))
      revert VerificationFailed();
  }

  function verifyQueryResponseMem(
    bytes memory response,
    GuardianSignature[] memory guardianSignatures,
    address[] memory guardians
  ) internal pure {
    if (!CoreBridgeLib.isVerifiedByQuorumMem(
      calcPrefixedResponseHashMem(response),
      guardianSignatures,
      guardians
    ))
      revert VerificationFailed();
  }

  // -------- decode functions --------

  function decodeQueryResponseCd(
    bytes calldata response
  ) internal pure returns (QueryResponse memory ret) { unchecked {
    uint offset;

    (ret.version, offset) = response.asUint8CdUnchecked(offset);
    if (ret.version != VERSION)
      revert InvalidResponseVersion();

    (ret.senderChainId, offset) = response.asUint16CdUnchecked(offset);

    //for off-chain requests (chainID zero), the requestId is the 65 byte signature
    //for on-chain requests, it is the 32 byte VAA hash
    (ret.requestId, offset) = response.sliceCdUnchecked(offset, ret.senderChainId == 0 ? 65 : 32);

    uint32 queryReqLen;
    (queryReqLen, offset) = response.asUint32CdUnchecked(offset);
    uint reqOff = offset;

    {
      uint8 version;
      (version, reqOff) = response.asUint8CdUnchecked(reqOff);
      if (version != ret.version)
        revert VersionMismatch();
    }

    (ret.nonce, reqOff) = response.asUint32CdUnchecked(reqOff);

    uint8 numPerChainQueries;
    (numPerChainQueries, reqOff) = response.asUint8CdUnchecked(reqOff);

    //a valid query request must have at least one per-chain-query
    if (numPerChainQueries == 0)
      revert ZeroQueries();

    //The response starts after the request.
    uint respOff = offset + queryReqLen;
    uint startOfResponse = respOff;

    uint8 respNumPerChainQueries;
    (respNumPerChainQueries, respOff) = response.asUint8CdUnchecked(respOff);
    if (respNumPerChainQueries != numPerChainQueries)
      revert NumberOfResponsesMismatch();

    ret.responses = new PerChainQueryResponse[](numPerChainQueries);

    //walk through the requests and responses in lock step.
    for (uint i; i < numPerChainQueries; ++i) {
      (ret.responses[i].chainId, reqOff) = response.asUint16CdUnchecked(reqOff);
      uint16 respChainId;
      (respChainId, respOff) = response.asUint16CdUnchecked(respOff);
      if (respChainId != ret.responses[i].chainId)
        revert ChainIdMismatch();

      (ret.responses[i].queryType, reqOff) = response.asUint8CdUnchecked(reqOff);
      QueryType.checkValid(ret.responses[i].queryType);
      uint8 respQueryType;
      (respQueryType, respOff) = response.asUint8CdUnchecked(respOff);
      if (respQueryType != ret.responses[i].queryType)
        revert RequestTypeMismatch();

      (ret.responses[i].request, reqOff) = response.sliceUint32PrefixedCdUnchecked(reqOff);

      (ret.responses[i].response, respOff) = response.sliceUint32PrefixedCdUnchecked(respOff);
    }

    //end of request body should align with start of response body
    if (startOfResponse != reqOff)
      revert InvalidPayloadLength(startOfResponse, reqOff);

    _checkLength(response.length, respOff);
    return ret;
  }}

  function decodeQueryResponseMem(
    bytes memory response
  ) internal pure returns (QueryResponse memory ret) { unchecked {
    uint offset;

    (ret.version, offset) = response.asUint8MemUnchecked(offset);
    if (ret.version != VERSION)
      revert InvalidResponseVersion();

    (ret.senderChainId, offset) = response.asUint16MemUnchecked(offset);

    //for off-chain requests (chainID zero), the requestId is the 65 byte signature
    //for on-chain requests, it is the 32 byte VAA hash
    (ret.requestId, offset) = response.sliceMemUnchecked(offset, ret.senderChainId == 0 ? 65 : 32);

    uint32 queryReqLen;
    (queryReqLen, offset) = response.asUint32MemUnchecked(offset);
    uint reqOff = offset;

    {
      uint8 version;
      (version, reqOff) = response.asUint8MemUnchecked(reqOff);
      if (version != ret.version)
        revert VersionMismatch();
    }

    (ret.nonce, reqOff) = response.asUint32MemUnchecked(reqOff);

    uint8 numPerChainQueries;
    (numPerChainQueries, reqOff) = response.asUint8MemUnchecked(reqOff);

    //a valid query request must have at least one per-chain-query
    if (numPerChainQueries == 0)
      revert ZeroQueries();

    //The response starts after the request.
    uint respOff = offset + queryReqLen;
    uint startOfResponse = respOff;

    uint8 respNumPerChainQueries;
    (respNumPerChainQueries, respOff) = response.asUint8MemUnchecked(respOff);
    if (respNumPerChainQueries != numPerChainQueries)
      revert NumberOfResponsesMismatch();

    ret.responses = new PerChainQueryResponse[](numPerChainQueries);

    //walk through the requests and responses in lock step.
    for (uint i; i < numPerChainQueries; ++i) {
      (ret.responses[i].chainId, reqOff) = response.asUint16MemUnchecked(reqOff);
      uint16 respChainId;
      (respChainId, respOff) = response.asUint16MemUnchecked(respOff);
      if (respChainId != ret.responses[i].chainId)
        revert ChainIdMismatch();

      (ret.responses[i].queryType, reqOff) = response.asUint8MemUnchecked(reqOff);
      QueryType.checkValid(ret.responses[i].queryType);
      uint8 respQueryType;
      (respQueryType, respOff) = response.asUint8MemUnchecked(respOff);
      if (respQueryType != ret.responses[i].queryType)
        revert RequestTypeMismatch();

      (ret.responses[i].request, reqOff) = response.sliceUint32PrefixedMemUnchecked(reqOff);

      (ret.responses[i].response, respOff) = response.sliceUint32PrefixedMemUnchecked(respOff);
    }

    //end of request body should align with start of response body
    if (startOfResponse != reqOff)
      revert InvalidPayloadLength(startOfResponse, reqOff);

    _checkLength(response.length, respOff);
    return ret;
  }}

  function decodeEthCallQueryResponse(
    PerChainQueryResponse memory pcr
  ) internal pure returns (EthCallQueryResponse memory ret) { unchecked {
    if (pcr.queryType != QueryType.ETH_CALL)
      revert WrongQueryType(pcr.queryType, QueryType.ETH_CALL);

    uint reqOff;
    uint respOff;

    uint8 numBatchCallData;
    (ret.requestBlockId, reqOff) = pcr.request.sliceUint32PrefixedMemUnchecked(reqOff);
    (numBatchCallData,   reqOff) = pcr.request.asUint8MemUnchecked(reqOff);

    uint8 respNumResults;
    (ret.blockNum,   respOff) = pcr.response.asUint64MemUnchecked(respOff);
    (ret.blockHash,  respOff) = pcr.response.asBytes32MemUnchecked(respOff);
    (ret.blockTime,  respOff) = pcr.response.asUint64MemUnchecked(respOff);
    (respNumResults, respOff) = pcr.response.asUint8MemUnchecked(respOff);

    if (respNumResults != numBatchCallData)
      revert UnexpectedNumberOfResults();

    ret.results = new EthCallRecord[](numBatchCallData);

    //walk through the call inputs and outputs in lock step.
    for (uint i; i < numBatchCallData; ++i) {
      EthCallRecord memory ecr = ret.results[i];
      (ecr.contractAddress, reqOff) = pcr.request.asAddressMemUnchecked(reqOff);
      (ecr.callData,        reqOff) = pcr.request.sliceUint32PrefixedMemUnchecked(reqOff);

      (ecr.result, respOff) = pcr.response.sliceUint32PrefixedMemUnchecked(respOff);
    }

    _checkLength(pcr.request.length, reqOff);
    _checkLength(pcr.response.length, respOff);
    return ret;
  }}

  function decodeEthCallByTimestampQueryResponse(
    PerChainQueryResponse memory pcr
  ) internal pure returns (EthCallByTimestampQueryResponse memory ret) { unchecked {
    if (pcr.queryType != QueryType.ETH_CALL_BY_TIMESTAMP)
      revert WrongQueryType(pcr.queryType, QueryType.ETH_CALL_BY_TIMESTAMP);

    uint reqOff;
    uint respOff;

    uint8 numBatchCallData;
    (ret.requestTargetTimestamp,      reqOff) = pcr.request.asUint64MemUnchecked(reqOff);
    (ret.requestTargetBlockIdHint,    reqOff) = pcr.request.sliceUint32PrefixedMemUnchecked(reqOff);
    (ret.requestFollowingBlockIdHint, reqOff) = pcr.request.sliceUint32PrefixedMemUnchecked(reqOff);
    (numBatchCallData,                reqOff) = pcr.request.asUint8MemUnchecked(reqOff);

    uint8 respNumResults;
    (ret.targetBlockNum,     respOff) = pcr.response.asUint64MemUnchecked(respOff);
    (ret.targetBlockHash,    respOff) = pcr.response.asBytes32MemUnchecked(respOff);
    (ret.targetBlockTime,    respOff) = pcr.response.asUint64MemUnchecked(respOff);
    (ret.followingBlockNum,  respOff) = pcr.response.asUint64MemUnchecked(respOff);
    (ret.followingBlockHash, respOff) = pcr.response.asBytes32MemUnchecked(respOff);
    (ret.followingBlockTime, respOff) = pcr.response.asUint64MemUnchecked(respOff);
    (respNumResults,         respOff) = pcr.response.asUint8MemUnchecked(respOff);

    if (respNumResults != numBatchCallData)
      revert UnexpectedNumberOfResults();

    ret.results = new EthCallRecord[](numBatchCallData);

    //walk through the call inputs and outputs in lock step.
    for (uint i; i < numBatchCallData; ++i) {
      EthCallRecord memory ecr = ret.results[i];
      (ecr.contractAddress, reqOff) = pcr.request.asAddressMemUnchecked(reqOff);
      (ecr.callData,        reqOff) = pcr.request.sliceUint32PrefixedMemUnchecked(reqOff);

      (ecr.result, respOff) = pcr.response.sliceUint32PrefixedMemUnchecked(respOff);
    }

    _checkLength(pcr.request.length, reqOff);
    _checkLength(pcr.response.length, respOff);
  }}

  function decodeEthCallWithFinalityQueryResponse(
    PerChainQueryResponse memory pcr
  ) internal pure returns (EthCallWithFinalityQueryResponse memory ret) { unchecked {
    if (pcr.queryType != QueryType.ETH_CALL_WITH_FINALITY)
      revert WrongQueryType(pcr.queryType, QueryType.ETH_CALL_WITH_FINALITY);

    uint reqOff;
    uint respOff;

    uint8 numBatchCallData;
    (ret.requestBlockId,  reqOff) = pcr.request.sliceUint32PrefixedMemUnchecked(reqOff);
    (ret.requestFinality, reqOff) = pcr.request.sliceUint32PrefixedMemUnchecked(reqOff);
    (numBatchCallData,    reqOff) = pcr.request.asUint8MemUnchecked(reqOff);

    uint8 respNumResults;
    (ret.blockNum,   respOff) = pcr.response.asUint64MemUnchecked(respOff);
    (ret.blockHash,  respOff) = pcr.response.asBytes32MemUnchecked(respOff);
    (ret.blockTime,  respOff) = pcr.response.asUint64MemUnchecked(respOff);
    (respNumResults, respOff) = pcr.response.asUint8MemUnchecked(respOff);

    if (respNumResults != numBatchCallData)
      revert UnexpectedNumberOfResults();

    ret.results = new EthCallRecord[](numBatchCallData);

    //walk through the call inputs and outputs in lock step.
    for (uint i; i < numBatchCallData; ++i) {
      EthCallRecord memory ecr = ret.results[i];
      (ecr.contractAddress, reqOff) = pcr.request.asAddressMemUnchecked(reqOff);
      (ecr.callData,        reqOff) = pcr.request.sliceUint32PrefixedMemUnchecked(reqOff);

      (ecr.result, respOff) = pcr.response.sliceUint32PrefixedMemUnchecked(respOff);
    }

    _checkLength(pcr.request.length, reqOff);
    _checkLength(pcr.response.length, respOff);
  }}

  function decodeSolanaAccountQueryResponse(
    PerChainQueryResponse memory pcr
  ) internal pure returns (SolanaAccountQueryResponse memory ret) { unchecked {
    if (pcr.queryType != QueryType.SOLANA_ACCOUNT)
      revert WrongQueryType(pcr.queryType, QueryType.SOLANA_ACCOUNT);

    uint reqOff;
    uint respOff;

    uint8 numAccounts;
    (ret.requestCommitment,      reqOff) = pcr.request.sliceUint32PrefixedMemUnchecked(reqOff);
    (ret.requestMinContextSlot,  reqOff) = pcr.request.asUint64MemUnchecked(reqOff);
    (ret.requestDataSliceOffset, reqOff) = pcr.request.asUint64MemUnchecked(reqOff);
    (ret.requestDataSliceLength, reqOff) = pcr.request.asUint64MemUnchecked(reqOff);
    (numAccounts,                reqOff) = pcr.request.asUint8MemUnchecked(reqOff);

    uint8 respNumResults;
    (ret.slotNumber, respOff) = pcr.response.asUint64MemUnchecked(respOff);
    (ret.blockTime,  respOff) = pcr.response.asUint64MemUnchecked(respOff);
    (ret.blockHash,  respOff) = pcr.response.asBytes32MemUnchecked(respOff);
    (respNumResults, respOff) = pcr.response.asUint8MemUnchecked(respOff);

    if (respNumResults != numAccounts)
      revert UnexpectedNumberOfResults();

    ret.results = new SolanaAccountResult[](numAccounts);

    //walk through the call inputs and outputs in lock step.
    for (uint i; i < numAccounts; ++i) {
      (ret.results[i].account, reqOff) = pcr.request.asBytes32MemUnchecked(reqOff);

      (ret.results[i].lamports,   respOff) = pcr.response.asUint64MemUnchecked(respOff);
      (ret.results[i].rentEpoch,  respOff) = pcr.response.asUint64MemUnchecked(respOff);
      (ret.results[i].executable, respOff) = pcr.response.asBoolMemUnchecked(respOff);
      (ret.results[i].owner,      respOff) = pcr.response.asBytes32MemUnchecked(respOff);
      (ret.results[i].data,       respOff) = pcr.response.sliceUint32PrefixedMemUnchecked(respOff);
    }

    _checkLength(pcr.request.length, reqOff);
    _checkLength(pcr.response.length, respOff);
  }}

  function decodeSolanaPdaQueryResponse(
    PerChainQueryResponse memory pcr
  ) internal pure returns (SolanaPdaQueryResponse memory ret) { unchecked {
    if (pcr.queryType != QueryType.SOLANA_PDA)
      revert WrongQueryType(pcr.queryType, QueryType.SOLANA_PDA);

    uint reqOff;
    uint respOff;

    (ret.requestCommitment,      reqOff) = pcr.request.sliceUint32PrefixedMemUnchecked(reqOff);
    (ret.requestMinContextSlot,  reqOff) = pcr.request.asUint64MemUnchecked(reqOff);
    (ret.requestDataSliceOffset, reqOff) = pcr.request.asUint64MemUnchecked(reqOff);
    (ret.requestDataSliceLength, reqOff) = pcr.request.asUint64MemUnchecked(reqOff);

    uint8 numPdas;
    (numPdas, reqOff) = pcr.request.asUint8MemUnchecked(reqOff);

    (ret.slotNumber, respOff) = pcr.response.asUint64MemUnchecked(respOff);
    (ret.blockTime,  respOff) = pcr.response.asUint64MemUnchecked(respOff);
    (ret.blockHash,  respOff) = pcr.response.asBytes32MemUnchecked(respOff);

    uint8 respNumResults;
    (respNumResults, respOff) = pcr.response.asUint8MemUnchecked(respOff);
    if (respNumResults != numPdas)
      revert UnexpectedNumberOfResults();

    ret.results = new SolanaPdaResult[](numPdas);

    //walk through the call inputs and outputs in lock step.
    for (uint i; i < numPdas; ++i) {
      (ret.results[i].programId, reqOff) = pcr.request.asBytes32MemUnchecked(reqOff);

      uint8 reqNumSeeds;
      (reqNumSeeds, reqOff) = pcr.request.asUint8MemUnchecked(reqOff);
      ret.results[i].seeds = new bytes[](reqNumSeeds);
      for (uint s; s < reqNumSeeds; ++s)
        (ret.results[i].seeds[s], reqOff) = pcr.request.sliceUint32PrefixedMemUnchecked(reqOff);

      (ret.results[i].account,    respOff) = pcr.response.asBytes32MemUnchecked(respOff);
      (ret.results[i].bump,       respOff) = pcr.response.asUint8MemUnchecked(respOff);
      (ret.results[i].lamports,   respOff) = pcr.response.asUint64MemUnchecked(respOff);
      (ret.results[i].rentEpoch,  respOff) = pcr.response.asUint64MemUnchecked(respOff);
      (ret.results[i].executable, respOff) = pcr.response.asBoolMemUnchecked(respOff);
      (ret.results[i].owner,      respOff) = pcr.response.asBytes32MemUnchecked(respOff);
      (ret.results[i].data,       respOff) = pcr.response.sliceUint32PrefixedMemUnchecked(respOff);
    }

    _checkLength(pcr.request.length, reqOff);
    _checkLength(pcr.response.length, respOff);
  }}

  function validateBlockTime(
    uint64 blockTimeInMicroSeconds,
    uint256 minBlockTimeInSeconds
  ) internal pure {
    uint256 blockTimeInSeconds = blockTimeInMicroSeconds / MICROSECONDS_PER_SECOND; // Rounds down

    if (blockTimeInSeconds < minBlockTimeInSeconds)
      revert StaleBlockTime();
  }

  function validateBlockNum(uint64 blockNum, uint256 minBlockNum) internal pure {
    if (blockNum < minBlockNum)
      revert StaleBlockNum();
  }

  function validateChainId(
    uint16 chainId,
    uint16[] memory validChainIds
  ) internal pure { unchecked {
    uint len = validChainIds.length;
    for (uint i; i < len; ++i)
      if (chainId == validChainIds[i])
        return;

    revert InvalidChainId();
  }}

  function validateEthCallRecord(
    EthCallRecord[] memory ecrs,
    address[] memory validContractAddresses,
    bytes4[] memory validFunctionSignatures
  ) internal pure { unchecked {
    uint len = ecrs.length;
    for (uint i; i < len; ++i)
      validateEthCallRecord(ecrs[i], validContractAddresses, validFunctionSignatures);
  }}

  //validates that EthCallRecord a valid function signature and contract address
  //An empty array means we accept all addresses/function signatures
  //  Example 1: To accept signatures 0xaaaaaaaa and 0xbbbbbbbb from `address(abcd)`
  //    you'd pass in [0xaaaaaaaa, 0xbbbbbbbb], [address(abcd)]
  //  Example 2: To accept any function signatures from `address(abcd)` or `address(efab)`
  //    you'd pass in [], [address(abcd), address(efab)]
  //  Example 3: To accept function signature 0xaaaaaaaa from any address
  //    you'd pass in [0xaaaaaaaa], []
  //
  // WARNING Example 4: If you want to accept signature 0xaaaaaaaa from `address(abcd)`
  //    and signature 0xbbbbbbbb from `address(efab)` the following input would be incorrect:
  //    [0xaaaaaaaa, 0xbbbbbbbb], [address(abcd), address(efab)]
  //    This would accept both 0xaaaaaaaa and 0xbbbbbbbb from `address(abcd)` AND `address(efab)`.
  //    Instead you should make 2 calls to this method using the pattern in Example 1.
  //    [0xaaaaaaaa], [address(abcd)] OR [0xbbbbbbbb], [address(efab)]
  function validateEthCallRecord(
    EthCallRecord memory ecd,
    address[] memory validContractAddresses, //empty array means accept all
    bytes4[] memory validFunctionSignatures  //empty array means accept all
  ) internal pure {
    if (validContractAddresses.length > 0)
      _validateContractAddress(ecd.contractAddress, validContractAddresses);

    if (validFunctionSignatures.length > 0) {
      if (ecd.callData.length < 4)
        revert InvalidFunctionSignature();

      (bytes4 funcSig, ) = ecd.callData.asBytes4MemUnchecked(0);
      _validateFunctionSignature(funcSig, validFunctionSignatures);
    }
  }

  function _validateContractAddress(
    address contractAddress,
    address[] memory validContractAddresses
  ) private pure { unchecked {
    uint len = validContractAddresses.length;
    for (uint i; i < len; ++i)
      if (contractAddress == validContractAddresses[i])
        return;

    revert InvalidContractAddress();
  }}

  function _validateFunctionSignature(
    bytes4 functionSignature,
    bytes4[] memory validFunctionSignatures
  ) private pure { unchecked {
    uint len = validFunctionSignatures.length;
    for (uint i; i < len; ++i)
      if (functionSignature == validFunctionSignatures[i])
        return;

    revert InvalidFunctionSignature();
  }}

  //we use this over BytesParsing.checkLength to return our custom errors in all error cases
  function _checkLength(uint256 length, uint256 expected) private pure {
    if (length != expected)
      revert InvalidPayloadLength(length, expected);
  }
}

File 4 of 21 : VaaLib.sol
// SPDX-License-Identifier: Apache 2
pragma solidity ^0.8.14; //for (bugfixed) support of `using ... global;` syntax for libraries

import {IWormhole} from "wormhole-sdk/interfaces/IWormhole.sol";
import {BytesParsing} from "wormhole-sdk/libraries/BytesParsing.sol";
import {
  toUniversalAddress,
  keccak256Cd,
  keccak256Word,
  keccak256SliceUnchecked
} from "wormhole-sdk/Utils.sol";

// ╭─────────────────────────────────────────────────╮
// │ Library for encoding and decoding Wormhole VAAs │
// ╰─────────────────────────────────────────────────╯

// # VAA Format
//
// see:
//  * ../interfaces/IWormhole.sol VM struct (VM = Verified Message)
//  * [CoreBridge](https://github.com/wormhole-foundation/wormhole/blob/c35940ae9689f6df9e983d51425763509b74a80f/ethereum/contracts/Messages.sol#L147)
//  * [Typescript SDK](https://github.com/wormhole-foundation/wormhole-sdk-ts/blob/3cd10030b5e924f0621c7231e24410b8a0946a07/core/definitions/src/vaa/vaa.ts#L32-L51)
//
// ╭──────────┬──────────────────────────────────────────────────────────────────────────────╮
// │ Section  │ Description                                                                  │
// ├──────────┼──────────────────────────────────────────────────────────────────────────────┤
// │ Header   │ version, guardian signature info required to verify the VAA                  │
// │ Envelope │ contains metadata of the emitted message, such as emitter or timestamp       │
// │ Payload  │ the emitted message, raw bytes, no length prefix, consumes remainder of data │
// ╰──────────┴──────────────────────────────────────────────────────────────────────────────╯
// Body = Envelope + Payload
// The VAA body is exactly the information that goes into a published message of the CoreBridge
//   and is what gets keccak256-hashed when calculating the VAA hash (i.e. the header is excluded).
//
// Note:
//   Guardians do _not_ sign the body directly, but rather the hash of the body, i.e. from the PoV
//     of a guardian, the message itself is already only a hash.
//   But [the first step of the ECDSA signature scheme](https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm#Signature_generation_algorithm)
//     is to hash the message, leading to the hash being hashed a second time when signing.
//   Likewise, ecrecover also operates on the hash of the message, rather than the message itself.
//   This means that when verifying guardian signatures of a VAA, the hash that must be passed to
//     ecrecover is the doubly-hashed body.
//
// ╭─────────────────────────────────────── WARNING ───────────────────────────────────────╮
// │ There is an unfortunate inconsistency between the implementation of the CoreBridge on │
// │   EVM, where IWormhole.VM.hash is the *doubly* hashed body [1], while everything else │
// │   only uses the singly-hashed body (see Solana CoreBridge [2] and Typescript SDK [3]) │
// ╰───────────────────────────────────────────────────────────────────────────────────────╯
// [1] https://github.com/wormhole-foundation/wormhole/blob/1dbe8459b96e182932d0dd5ae4b6bbce6f48cb09/ethereum/contracts/Messages.sol#L178-L186
// [2] https://github.com/wormhole-foundation/wormhole/blob/1dbe8459b96e182932d0dd5ae4b6bbce6f48cb09/solana/bridge/program/src/api/post_vaa.rs#L214C4-L244
// [3] https://github.com/wormhole-foundation/wormhole-sdk-ts/blob/3cd10030b5e924f0621c7231e24410b8a0946a07/core/definitions/src/vaa/functions.ts#L189
//
// ## Format in Detail
//
// ╭─────────────┬──────────────────┬──────────────────────────────────────────────────────────────╮
// │    Type     │       Name       │     Description                                              │
// ┝━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┥
// │           Header                                                                              │
// ├─────────────┬──────────────────┬──────────────────────────────────────────────────────────────┤
// │    uint8    │ version          │ fixed value of 1 (see HEADER_VERSION below)                  │
// │    uint32   │ guardianSetIndex │ the guardian set that signed the VAA                         │
// │    uint8    │ signatureCount   │ must be greater than guardian set size * 2 / 3 for quorum    │
// │ Signature[] │ signatures       │ signatures of the guardians that signed the VAA              │
// ┝━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┥
// │          Signature                                                                            │
// ├─────────────┬──────────────────┬──────────────────────────────────────────────────────────────┤
// │    uint8    │ guardianIndex    │ position of the signing guardian in the guardian set         │
// │   bytes32   │ r                │ ECDSA r value                                                │
// │   bytes32   │ s                │ ECDSA s value                                                │
// │    uint8    │ v                │ encoded: 0/1, decoded: 27/28, see SIGNATURE_RECOVERY_MAGIC   │
// ┝━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┥
// │          Envelope                                                                             │
// ├─────────────┬──────────────────┬──────────────────────────────────────────────────────────────┤
// │    uint32   │ timestamp        │ unix timestamp of block containing the emitted message       │
// │    uint32   │ nonce            │ user-defined nonce                                           │
// │    uint16   │ emitterChainId   │ Wormhole (not EVM) chain id of the emitter                   │
// │   bytes32   │ emitterAddress   │ universal address of the emitter                             │
// │    uint64   │ sequence         │ sequence number of the message (counter per emitter)         │
// │    uint8    │ consistencyLevel │ https://wormhole.com/docs/build/reference/consistency-levels │
// ┝━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┥
// │          Payload                                                                              │
// ├─────────────┬──────────────────┬──────────────────────────────────────────────────────────────┤
// │    bytes    │ payload          │ emitted message, consumes rest of VAA (no length prefix)     │
// ╰─────────────┴──────────────────┴──────────────────────────────────────────────────────────────╯
//
// # Library
//
// This library is built on top of BytesParsing which is a lot more gas efficient than BytesLib,
//   which is used in the CoreBridge.
//
// It also provides decoding functions for parsing the individual components of the VAA separately
//   and returning them on the stack, rather than as a struct which requires memory allocation.
//
// ## Library Functions & Naming Conventions
//
// All library functions come in 2 flavors:
//   1. Calldata (using the Cd tag)
//   2. Memory (using the Mem tag)
//
// Additionally, most functions also have an additional struct flavor that returns the decoded
//   values in the associated struct (in memory), rather than as individual values (on the stack).
//
// The parameter name `encodedVaa` is used for functions where the bytes are expected to contain
//   a single, full VAA. Otherwise, i.e. for partials or multiple VAAs, the name `encoded` is used.
//
// Like in BytesParsing, the Unchecked function name suffix does not refer to Solidity's `unchecked`
//   keyword, but rather to the fact that no bounds checking is performed. All math is done using
//   unchecked arithmetic because overflows are impossible due to the nature of the VAA format,
//   while we explicitly check for underflows where necessary.
//
// Function names, somewhat redundantly, contain the tag "Vaa" to add clarity and avoid potential
//   name collisions when using the library with a `using ... for bytes` directive.
//
//   Function Base Name  │     Description
//  ─────────────────────┼────────────────────────────────────────────────────────────────────────
//   decodeVmStruct      │ decodes a legacy VM struct (no non-struct flavor available)
//   decodeVaaEssentials │ decodes the emitter, sequence, and payload
//   decodeVaaBody       │ decodes the envelope and payload
//   checkVaaVersion     │
//   skipVaaHeader       │ returns the offset to the envelope
//   calcVaaSingleHash   │ see explanation/WARNING box at the top
//   calcVaaDoubleHash   │ see explanation/WARNING box at the top
//   decodeVaaEnvelope   │
//   decodeVaaPayload    │
//
// encode functions (for testing, converts back into serialized byte array format):
//   * encode (overloaded for each struct)
//   * encodeVaaHeader
//   * encodeVaaEnvelope
//   * encodeVaaBody
//   * encodeVaa
//
// other functions:
//   * asIWormholeSignatures (casting between GuardianSignature and IWormhole.Signature)
//   * asGuardianSignatures (casting between GuardianSignature and IWormhole.Signature)

//Annoyingly, Solidity only allows aliasing of types that are exported on the file level, but not
//  of nested types, see [language grammar](https://docs.soliditylang.org/en/v0.8.28/grammar.html#a4.SolidityParser.importDirective)
//So we (re)define GuardianSignature identically to IWormhole.Signature to avoid the explicit
//  dependency and to provide a better name and do the necessary casts manually using assembly.
//Without the alias, users who want to reference the GuardianSignature type would have to import
//  IWormhole themselves, which breaks the intended encapsulation of this library.
struct GuardianSignature {
  bytes32 r;
  bytes32 s;
  uint8 v;
  uint8 guardianIndex;
}

struct VaaHeader {
  //uint8 version;
  uint32 guardianSetIndex;
  GuardianSignature[] signatures;
}

struct VaaEnvelope {
  uint32 timestamp;
  uint32 nonce;
  uint16 emitterChainId;
  bytes32 emitterAddress;
  uint64 sequence;
  uint8 consistencyLevel;
}

struct VaaBody {
  VaaEnvelope envelope;
  bytes payload;
}

struct Vaa {
  VaaHeader header;
  VaaEnvelope envelope;
  bytes payload;
}

struct VaaEssentials {
  uint16 emitterChainId;
  bytes32 emitterAddress;
  uint64 sequence;
  bytes payload;
}

library VaaLib {
  using BytesParsing for bytes;
  using {BytesParsing.checkBound} for uint;

  error InvalidVersion(uint8 version);

  uint8 internal constant HEADER_VERSION = 1;
  //see https://github.com/wormhole-foundation/wormhole/blob/c35940ae9689f6df9e983d51425763509b74a80f/ethereum/contracts/Messages.sol#L174
  //origin: https://bitcoin.stackexchange.com/a/102382
  uint8 internal constant SIGNATURE_RECOVERY_MAGIC = 27;

  //the following offsets are provided for more eclectic, manual parsing
  uint internal constant HEADER_VERSION_OFFSET = 0;
  uint internal constant HEADER_VERSION_SIZE = 1;

  uint internal constant HEADER_GUARDIAN_SET_INDEX_OFFSET =
    HEADER_VERSION_OFFSET + HEADER_VERSION_SIZE;
  uint internal constant HEADER_GUARDIAN_SET_INDEX_SIZE = 4;

  uint internal constant HEADER_SIGNATURE_COUNT_OFFSET =
    HEADER_GUARDIAN_SET_INDEX_OFFSET + HEADER_GUARDIAN_SET_INDEX_SIZE;
  uint internal constant HEADER_SIGNATURE_COUNT_SIZE = 1;

  uint internal constant HEADER_SIGNATURE_ARRAY_OFFSET =
    HEADER_SIGNATURE_COUNT_OFFSET + HEADER_SIGNATURE_COUNT_SIZE;

  uint internal constant GUARDIAN_SIGNATURE_GUARDIAN_INDEX_OFFSET = 0;
  uint internal constant GUARDIAN_SIGNATURE_GUARDIAN_INDEX_SIZE = 1;

  uint internal constant GUARDIAN_SIGNATURE_R_OFFSET =
    GUARDIAN_SIGNATURE_GUARDIAN_INDEX_OFFSET + GUARDIAN_SIGNATURE_GUARDIAN_INDEX_SIZE;
  uint internal constant GUARDIAN_SIGNATURE_R_SIZE = 32;

  uint internal constant GUARDIAN_SIGNATURE_S_OFFSET =
    GUARDIAN_SIGNATURE_R_OFFSET + GUARDIAN_SIGNATURE_R_SIZE;
  uint internal constant GUARDIAN_SIGNATURE_S_SIZE = 32;

  uint internal constant GUARDIAN_SIGNATURE_V_OFFSET =
    GUARDIAN_SIGNATURE_S_OFFSET + GUARDIAN_SIGNATURE_S_SIZE;
  uint internal constant GUARDIAN_SIGNATURE_V_SIZE = 1;

  uint internal constant GUARDIAN_SIGNATURE_SIZE =
    GUARDIAN_SIGNATURE_V_OFFSET + GUARDIAN_SIGNATURE_V_SIZE;

  uint internal constant ENVELOPE_TIMESTAMP_OFFSET = 0;
  uint internal constant ENVELOPE_TIMESTAMP_SIZE = 4;

  uint internal constant ENVELOPE_NONCE_OFFSET =
    ENVELOPE_TIMESTAMP_OFFSET + ENVELOPE_TIMESTAMP_SIZE;
  uint internal constant ENVELOPE_NONCE_SIZE = 4;

  uint internal constant ENVELOPE_EMITTER_CHAIN_ID_OFFSET =
    ENVELOPE_NONCE_OFFSET + ENVELOPE_NONCE_SIZE;
  uint internal constant ENVELOPE_EMITTER_CHAIN_ID_SIZE = 2;

  uint internal constant ENVELOPE_EMITTER_ADDRESS_OFFSET =
    ENVELOPE_EMITTER_CHAIN_ID_OFFSET + ENVELOPE_EMITTER_CHAIN_ID_SIZE;
  uint internal constant ENVELOPE_EMITTER_ADDRESS_SIZE = 32;

  uint internal constant ENVELOPE_SEQUENCE_OFFSET =
    ENVELOPE_EMITTER_ADDRESS_OFFSET + ENVELOPE_EMITTER_ADDRESS_SIZE;
  uint internal constant ENVELOPE_SEQUENCE_SIZE = 8;

  uint internal constant ENVELOPE_CONSISTENCY_LEVEL_OFFSET =
    ENVELOPE_SEQUENCE_OFFSET + ENVELOPE_SEQUENCE_SIZE;
  uint internal constant ENVELOPE_CONSISTENCY_LEVEL_SIZE = 1;

  uint internal constant ENVELOPE_SIZE =
    ENVELOPE_CONSISTENCY_LEVEL_OFFSET + ENVELOPE_CONSISTENCY_LEVEL_SIZE;

  // ------------ Convenience Decoding Functions ------------

  //legacy decoder for IWormhole.VM
  function decodeVmStructCd(
    bytes calldata encodedVaa
  ) internal pure returns (IWormhole.VM memory vm) {
    vm.version = HEADER_VERSION;
    uint envelopeOffset;
    GuardianSignature[] memory signatures;
    (vm.guardianSetIndex, signatures, envelopeOffset) = decodeVaaHeaderCdUnchecked(encodedVaa);
    vm.signatures = asIWormholeSignatures(signatures);
    vm.hash = calcVaaDoubleHashCd(encodedVaa, envelopeOffset);
    ( vm.timestamp,
      vm.nonce,
      vm.emitterChainId,
      vm.emitterAddress,
      vm.sequence,
      vm.consistencyLevel,
      vm.payload
    ) = decodeVaaBodyCd(encodedVaa, envelopeOffset);
  }

  function decodeVmStructMem(
    bytes memory encodedVaa
  ) internal pure returns (IWormhole.VM memory vm) {
    (vm, ) = decodeVmStructMemUnchecked(encodedVaa, 0, encodedVaa.length);
  }

  function decodeVaaStructCd(
    bytes calldata encodedVaa
  ) internal pure returns (Vaa memory vaa) {
    uint envelopeOffset;
    (vaa.header, envelopeOffset) = decodeVaaHeaderStructCdUnchecked(encodedVaa);

    uint payloadOffset;
    (vaa.envelope, payloadOffset) = decodeVaaEnvelopeStructCdUnchecked(encodedVaa, envelopeOffset);
    vaa.payload = decodeVaaPayloadCd(encodedVaa, payloadOffset);
  }

  function decodeVaaStructMem(
    bytes memory encodedVaa
  ) internal pure returns (Vaa memory vaa) {
    (vaa, ) = decodeVaaStructMemUnchecked(encodedVaa, 0, encodedVaa.length);
  }

  function decodeVaaEssentialsCd(
    bytes calldata encodedVaa
  ) internal pure returns (
    uint16  emitterChainId,
    bytes32 emitterAddress,
    uint64  sequence,
    bytes calldata payload
  ) { unchecked {
    checkVaaVersionCd(encodedVaa);

    uint envelopeOffset = skipVaaHeaderCd(encodedVaa);
    uint offset = envelopeOffset + ENVELOPE_EMITTER_CHAIN_ID_OFFSET;
    (emitterChainId, offset) = encodedVaa.asUint16CdUnchecked(offset);
    (emitterAddress, offset) = encodedVaa.asBytes32CdUnchecked(offset);
    (sequence,             ) = encodedVaa.asUint64CdUnchecked(offset);

    uint payloadOffset = envelopeOffset + ENVELOPE_SIZE;
    payload = decodeVaaPayloadCd(encodedVaa, payloadOffset);
  }}

  function decodeVaaEssentialsStructCd(
    bytes calldata encodedVaa
  ) internal pure returns (VaaEssentials memory ret) {
    (ret.emitterChainId, ret.emitterAddress, ret.sequence, ret.payload) =
      decodeVaaEssentialsCd(encodedVaa);
  }

  //The returned values are considered the essentials because it's important to check the emitter
  //  to avoid spoofing. Also, VAAs that use finalized consistency levels should leverage the
  //  sequence number (on a per emitter basis!) and a bitmap for replay protection rather than the
  //  hashed body because it is more gas efficient (storage slot is likely already dirty).
  function decodeVaaEssentialsMem(
    bytes memory encodedVaa
  ) internal pure returns (
    uint16 emitterChainId,
    bytes32 emitterAddress,
    uint64 sequence,
    bytes memory payload
  ) {
    (emitterChainId, emitterAddress, sequence, payload, ) =
      decodeVaaEssentialsMem(encodedVaa, 0, encodedVaa.length);
  }

  function decodeVaaEssentialsStructMem(
    bytes memory encodedVaa
  ) internal pure returns (VaaEssentials memory ret) {
    (ret.emitterChainId, ret.emitterAddress, ret.sequence, ret.payload, ) =
      decodeVaaEssentialsMem(encodedVaa, 0, encodedVaa.length);
  }

  function decodeVaaEssentialsMem(
    bytes memory encoded,
    uint headerOffset,
    uint vaaLength
  ) internal pure returns (
    uint16  emitterChainId,
    bytes32 emitterAddress,
    uint64  sequence,
    bytes memory payload,
    uint    newOffset
  ) { unchecked {
    uint offset = checkVaaVersionMemUnchecked(encoded, headerOffset);

    uint envelopeOffset = skipVaaHeaderMemUnchecked(encoded, offset);
    offset = envelopeOffset + ENVELOPE_EMITTER_CHAIN_ID_OFFSET;
    (emitterChainId, offset) = encoded.asUint16MemUnchecked(offset);
    (emitterAddress, offset) = encoded.asBytes32MemUnchecked(offset);
    (sequence,             ) = encoded.asUint64MemUnchecked(offset);

    uint payloadOffset = envelopeOffset + ENVELOPE_SIZE;
    (payload, newOffset) = decodeVaaPayloadMemUnchecked(encoded, payloadOffset, vaaLength);
  }}

  function decodeVaaEssentialsStructMem(
    bytes memory encodedVaa,
    uint headerOffset,
    uint vaaLength
  ) internal pure returns (VaaEssentials memory ret, uint newOffset) {
    (ret.emitterChainId, ret.emitterAddress, ret.sequence, ret.payload, newOffset) =
      decodeVaaEssentialsMem(encodedVaa, headerOffset, vaaLength);
  }

  function decodeVaaBodyCd(
    bytes calldata encodedVaa
  ) internal pure returns (
    uint32  timestamp,
    uint32  nonce,
    uint16  emitterChainId,
    bytes32 emitterAddress,
    uint64  sequence,
    uint8   consistencyLevel,
    bytes calldata payload
  ) {
    checkVaaVersionCd(encodedVaa);
    (timestamp, nonce, emitterChainId, emitterAddress, sequence, consistencyLevel, payload) =
      decodeVaaBodyCd(encodedVaa, skipVaaHeaderCd(encodedVaa));
  }

  function decodeVaaBodyStructCd(
    bytes calldata encodedVaa
  ) internal pure returns (VaaBody memory body) {
    ( body.envelope.timestamp,
      body.envelope.nonce,
      body.envelope.emitterChainId,
      body.envelope.emitterAddress,
      body.envelope.sequence,
      body.envelope.consistencyLevel,
      body.payload
    ) = decodeVaaBodyCd(encodedVaa);
  }

  function decodeVaaBodyMem(
    bytes memory encodedVaa
  ) internal pure returns (
    uint32  timestamp,
    uint32  nonce,
    uint16  emitterChainId,
    bytes32 emitterAddress,
    uint64  sequence,
    uint8   consistencyLevel,
    bytes memory payload
  ) {
    checkVaaVersionMemUnchecked(encodedVaa, 0);
    uint envelopeOffset = skipVaaHeaderMemUnchecked(encodedVaa, 0);
    (timestamp, nonce, emitterChainId, emitterAddress, sequence, consistencyLevel, payload, ) =
      decodeVaaBodyMemUnchecked(encodedVaa, envelopeOffset, encodedVaa.length);
  }

  function decodeVaaBodyStructMem(
    bytes memory encodedVaa
  ) internal pure returns (VaaBody memory body) {
    ( body.envelope.timestamp,
      body.envelope.nonce,
      body.envelope.emitterChainId,
      body.envelope.emitterAddress,
      body.envelope.sequence,
      body.envelope.consistencyLevel,
      body.payload,
    ) = decodeVaaBodyMemUnchecked(encodedVaa, 0, encodedVaa.length);
  }

  // Convinience decoding function for token bridge Vaas
  function decodeEmitterChainAndPayloadCdUnchecked(
    bytes calldata encodedVaa
  ) internal pure returns (uint16 emitterChainId, bytes calldata payload) { unchecked {
    checkVaaVersionCd(encodedVaa);
    uint envelopeOffset = skipVaaHeaderCd(encodedVaa);
    uint offset = envelopeOffset + ENVELOPE_EMITTER_CHAIN_ID_OFFSET;
    (emitterChainId, offset) = encodedVaa.asUint16CdUnchecked(offset);
    offset += ENVELOPE_EMITTER_ADDRESS_SIZE + ENVELOPE_SEQUENCE_SIZE + ENVELOPE_CONSISTENCY_LEVEL_SIZE;
    payload = decodeVaaPayloadCd(encodedVaa, offset);
  }}

  function decodeEmitterChainAndPayloadMemUnchecked(
    bytes memory encodedVaa
  ) internal pure returns (uint16 emitterChainId, bytes memory payload) { unchecked {
    checkVaaVersionMemUnchecked(encodedVaa, 0);
    uint envelopeOffset = skipVaaHeaderMemUnchecked(encodedVaa, 0);
    uint offset = envelopeOffset + ENVELOPE_EMITTER_CHAIN_ID_OFFSET;
    (emitterChainId, offset) = encodedVaa.asUint16MemUnchecked(offset);
    offset += ENVELOPE_EMITTER_ADDRESS_SIZE + ENVELOPE_SEQUENCE_SIZE + ENVELOPE_CONSISTENCY_LEVEL_SIZE;
    (payload, ) = decodeVaaPayloadMemUnchecked(encodedVaa, offset, encodedVaa.length);
  }}

  // ------------ Advanced Decoding Functions ------------

  function asIWormholeSignatures(
    GuardianSignature[] memory signatures
  ) internal pure returns (IWormhole.Signature[] memory vmSignatures) {
    assembly ("memory-safe") {
      vmSignatures := signatures
    }
  }

  function asGuardianSignatures(
    IWormhole.Signature[] memory vmSignatures
  ) internal pure returns (GuardianSignature[] memory signatures) {
    assembly ("memory-safe") {
      signatures := vmSignatures
    }
  }

  function checkVaaVersionCd(bytes calldata encodedVaa) internal pure returns (uint newOffset) {
    uint8 version;
    (version, newOffset) = encodedVaa.asUint8CdUnchecked(0);
    checkVaaVersion(version);
  }

  function checkVaaVersionMemUnchecked(
    bytes memory encoded,
    uint offset
  ) internal pure returns (uint newOffset) {
    uint8 version;
    (version, newOffset) = encoded.asUint8MemUnchecked(offset);
    checkVaaVersion(version);
  }

  function checkVaaVersion(uint8 version) internal pure {
    if (version != HEADER_VERSION)
      revert InvalidVersion(version);
  }

  //return the offset to the start of the envelope/body
  function skipVaaHeaderCd(
    bytes calldata encodedVaa
  ) internal pure returns (uint envelopeOffset) { unchecked {
    (uint sigCount, uint offset) = encodedVaa.asUint8CdUnchecked(HEADER_SIGNATURE_COUNT_OFFSET);
    envelopeOffset = offset + sigCount * GUARDIAN_SIGNATURE_SIZE;
  }}

  function skipVaaHeaderMemUnchecked(
    bytes memory encoded,
    uint headerOffset
  ) internal pure returns (uint envelopeOffset) { unchecked {
    uint offset = headerOffset + HEADER_SIGNATURE_COUNT_OFFSET;
    uint sigCount;
    (sigCount, offset) = encoded.asUint8MemUnchecked(offset);
    envelopeOffset = offset + sigCount * GUARDIAN_SIGNATURE_SIZE;
  }}

  //see WARNING box at the top
  function calcVaaSingleHashCd(
    bytes calldata encodedVaa,
    uint envelopeOffset
  ) internal pure returns (bytes32) {
    return keccak256Cd(_decodeRemainderCd(encodedVaa, envelopeOffset));
  }

  //see WARNING box at the top
  function calcVaaSingleHashMem(
    bytes memory encoded,
    uint envelopeOffset,
    uint vaaLength
  ) internal pure returns (bytes32) { unchecked {
    envelopeOffset.checkBound(vaaLength);
    return keccak256SliceUnchecked(encoded, envelopeOffset, vaaLength - envelopeOffset);
  }}

  //see WARNING box at the top
  function calcSingleHash(Vaa memory vaa) internal pure returns (bytes32) {
    return keccak256(abi.encodePacked(encode(vaa.envelope), vaa.payload));
  }

  //see WARNING box at the top
  function calcSingleHash(VaaBody memory body) internal pure returns (bytes32) {
    return keccak256(encode(body));
  }

  //see WARNING box at the top
  //this function matches IWormhole.VM.hash and is what's been used for (legacy) replay protection
  function calcVaaDoubleHashCd(
    bytes calldata encodedVaa,
    uint envelopeOffset
  ) internal pure returns (bytes32) {
    return keccak256Word(calcVaaSingleHashCd(encodedVaa, envelopeOffset));
  }

  //see WARNING box at the top
  function calcVaaDoubleHashMem(
    bytes memory encoded,
    uint envelopeOffset,
    uint vaaLength
  ) internal pure returns (bytes32) {
    return keccak256Word(calcVaaSingleHashMem(encoded, envelopeOffset, vaaLength));
  }

  //see WARNING box at the top
  function calcDoubleHash(Vaa memory vaa) internal pure returns (bytes32) {
    return keccak256Word(calcSingleHash(vaa));
  }

  //see WARNING box at the top
  function calcDoubleHash(VaaBody memory body) internal pure returns (bytes32) {
    return keccak256Word(calcSingleHash(body));
  }

  function decodeVmStructMemUnchecked(
    bytes memory encoded,
    uint headerOffset,
    uint vaaLength
  ) internal pure returns (IWormhole.VM memory vm, uint newOffset) {
    vm.version = HEADER_VERSION;
    uint envelopeOffset;
    GuardianSignature[] memory signatures;
    (vm.guardianSetIndex, signatures, envelopeOffset) =
      decodeVaaHeaderMemUnchecked(encoded, headerOffset);
    vm.signatures = asIWormholeSignatures(signatures);
    vm.hash = calcVaaDoubleHashMem(encoded, envelopeOffset, vaaLength);
    ( vm.timestamp,
      vm.nonce,
      vm.emitterChainId,
      vm.emitterAddress,
      vm.sequence,
      vm.consistencyLevel,
      vm.payload,
      newOffset
    ) = decodeVaaBodyMemUnchecked(encoded, envelopeOffset, vaaLength);
  }

  function decodeVaaStructMemUnchecked(
    bytes memory encoded,
    uint headerOffset,
    uint vaaLength
  ) internal pure returns (Vaa memory vaa, uint newOffset) {
    uint envelopeOffset;
    (vaa.header.guardianSetIndex, vaa.header.signatures, envelopeOffset) =
      decodeVaaHeaderMemUnchecked(encoded, headerOffset);

    uint payloadOffset;
    (vaa.envelope, payloadOffset) = decodeVaaEnvelopeStructMemUnchecked(encoded, envelopeOffset);

    (vaa.payload, newOffset) = decodeVaaPayloadMemUnchecked(encoded, payloadOffset, vaaLength);
  }

  function decodeVaaBodyCd(
    bytes calldata encodedVaa,
    uint envelopeOffset
  ) internal pure returns (
    uint32  timestamp,
    uint32  nonce,
    uint16  emitterChainId,
    bytes32 emitterAddress,
    uint64  sequence,
    uint8   consistencyLevel,
    bytes calldata payload
  ) {
    uint payloadOffset;
    (timestamp, nonce, emitterChainId, emitterAddress, sequence, consistencyLevel, payloadOffset) =
      decodeVaaEnvelopeCdUnchecked(encodedVaa, envelopeOffset);
    payload = decodeVaaPayloadCd(encodedVaa, payloadOffset);
  }

  function decodeVaaBodyStructCd(
    bytes calldata encodedVaa,
    uint envelopeOffset
  ) internal pure returns (VaaBody memory body) {
    ( body.envelope.timestamp,
      body.envelope.nonce,
      body.envelope.emitterChainId,
      body.envelope.emitterAddress,
      body.envelope.sequence,
      body.envelope.consistencyLevel,
      body.payload
    ) = decodeVaaBodyCd(encodedVaa, envelopeOffset);
  }

  function decodeVaaBodyMemUnchecked(
    bytes memory encoded,
    uint envelopeOffset,
    uint vaaLength
  ) internal pure returns (
    uint32  timestamp,
    uint32  nonce,
    uint16  emitterChainId,
    bytes32 emitterAddress,
    uint64  sequence,
    uint8   consistencyLevel,
    bytes memory payload,
    uint    newOffset
  ) {
    uint payloadOffset;
    (timestamp, nonce, emitterChainId, emitterAddress, sequence, consistencyLevel, payloadOffset) =
      decodeVaaEnvelopeMemUnchecked(encoded, envelopeOffset);
    (payload, newOffset) = decodeVaaPayloadMemUnchecked(encoded, payloadOffset, vaaLength);
  }

  function decodeVaaBodyStructMemUnchecked(
    bytes memory encoded,
    uint envelopeOffset,
    uint vaaLength
  ) internal pure returns (VaaBody memory body, uint newOffset) {
    ( body.envelope.timestamp,
      body.envelope.nonce,
      body.envelope.emitterChainId,
      body.envelope.emitterAddress,
      body.envelope.sequence,
      body.envelope.consistencyLevel,
      body.payload,
      newOffset
    ) = decodeVaaBodyMemUnchecked(encoded, envelopeOffset, vaaLength);
  }

  function decodeVaaEnvelopeCdUnchecked(
    bytes calldata encodedVaa,
    uint envelopeOffset
  ) internal pure returns (
    uint32  timestamp,
    uint32  nonce,
    uint16  emitterChainId,
    bytes32 emitterAddress,
    uint64  sequence,
    uint8   consistencyLevel,
    uint    payloadOffset
  ) {
    uint offset = envelopeOffset;
    (timestamp,        offset) = encodedVaa.asUint32CdUnchecked(offset);
    (nonce,            offset) = encodedVaa.asUint32CdUnchecked(offset);
    (emitterChainId,   offset) = encodedVaa.asUint16CdUnchecked(offset);
    (emitterAddress,   offset) = encodedVaa.asBytes32CdUnchecked(offset);
    (sequence,         offset) = encodedVaa.asUint64CdUnchecked(offset);
    (consistencyLevel, offset) = encodedVaa.asUint8CdUnchecked(offset);
    payloadOffset = offset;
  }

  function decodeVaaEnvelopeStructCdUnchecked(
    bytes calldata encodedVaa,
    uint envelopeOffset
  ) internal pure returns (VaaEnvelope memory envelope, uint payloadOffset) {
    ( envelope.timestamp,
      envelope.nonce,
      envelope.emitterChainId,
      envelope.emitterAddress,
      envelope.sequence,
      envelope.consistencyLevel,
      payloadOffset
    ) = decodeVaaEnvelopeCdUnchecked(encodedVaa, envelopeOffset);
  }

  function decodeVaaEnvelopeMemUnchecked(
    bytes memory encoded,
    uint envelopeOffset
  ) internal pure returns (
    uint32  timestamp,
    uint32  nonce,
    uint16  emitterChainId,
    bytes32 emitterAddress,
    uint64  sequence,
    uint8   consistencyLevel,
    uint    payloadOffset
  ) {
    uint offset = envelopeOffset;
    (timestamp,        offset) = encoded.asUint32MemUnchecked(offset);
    (nonce,            offset) = encoded.asUint32MemUnchecked(offset);
    (emitterChainId,   offset) = encoded.asUint16MemUnchecked(offset);
    (emitterAddress,   offset) = encoded.asBytes32MemUnchecked(offset);
    (sequence,         offset) = encoded.asUint64MemUnchecked(offset);
    (consistencyLevel, offset) = encoded.asUint8MemUnchecked(offset);
    payloadOffset = offset;
  }

  function decodeVaaEnvelopeStructMemUnchecked(
    bytes memory encoded,
    uint envelopeOffset
  ) internal pure returns (VaaEnvelope memory envelope, uint payloadOffset) {
    ( envelope.timestamp,
      envelope.nonce,
      envelope.emitterChainId,
      envelope.emitterAddress,
      envelope.sequence,
      envelope.consistencyLevel,
      payloadOffset
    ) = decodeVaaEnvelopeMemUnchecked(encoded, envelopeOffset);
  }

  function decodeVaaHeaderCdUnchecked(
    bytes calldata encodedVaa
  ) internal pure returns (
    uint32 guardianSetIndex,
    GuardianSignature[] memory signatures,
    uint envelopeOffset
  ) { unchecked {
    checkVaaVersionCd(encodedVaa);
    uint offset = HEADER_GUARDIAN_SET_INDEX_OFFSET;
    (guardianSetIndex, offset) = encodedVaa.asUint32CdUnchecked(offset);

    uint signersLen;
    (signersLen, offset) = encodedVaa.asUint8CdUnchecked(offset);

    signatures = new GuardianSignature[](signersLen);
    for (uint i = 0; i < signersLen; ++i)
      (signatures[i], offset) = decodeGuardianSignatureStructCdUnchecked(encodedVaa, offset);

    envelopeOffset = offset;
  }}

  function decodeVaaHeaderStructCdUnchecked(
    bytes calldata encodedVaa
  ) internal pure returns (VaaHeader memory header, uint envelopeOffset) {
    ( header.guardianSetIndex,
      header.signatures,
      envelopeOffset
    ) = decodeVaaHeaderCdUnchecked(encodedVaa);
  }

  function decodeVaaHeaderMemUnchecked(
    bytes memory encoded,
    uint offset
  ) internal pure returns (
    uint32 guardianSetIndex,
    GuardianSignature[] memory signatures,
    uint envelopeOffset
  ) { unchecked {
    offset = checkVaaVersionMemUnchecked(encoded, offset);
    (guardianSetIndex, offset) = encoded.asUint32MemUnchecked(offset);

    uint signersLen;
    (signersLen, offset) = encoded.asUint8MemUnchecked(offset);

    signatures = new GuardianSignature[](signersLen);
    for (uint i = 0; i < signersLen; ++i)
      (signatures[i], offset) = decodeGuardianSignatureStructMemUnchecked(encoded, offset);

    envelopeOffset = offset;
  }}

  function decodeVaaHeaderStructMemUnchecked(
    bytes memory encoded,
    uint offset
  ) internal pure returns (VaaHeader memory header, uint envelopeOffset) {
    ( header.guardianSetIndex,
      header.signatures,
      envelopeOffset
    ) = decodeVaaHeaderMemUnchecked(encoded, offset);
  }

  function decodeGuardianSignatureCdUnchecked(
    bytes calldata encodedVaa,
    uint offset
  ) internal pure returns (
    uint8 guardianIndex,
    bytes32 r,
    bytes32 s,
    uint8 v,
    uint newOffset
  ) { unchecked {
    (guardianIndex, offset) = encodedVaa.asUint8CdUnchecked(offset);
    (r,             offset) = encodedVaa.asBytes32CdUnchecked(offset);
    (s,             offset) = encodedVaa.asBytes32CdUnchecked(offset);
    (v,             offset) = encodedVaa.asUint8CdUnchecked(offset);
    v += SIGNATURE_RECOVERY_MAGIC;
    newOffset = offset;
  }}

  function decodeGuardianSignatureStructCdUnchecked(
    bytes calldata encodedVaa,
    uint offset
  ) internal pure returns (GuardianSignature memory ret, uint newOffset) {
    (ret.guardianIndex, ret.r, ret.s, ret.v, newOffset) =
      decodeGuardianSignatureCdUnchecked(encodedVaa, offset);
  }

  function decodeGuardianSignatureMemUnchecked(
    bytes memory encoded,
    uint offset
  ) internal pure returns (
    uint8 guardianIndex,
    bytes32 r,
    bytes32 s,
    uint8 v,
    uint newOffset
  ) { unchecked {
    (guardianIndex, offset) = encoded.asUint8MemUnchecked(offset);
    (r,             offset) = encoded.asBytes32MemUnchecked(offset);
    (s,             offset) = encoded.asBytes32MemUnchecked(offset);
    (v,             offset) = encoded.asUint8MemUnchecked(offset);
    v += SIGNATURE_RECOVERY_MAGIC;
    newOffset = offset;
  }}

  function decodeGuardianSignatureStructMemUnchecked(
    bytes memory encoded,
    uint offset
  ) internal pure returns (GuardianSignature memory ret, uint newOffset) {
    (ret.guardianIndex, ret.r, ret.s, ret.v, newOffset) =
      decodeGuardianSignatureMemUnchecked(encoded, offset);
  }

  function decodeVaaPayloadCd(
    bytes calldata encodedVaa,
    uint payloadOffset
  ) internal pure returns (bytes calldata payload) {
    payload = _decodeRemainderCd(encodedVaa, payloadOffset);
  }

  function decodeVaaPayloadMemUnchecked(
    bytes memory encoded,
    uint payloadOffset,
    uint vaaLength
  ) internal pure returns (bytes memory payload, uint newOffset) { unchecked {
    //check to avoid underflow in following subtraction
    payloadOffset.checkBound(vaaLength);
    (payload, newOffset) = encoded.sliceMemUnchecked(payloadOffset, vaaLength - payloadOffset);
  }}

  // ------------ Encoding ------------

  function encode(IWormhole.VM memory vm) internal pure returns (bytes memory) { unchecked {
    require(vm.version == HEADER_VERSION, "Invalid version");
    return abi.encodePacked(
      encodeVaaHeader(vm.guardianSetIndex, asGuardianSignatures(vm.signatures)),
      vm.timestamp,
      vm.nonce,
      vm.emitterChainId,
      vm.emitterAddress,
      vm.sequence,
      vm.consistencyLevel,
      vm.payload
    );
  }}

  function encodeVaaHeader(
    uint32 guardianSetIndex,
    GuardianSignature[] memory signatures
  ) internal pure returns (bytes memory) {
    bytes memory sigs;
    for (uint i = 0; i < signatures.length; ++i) {
      GuardianSignature memory sig = signatures[i];
      uint8 v = sig.v - SIGNATURE_RECOVERY_MAGIC; //deliberately checked
      sigs = bytes.concat(sigs, abi.encodePacked(sig.guardianIndex, sig.r, sig.s, v));
    }

    return abi.encodePacked(
      HEADER_VERSION,
      guardianSetIndex,
      uint8(signatures.length),
      sigs
    );
  }

  function encode(VaaHeader memory header) internal pure returns (bytes memory) {
    return encodeVaaHeader(header.guardianSetIndex, header.signatures);
  }

  function encodeVaaEnvelope(
    uint32  timestamp,
    uint32  nonce,
    uint16  emitterChainId,
    bytes32 emitterAddress,
    uint64  sequence,
    uint8   consistencyLevel
  ) internal pure returns (bytes memory) {
    return abi.encodePacked(
      timestamp,
      nonce,
      emitterChainId,
      emitterAddress,
      sequence,
      consistencyLevel
    );
  }

  function encode(VaaEnvelope memory envelope) internal pure returns (bytes memory) {
    return encodeVaaEnvelope(
      envelope.timestamp,
      envelope.nonce,
      envelope.emitterChainId,
      envelope.emitterAddress,
      envelope.sequence,
      envelope.consistencyLevel
    );
  }

  function encodeVaaBody(
    uint32  timestamp,
    uint32  nonce,
    uint16  emitterChainId,
    bytes32 emitterAddress,
    uint64  sequence,
    uint8   consistencyLevel,
    bytes memory payload
  ) internal pure returns (bytes memory) {
    return abi.encodePacked(
      encodeVaaEnvelope(
        timestamp,
        nonce,
        emitterChainId,
        emitterAddress,
        sequence,
        consistencyLevel
      ),
      payload
    );
  }

  function encode(VaaBody memory body) internal pure returns (bytes memory) {
    return abi.encodePacked(encode(body.envelope), body.payload);
  }

  function encodeVaa(
    uint32 guardianSetIndex,
    GuardianSignature[] memory signatures,
    uint32  timestamp,
    uint32  nonce,
    uint16  emitterChainId,
    bytes32 emitterAddress,
    uint64  sequence,
    uint8   consistencyLevel,
    bytes memory payload
  ) internal pure returns (bytes memory) {
    return abi.encodePacked(
      encodeVaaHeader(guardianSetIndex, signatures),
      encodeVaaBody(
        timestamp,
        nonce,
        emitterChainId,
        emitterAddress,
        sequence,
        consistencyLevel,
        payload
      )
    );
  }

  function encode(Vaa memory vaa) internal pure returns (bytes memory) {
    return encodeVaa(
      vaa.header.guardianSetIndex,
      vaa.header.signatures,
      vaa.envelope.timestamp,
      vaa.envelope.nonce,
      vaa.envelope.emitterChainId,
      vaa.envelope.emitterAddress,
      vaa.envelope.sequence,
      vaa.envelope.consistencyLevel,
      vaa.payload
    );
  }

  // ------------ Private ------------

  //we use this function over encodedVaa[offset:] to consistently get BytesParsing errors
  function _decodeRemainderCd(
    bytes calldata encodedVaa,
    uint offset
  ) private pure returns (bytes calldata remainder) { unchecked {
    //check to avoid underflow in following subtraction
    offset.checkBound(encodedVaa.length);
    (remainder, ) = encodedVaa.sliceCdUnchecked(offset, encodedVaa.length - offset);
  }}
}

using VaaLib for VaaHeader global;
using VaaLib for VaaEnvelope global;
using VaaLib for VaaBody global;
using VaaLib for Vaa global;

// SPDX-License-Identifier: MIT
pragma solidity 0.8.28;

import {IMachineEndpoint} from "./IMachineEndpoint.sol";
import {IMakinaGovernable} from "./IMakinaGovernable.sol";

interface ICaliberMailbox is IMachineEndpoint {
    event CaliberSet(address indexed caliber);
    event CooldownDurationChanged(uint256 oldDuration, uint256 newDuration);
    event HubBridgeAdapterSet(uint256 indexed bridgeId, address indexed adapter);

    /// @notice Accounting data of the caliber.
    /// @param netAum The net AUM expresses in caliber's accounting token.
    /// @param positions The list of positions of the caliber, each encoded as abi.encode(positionId, value, isDebt).
    /// @param baseTokens The list of base tokens of the caliber, each encoded as abi.encode(token, value).
    /// @param bridgesIn The list of incoming bridge amounts, each encoded as abi.encode(token, amount).
    /// @param bridgesOut The list of outgoing bridge amounts, each encoded as abi.encode(token, amount).
    struct SpokeCaliberAccountingData {
        uint256 netAum;
        bytes[] positions;
        bytes[] baseTokens;
        bytes[] bridgesIn;
        bytes[] bridgesOut;
    }

    /// @notice Initializer of the contract.
    /// @param mgParams The makina governable initialization parameters.
    /// @param initialCooldownDuration The duration of the cooldown period for outgoing bridge transfers.
    /// @param hubMachine The foreign address of the hub machine.
    function initialize(
        IMakinaGovernable.MakinaGovernableInitParams calldata mgParams,
        uint256 initialCooldownDuration,
        address hubMachine
    ) external;

    /// @notice Address of the associated caliber.
    function caliber() external view returns (address);

    /// @notice Duration of the cooldown period for outgoing bridge transfers.
    function cooldownDuration() external view returns (uint256);

    /// @notice Returns the foreign address of the Hub bridge adapter for a given bridge ID.
    /// @param bridgeId The ID of the bridge.
    function getHubBridgeAdapter(uint16 bridgeId) external view returns (address);

    /// @notice Chain ID of the hub.
    function hubChainId() external view returns (uint256);

    /// @notice Returns the accounting data of the associated caliber.
    /// @return data The accounting data.
    function getSpokeCaliberAccountingData() external view returns (SpokeCaliberAccountingData memory);

    /// @notice Sets the associated caliber address.
    /// @param caliber The address of the associated caliber.
    function setCaliber(address caliber) external;

    /// @notice Sets the duration of the cooldown period for outgoing bridge transfers.
    /// @param newCooldownDuration The new duration in seconds.
    function setCooldownDuration(uint256 newCooldownDuration) external;

    /// @notice Registers a hub bridge adapter.
    /// @param bridgeId The ID of the bridge.
    /// @param adapter The foreign address of the bridge adapter.
    function setHubBridgeAdapter(uint16 bridgeId, address adapter) external;
}

File 6 of 21 : Errors.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.28;

library Errors {
    error AccountingToken();
    error ActiveUpdatePending();
    error AlreadyAccountingAgent();
    error AlreadyBaseToken();
    error AlreadyPositionToken();
    error AlreadyRootGuardian();
    error AmountOutTooLow();
    error BridgeAdapterAlreadyExists();
    error BridgeAdapterDoesNotExist();
    error BridgeConfigNotSet();
    error BridgeStateMismatch();
    error CaliberAccountingStale(uint256 caliberChainId);
    error CaliberAlreadySet();
    error Create3ContractDeploymentFailed();
    error DirectManageFlashLoanCall();
    error EvmChainIdNotRegistered(uint256 chainId);
    error ExceededMaxDeposit();
    error ExceededMaxFee(uint256 fee, uint256 max);
    error ExceededMaxMint(uint256 shares, uint256 max);
    error ExceededMaxWithdraw(uint256 assets, uint256 max);
    error ForeignTokenNotRegistered(address token, uint256 foreignEvmChainId);
    error HubBridgeAdapterAlreadySet();
    error HubBridgeAdapterNotSet();
    error GroupIdNotProvided();
    error InstructionsMismatch();
    error InsufficientBalance();
    error InvalidAccounting();
    error InvalidAffectedToken();
    error InvalidBridgeTransferRoute();
    error InvalidChainId();
    error InvalidDebtFlag();
    error InvalidDecimals();
    error InvalidFeedRoute();
    error InvalidInputAmount();
    error InvalidInputToken();
    error InvalidInstructionProof();
    error InvalidInstructionType();
    error InvalidLzSentAmount();
    error InvalidOft();
    error InvalidOutputToken();
    error InvalidPositionChangeDirection();
    error InvalidRecipientChainId();
    error InvalidTransferStatus();
    error LocalTokenNotRegistered(address token, uint256 foreignEvmChainId);
    error LzChainIdNotRegistered(uint32 chainId);
    error LzForeignTokenNotRegistered(address token, uint256 foreignEvmChainId);
    error OftNotRegistered(address token);
    error ManageFlashLoanReentrantCall();
    error MaxAuthorizedPriceChangeExceeded();
    error MaxValueLossExceeded();
    error MessageAlreadyAuthorized();
    error Migrated();
    error MinOutputAmountExceedsInputAmount();
    error MismatchedLength();
    error MismatchedLengths();
    error MissingInstructionForGroup(uint256 groupId);
    error NegativeTokenPrice(address priceFeed);
    error NoPendingUpdate();
    error NonZeroBalance();
    error NotAccountingAgent();
    error NotBaseToken();
    error NotCaliber();
    error NotCaliberMailbox();
    error NotController();
    error NotFactory();
    error NotFlashLoanModule();
    error NotMachine();
    error NotMachineEndpoint();
    error NotMigrated();
    error NotPendingMachine();
    error NotPreDepositVault();
    error NotRootGuardian();
    error OngoingCooldown();
    error OutTransferDisabled();
    error PendingBridgeTransfer();
    error PositionAccountingStale(uint256 posId);
    error PositionDoesNotExist();
    error PositionIsGrouped();
    error PositionToken();
    error PositionTokenIsBaseToken();
    error PriceFeedRouteNotRegistered(address token);
    error PriceFeedStale(address priceFeed, uint256 updatedAt);
    error ProtectedAccountingAgent();
    error ProtectedRootGuardian();
    error Create3ProxyDeploymentFailed();
    error RecoveryMode();
    error SameRoot();
    error SlippageProtection();
    error SpokeBridgeAdapterAlreadySet();
    error SpokeBridgeAdapterNotSet();
    error SpokeCaliberAlreadySet();
    error StaleData();
    error SwapFailed();
    error SwapperTargetsNotSet();
    error TargetAlreadyExists();
    error UnauthorizedCaller();
    error UnauthorizedSource();
    error UnexpectedMessage();
    error UnexpectedResultLength();
    error InvalidBridgeId();
    error WhChainIdNotRegistered(uint16 chainId);
    error ZeroBridgeAdapterAddress();
    error ZeroChainId();
    error ZeroGroupId();
    error ZeroOftAddress();
    error ZeroPositionId();
    error ZeroSalt();
    error ZeroTokenAddress();
}

File 7 of 21 : BytesParsing.sol
// SPDX-License-Identifier: Apache 2
pragma solidity ^0.8.4;

import "wormhole-sdk/constants/Common.sol";

//This file appears comically large, but all unused functions are removed by the compiler.
library BytesParsing {
  error OutOfBounds(uint256 offset, uint256 length);
  error LengthMismatch(uint256 encodedLength, uint256 expectedLength);
  error InvalidBoolVal(uint8 val);

  /**
   * Implements runtime check of logic that accesses memory.
   * @param pastTheEndOffset The offset past the end relative to the accessed memory fragment.
   * @param length The length of the memory fragment accessed.
   */
  function checkBound(uint pastTheEndOffset, uint length) internal pure {
    if (pastTheEndOffset > length)
      revert OutOfBounds(pastTheEndOffset, length);
  }

  function checkLength(uint encodedLength, uint expectedLength) internal pure {
    if (encodedLength != expectedLength)
      revert LengthMismatch(encodedLength, expectedLength);
  }

  //Summary of all remaining functions:
  //
  //Each function has 2*2=4 versions:
  //  1. unchecked - no bounds checking (uses suffix `Unchecked`)
  //  2. checked (no suffix)
  //and (since Solidity does not allow overloading based on data location)
  //  1. calldata input (uses tag `Cd` )
  //  2. memory input (uses tag `Mem`)
  //
  //The canoncial/recommended way of parsing data to be maximally gas efficient is to prefer the
  //  calldata variants over the memory variants and to use the unchecked variants with a manual
  //  length check at the end using `checkLength` to ensure that encoded data was consumed exactly.
  //
  //WARNING: Neither variant uses safe math! It is up to the dev to ensure that offset and length
  //  values are sensible. In other words, verify user inputs before passing them on. Preferably,
  //  the format that's being parsed does not allow for such overflows in the first place by e.g.
  //  encoding lengths using at most 4 bytes, etc.
  //
  //Functions:
  //  Unless stated otherwise, all functions take an `encoded` bytes calldata/memory and an `offset`
  //    as input and return the parsed value and the next offset (i.e. the offset pointing to the
  //    next, unparsed byte).
  //
  // * slice(encoded, offset, length)
  // * sliceUint<n>Prefixed - n in {8, 16, 32} - parses n bytes of length prefix followed by data
  // * asAddress
  // * asBool
  // * asUint<8*n> - n in {1, ..., 32}, i.e. asUint8, asUint16, ..., asUint256
  // * asBytes<n>  - n in {1, ..., 32}, i.e. asBytes1, asBytes2, ..., asBytes32

  function sliceCdUnchecked(
    bytes calldata encoded,
    uint offset,
    uint length
  ) internal pure returns (bytes calldata ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      ret.offset := add(encoded.offset, offset)
      ret.length := length
      nextOffset := add(offset, length)
    }
  }

  function sliceMemUnchecked(
    bytes memory encoded,
    uint offset,
    uint length
  ) internal pure returns (bytes memory ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      nextOffset := add(offset, length)
      ret := mload(FREE_MEMORY_PTR)

      //Explanation on how we copy data here:
      //  The bytes type has the following layout in memory:
      //    [length: 32 bytes, data: length bytes]
      //  So if we allocate `bytes memory foo = new bytes(1);` then `foo` will be a pointer to 33
      //    bytes where the first 32 bytes contain the length and the last byte is the actual data.
      //  Since mload always loads 32 bytes of memory at once, we use our shift variable to align
      //    our reads so that our last read lines up exactly with the last 32 bytes of `encoded`.
      //  However this also means that if the length of `encoded` is not a multiple of 32 bytes, our
      //    first read will necessarily partly contain bytes from `encoded`'s 32 length bytes that
      //    will be written into the length part of our `ret` slice.
      //  We remedy this issue by writing the length of our `ret` slice at the end, thus
      //    overwritting those garbage bytes.

      //and(length, 31) is equivalent to `mod(length, 32)`, but 2 gas cheaper
      let shift := and(length, WORD_SIZE_MINUS_ONE)
      if iszero(shift) {
        shift := WORD_SIZE
      }

      let dest := add(ret, shift)
      let end := add(dest, length)
      for {
        let src := add(add(encoded, shift), offset)
      } lt(dest, end) {
        src := add(src, WORD_SIZE)
        dest := add(dest, WORD_SIZE)
      } {
        mstore(dest, mload(src))
      }

      mstore(ret, length)
      //When compiling with --via-ir then normally allocated memory (i.e. via new) will have 32 byte
      //  memory alignment and so we enforce the same memory alignment here.
      mstore(
        FREE_MEMORY_PTR,
        and(add(dest, WORD_SIZE_MINUS_ONE), not(WORD_SIZE_MINUS_ONE))
      )
    }
  }

/* -------------------------------------------------------------------------------------------------
Remaining library code below was auto-generated via the following js/node code:

const dlTag = dl => dl ? "Cd" : "Mem";
const dlType = dl =>dl ? "calldata" : "memory";

const funcs = [
  ...[8,16,32].map(n => [
    `sliceUint${n}Prefixed`,
    dl => [
      `uint${n} len;`,
      `(len, nextOffset) = asUint${n}${dlTag(dl)}Unchecked(encoded, offset);`,
      `(ret, nextOffset) = slice${dlTag(dl)}Unchecked(encoded, nextOffset, uint(len));`
    ],
    dl => `bytes ${dlType(dl)}`,
  ]), [
    `asAddress`,
    dl => [
      `uint160 tmp;`,
      `(tmp, nextOffset) = asUint160${dlTag(dl)}Unchecked(encoded, offset);`,
      `ret = address(tmp);`
    ],
    _ => `address`
  ], [
    `asBool`,
    dl => [
      `uint8 val;`,
      `(val, nextOffset) = asUint8${dlTag(dl)}Unchecked(encoded, offset);`,
      `if (val & 0xfe != 0)`,
      `  revert InvalidBoolVal(val);`,
      `uint cleanedVal = uint(val);`,
      `//skip 2x iszero opcode`,
      `/// @solidity memory-safe-assembly`,
      `assembly { ret := cleanedVal }`
    ],
    _ => `bool`
  ],
  ...Array.from({length: 32}, (_, i) => [
    `asUint${(i+1)*8}`,
    dl => [
      `/// @solidity memory-safe-assembly`,
      `assembly {`,
      `  nextOffset := add(offset, ${i+1})`,
      dl ? `  ret := shr(${256-(i+1)*8}, calldataload(add(encoded.offset, offset)))`
         : `  ret := mload(add(encoded, nextOffset))`,
      `}`
    ],
    _ => `uint${(i+1)*8}`
  ]),
  ...Array.from({length: 32}, (_, i) => [
    `asBytes${i+1}`,
    dl => [
      `/// @solidity memory-safe-assembly`,
      `assembly {`,
      `  ret := ${dl ? "calldataload" : "mload"}(add(encoded${dl ? ".offset" :""}, ${dl ? "offset" : "add(offset, WORD_SIZE)"}))`,
      `  nextOffset := add(offset, ${i+1})`,
      `}`
    ],
    _ => `bytes${i+1}`
  ]),
];

for (const dl of [true, false])
  console.log(
`function slice${dlTag(dl)}(
  bytes ${dlType(dl)} encoded,
  uint offset,
  uint length
) internal pure returns (bytes ${dlType(dl)} ret, uint nextOffset) {
  (ret, nextOffset) = slice${dlTag(dl)}Unchecked(encoded, offset, length);
  checkBound(nextOffset, encoded.length);
}
`);

for (const [name, code, ret] of funcs) {
  for (const dl of [true, false])
    console.log(
`function ${name}${dlTag(dl)}Unchecked(
  bytes ${dlType(dl)} encoded,
  uint offset
) internal pure returns (${ret(dl)} ret, uint nextOffset) {
  ${code(dl).join("\n  ")}
}

function ${name}${dlTag(dl)}(
  bytes ${dlType(dl)} encoded,
  uint offset
) internal pure returns (${ret(dl)} ret, uint nextOffset) {
  (ret, nextOffset) = ${name}${dlTag(dl)}Unchecked(encoded, offset);
  checkBound(nextOffset, encoded.length);
}
`);
}
------------------------------------------------------------------------------------------------- */

  function sliceCd(
    bytes calldata encoded,
    uint offset,
    uint length
  ) internal pure returns (bytes calldata ret, uint nextOffset) {
    (ret, nextOffset) = sliceCdUnchecked(encoded, offset, length);
    checkBound(nextOffset, encoded.length);
  }

  function sliceMem(
    bytes memory encoded,
    uint offset,
    uint length
  ) internal pure returns (bytes memory ret, uint nextOffset) {
    (ret, nextOffset) = sliceMemUnchecked(encoded, offset, length);
    checkBound(nextOffset, encoded.length);
  }

  function sliceUint8PrefixedCdUnchecked(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (bytes calldata ret, uint nextOffset) {
    uint8 len;
    (len, nextOffset) = asUint8CdUnchecked(encoded, offset);
    (ret, nextOffset) = sliceCdUnchecked(encoded, nextOffset, uint(len));
  }

  function sliceUint8PrefixedCd(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (bytes calldata ret, uint nextOffset) {
    (ret, nextOffset) = sliceUint8PrefixedCdUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function sliceUint8PrefixedMemUnchecked(
    bytes memory encoded,
    uint offset
  ) internal pure returns (bytes memory ret, uint nextOffset) {
    uint8 len;
    (len, nextOffset) = asUint8MemUnchecked(encoded, offset);
    (ret, nextOffset) = sliceMemUnchecked(encoded, nextOffset, uint(len));
  }

  function sliceUint8PrefixedMem(
    bytes memory encoded,
    uint offset
  ) internal pure returns (bytes memory ret, uint nextOffset) {
    (ret, nextOffset) = sliceUint8PrefixedMemUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function sliceUint16PrefixedCdUnchecked(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (bytes calldata ret, uint nextOffset) {
    uint16 len;
    (len, nextOffset) = asUint16CdUnchecked(encoded, offset);
    (ret, nextOffset) = sliceCdUnchecked(encoded, nextOffset, uint(len));
  }

  function sliceUint16PrefixedCd(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (bytes calldata ret, uint nextOffset) {
    (ret, nextOffset) = sliceUint16PrefixedCdUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function sliceUint16PrefixedMemUnchecked(
    bytes memory encoded,
    uint offset
  ) internal pure returns (bytes memory ret, uint nextOffset) {
    uint16 len;
    (len, nextOffset) = asUint16MemUnchecked(encoded, offset);
    (ret, nextOffset) = sliceMemUnchecked(encoded, nextOffset, uint(len));
  }

  function sliceUint16PrefixedMem(
    bytes memory encoded,
    uint offset
  ) internal pure returns (bytes memory ret, uint nextOffset) {
    (ret, nextOffset) = sliceUint16PrefixedMemUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function sliceUint32PrefixedCdUnchecked(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (bytes calldata ret, uint nextOffset) {
    uint32 len;
    (len, nextOffset) = asUint32CdUnchecked(encoded, offset);
    (ret, nextOffset) = sliceCdUnchecked(encoded, nextOffset, uint(len));
  }

  function sliceUint32PrefixedCd(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (bytes calldata ret, uint nextOffset) {
    (ret, nextOffset) = sliceUint32PrefixedCdUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function sliceUint32PrefixedMemUnchecked(
    bytes memory encoded,
    uint offset
  ) internal pure returns (bytes memory ret, uint nextOffset) {
    uint32 len;
    (len, nextOffset) = asUint32MemUnchecked(encoded, offset);
    (ret, nextOffset) = sliceMemUnchecked(encoded, nextOffset, uint(len));
  }

  function sliceUint32PrefixedMem(
    bytes memory encoded,
    uint offset
  ) internal pure returns (bytes memory ret, uint nextOffset) {
    (ret, nextOffset) = sliceUint32PrefixedMemUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asAddressCdUnchecked(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (address ret, uint nextOffset) {
    uint160 tmp;
    (tmp, nextOffset) = asUint160CdUnchecked(encoded, offset);
    ret = address(tmp);
  }

  function asAddressCd(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (address ret, uint nextOffset) {
    (ret, nextOffset) = asAddressCdUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asAddressMemUnchecked(
    bytes memory encoded,
    uint offset
  ) internal pure returns (address ret, uint nextOffset) {
    uint160 tmp;
    (tmp, nextOffset) = asUint160MemUnchecked(encoded, offset);
    ret = address(tmp);
  }

  function asAddressMem(
    bytes memory encoded,
    uint offset
  ) internal pure returns (address ret, uint nextOffset) {
    (ret, nextOffset) = asAddressMemUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asBoolCdUnchecked(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (bool ret, uint nextOffset) {
    uint8 val;
    (val, nextOffset) = asUint8CdUnchecked(encoded, offset);
    if (val & 0xfe != 0)
      revert InvalidBoolVal(val);
    uint cleanedVal = uint(val);
    //skip 2x iszero opcode
    /// @solidity memory-safe-assembly
    assembly { ret := cleanedVal }
  }

  function asBoolCd(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (bool ret, uint nextOffset) {
    (ret, nextOffset) = asBoolCdUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asBoolMemUnchecked(
    bytes memory encoded,
    uint offset
  ) internal pure returns (bool ret, uint nextOffset) {
    uint8 val;
    (val, nextOffset) = asUint8MemUnchecked(encoded, offset);
    if (val & 0xfe != 0)
      revert InvalidBoolVal(val);
    uint cleanedVal = uint(val);
    //skip 2x iszero opcode
    /// @solidity memory-safe-assembly
    assembly { ret := cleanedVal }
  }

  function asBoolMem(
    bytes memory encoded,
    uint offset
  ) internal pure returns (bool ret, uint nextOffset) {
    (ret, nextOffset) = asBoolMemUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asUint8CdUnchecked(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (uint8 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      nextOffset := add(offset, 1)
      ret := shr(248, calldataload(add(encoded.offset, offset)))
    }
  }

  function asUint8Cd(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (uint8 ret, uint nextOffset) {
    (ret, nextOffset) = asUint8CdUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asUint8MemUnchecked(
    bytes memory encoded,
    uint offset
  ) internal pure returns (uint8 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      nextOffset := add(offset, 1)
      ret := mload(add(encoded, nextOffset))
    }
  }

  function asUint8Mem(
    bytes memory encoded,
    uint offset
  ) internal pure returns (uint8 ret, uint nextOffset) {
    (ret, nextOffset) = asUint8MemUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asUint16CdUnchecked(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (uint16 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      nextOffset := add(offset, 2)
      ret := shr(240, calldataload(add(encoded.offset, offset)))
    }
  }

  function asUint16Cd(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (uint16 ret, uint nextOffset) {
    (ret, nextOffset) = asUint16CdUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asUint16MemUnchecked(
    bytes memory encoded,
    uint offset
  ) internal pure returns (uint16 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      nextOffset := add(offset, 2)
      ret := mload(add(encoded, nextOffset))
    }
  }

  function asUint16Mem(
    bytes memory encoded,
    uint offset
  ) internal pure returns (uint16 ret, uint nextOffset) {
    (ret, nextOffset) = asUint16MemUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asUint24CdUnchecked(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (uint24 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      nextOffset := add(offset, 3)
      ret := shr(232, calldataload(add(encoded.offset, offset)))
    }
  }

  function asUint24Cd(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (uint24 ret, uint nextOffset) {
    (ret, nextOffset) = asUint24CdUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asUint24MemUnchecked(
    bytes memory encoded,
    uint offset
  ) internal pure returns (uint24 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      nextOffset := add(offset, 3)
      ret := mload(add(encoded, nextOffset))
    }
  }

  function asUint24Mem(
    bytes memory encoded,
    uint offset
  ) internal pure returns (uint24 ret, uint nextOffset) {
    (ret, nextOffset) = asUint24MemUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asUint32CdUnchecked(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (uint32 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      nextOffset := add(offset, 4)
      ret := shr(224, calldataload(add(encoded.offset, offset)))
    }
  }

  function asUint32Cd(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (uint32 ret, uint nextOffset) {
    (ret, nextOffset) = asUint32CdUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asUint32MemUnchecked(
    bytes memory encoded,
    uint offset
  ) internal pure returns (uint32 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      nextOffset := add(offset, 4)
      ret := mload(add(encoded, nextOffset))
    }
  }

  function asUint32Mem(
    bytes memory encoded,
    uint offset
  ) internal pure returns (uint32 ret, uint nextOffset) {
    (ret, nextOffset) = asUint32MemUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asUint40CdUnchecked(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (uint40 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      nextOffset := add(offset, 5)
      ret := shr(216, calldataload(add(encoded.offset, offset)))
    }
  }

  function asUint40Cd(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (uint40 ret, uint nextOffset) {
    (ret, nextOffset) = asUint40CdUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asUint40MemUnchecked(
    bytes memory encoded,
    uint offset
  ) internal pure returns (uint40 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      nextOffset := add(offset, 5)
      ret := mload(add(encoded, nextOffset))
    }
  }

  function asUint40Mem(
    bytes memory encoded,
    uint offset
  ) internal pure returns (uint40 ret, uint nextOffset) {
    (ret, nextOffset) = asUint40MemUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asUint48CdUnchecked(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (uint48 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      nextOffset := add(offset, 6)
      ret := shr(208, calldataload(add(encoded.offset, offset)))
    }
  }

  function asUint48Cd(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (uint48 ret, uint nextOffset) {
    (ret, nextOffset) = asUint48CdUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asUint48MemUnchecked(
    bytes memory encoded,
    uint offset
  ) internal pure returns (uint48 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      nextOffset := add(offset, 6)
      ret := mload(add(encoded, nextOffset))
    }
  }

  function asUint48Mem(
    bytes memory encoded,
    uint offset
  ) internal pure returns (uint48 ret, uint nextOffset) {
    (ret, nextOffset) = asUint48MemUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asUint56CdUnchecked(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (uint56 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      nextOffset := add(offset, 7)
      ret := shr(200, calldataload(add(encoded.offset, offset)))
    }
  }

  function asUint56Cd(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (uint56 ret, uint nextOffset) {
    (ret, nextOffset) = asUint56CdUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asUint56MemUnchecked(
    bytes memory encoded,
    uint offset
  ) internal pure returns (uint56 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      nextOffset := add(offset, 7)
      ret := mload(add(encoded, nextOffset))
    }
  }

  function asUint56Mem(
    bytes memory encoded,
    uint offset
  ) internal pure returns (uint56 ret, uint nextOffset) {
    (ret, nextOffset) = asUint56MemUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asUint64CdUnchecked(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (uint64 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      nextOffset := add(offset, 8)
      ret := shr(192, calldataload(add(encoded.offset, offset)))
    }
  }

  function asUint64Cd(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (uint64 ret, uint nextOffset) {
    (ret, nextOffset) = asUint64CdUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asUint64MemUnchecked(
    bytes memory encoded,
    uint offset
  ) internal pure returns (uint64 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      nextOffset := add(offset, 8)
      ret := mload(add(encoded, nextOffset))
    }
  }

  function asUint64Mem(
    bytes memory encoded,
    uint offset
  ) internal pure returns (uint64 ret, uint nextOffset) {
    (ret, nextOffset) = asUint64MemUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asUint72CdUnchecked(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (uint72 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      nextOffset := add(offset, 9)
      ret := shr(184, calldataload(add(encoded.offset, offset)))
    }
  }

  function asUint72Cd(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (uint72 ret, uint nextOffset) {
    (ret, nextOffset) = asUint72CdUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asUint72MemUnchecked(
    bytes memory encoded,
    uint offset
  ) internal pure returns (uint72 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      nextOffset := add(offset, 9)
      ret := mload(add(encoded, nextOffset))
    }
  }

  function asUint72Mem(
    bytes memory encoded,
    uint offset
  ) internal pure returns (uint72 ret, uint nextOffset) {
    (ret, nextOffset) = asUint72MemUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asUint80CdUnchecked(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (uint80 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      nextOffset := add(offset, 10)
      ret := shr(176, calldataload(add(encoded.offset, offset)))
    }
  }

  function asUint80Cd(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (uint80 ret, uint nextOffset) {
    (ret, nextOffset) = asUint80CdUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asUint80MemUnchecked(
    bytes memory encoded,
    uint offset
  ) internal pure returns (uint80 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      nextOffset := add(offset, 10)
      ret := mload(add(encoded, nextOffset))
    }
  }

  function asUint80Mem(
    bytes memory encoded,
    uint offset
  ) internal pure returns (uint80 ret, uint nextOffset) {
    (ret, nextOffset) = asUint80MemUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asUint88CdUnchecked(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (uint88 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      nextOffset := add(offset, 11)
      ret := shr(168, calldataload(add(encoded.offset, offset)))
    }
  }

  function asUint88Cd(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (uint88 ret, uint nextOffset) {
    (ret, nextOffset) = asUint88CdUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asUint88MemUnchecked(
    bytes memory encoded,
    uint offset
  ) internal pure returns (uint88 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      nextOffset := add(offset, 11)
      ret := mload(add(encoded, nextOffset))
    }
  }

  function asUint88Mem(
    bytes memory encoded,
    uint offset
  ) internal pure returns (uint88 ret, uint nextOffset) {
    (ret, nextOffset) = asUint88MemUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asUint96CdUnchecked(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (uint96 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      nextOffset := add(offset, 12)
      ret := shr(160, calldataload(add(encoded.offset, offset)))
    }
  }

  function asUint96Cd(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (uint96 ret, uint nextOffset) {
    (ret, nextOffset) = asUint96CdUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asUint96MemUnchecked(
    bytes memory encoded,
    uint offset
  ) internal pure returns (uint96 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      nextOffset := add(offset, 12)
      ret := mload(add(encoded, nextOffset))
    }
  }

  function asUint96Mem(
    bytes memory encoded,
    uint offset
  ) internal pure returns (uint96 ret, uint nextOffset) {
    (ret, nextOffset) = asUint96MemUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asUint104CdUnchecked(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (uint104 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      nextOffset := add(offset, 13)
      ret := shr(152, calldataload(add(encoded.offset, offset)))
    }
  }

  function asUint104Cd(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (uint104 ret, uint nextOffset) {
    (ret, nextOffset) = asUint104CdUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asUint104MemUnchecked(
    bytes memory encoded,
    uint offset
  ) internal pure returns (uint104 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      nextOffset := add(offset, 13)
      ret := mload(add(encoded, nextOffset))
    }
  }

  function asUint104Mem(
    bytes memory encoded,
    uint offset
  ) internal pure returns (uint104 ret, uint nextOffset) {
    (ret, nextOffset) = asUint104MemUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asUint112CdUnchecked(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (uint112 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      nextOffset := add(offset, 14)
      ret := shr(144, calldataload(add(encoded.offset, offset)))
    }
  }

  function asUint112Cd(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (uint112 ret, uint nextOffset) {
    (ret, nextOffset) = asUint112CdUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asUint112MemUnchecked(
    bytes memory encoded,
    uint offset
  ) internal pure returns (uint112 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      nextOffset := add(offset, 14)
      ret := mload(add(encoded, nextOffset))
    }
  }

  function asUint112Mem(
    bytes memory encoded,
    uint offset
  ) internal pure returns (uint112 ret, uint nextOffset) {
    (ret, nextOffset) = asUint112MemUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asUint120CdUnchecked(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (uint120 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      nextOffset := add(offset, 15)
      ret := shr(136, calldataload(add(encoded.offset, offset)))
    }
  }

  function asUint120Cd(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (uint120 ret, uint nextOffset) {
    (ret, nextOffset) = asUint120CdUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asUint120MemUnchecked(
    bytes memory encoded,
    uint offset
  ) internal pure returns (uint120 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      nextOffset := add(offset, 15)
      ret := mload(add(encoded, nextOffset))
    }
  }

  function asUint120Mem(
    bytes memory encoded,
    uint offset
  ) internal pure returns (uint120 ret, uint nextOffset) {
    (ret, nextOffset) = asUint120MemUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asUint128CdUnchecked(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (uint128 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      nextOffset := add(offset, 16)
      ret := shr(128, calldataload(add(encoded.offset, offset)))
    }
  }

  function asUint128Cd(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (uint128 ret, uint nextOffset) {
    (ret, nextOffset) = asUint128CdUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asUint128MemUnchecked(
    bytes memory encoded,
    uint offset
  ) internal pure returns (uint128 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      nextOffset := add(offset, 16)
      ret := mload(add(encoded, nextOffset))
    }
  }

  function asUint128Mem(
    bytes memory encoded,
    uint offset
  ) internal pure returns (uint128 ret, uint nextOffset) {
    (ret, nextOffset) = asUint128MemUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asUint136CdUnchecked(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (uint136 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      nextOffset := add(offset, 17)
      ret := shr(120, calldataload(add(encoded.offset, offset)))
    }
  }

  function asUint136Cd(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (uint136 ret, uint nextOffset) {
    (ret, nextOffset) = asUint136CdUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asUint136MemUnchecked(
    bytes memory encoded,
    uint offset
  ) internal pure returns (uint136 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      nextOffset := add(offset, 17)
      ret := mload(add(encoded, nextOffset))
    }
  }

  function asUint136Mem(
    bytes memory encoded,
    uint offset
  ) internal pure returns (uint136 ret, uint nextOffset) {
    (ret, nextOffset) = asUint136MemUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asUint144CdUnchecked(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (uint144 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      nextOffset := add(offset, 18)
      ret := shr(112, calldataload(add(encoded.offset, offset)))
    }
  }

  function asUint144Cd(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (uint144 ret, uint nextOffset) {
    (ret, nextOffset) = asUint144CdUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asUint144MemUnchecked(
    bytes memory encoded,
    uint offset
  ) internal pure returns (uint144 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      nextOffset := add(offset, 18)
      ret := mload(add(encoded, nextOffset))
    }
  }

  function asUint144Mem(
    bytes memory encoded,
    uint offset
  ) internal pure returns (uint144 ret, uint nextOffset) {
    (ret, nextOffset) = asUint144MemUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asUint152CdUnchecked(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (uint152 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      nextOffset := add(offset, 19)
      ret := shr(104, calldataload(add(encoded.offset, offset)))
    }
  }

  function asUint152Cd(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (uint152 ret, uint nextOffset) {
    (ret, nextOffset) = asUint152CdUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asUint152MemUnchecked(
    bytes memory encoded,
    uint offset
  ) internal pure returns (uint152 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      nextOffset := add(offset, 19)
      ret := mload(add(encoded, nextOffset))
    }
  }

  function asUint152Mem(
    bytes memory encoded,
    uint offset
  ) internal pure returns (uint152 ret, uint nextOffset) {
    (ret, nextOffset) = asUint152MemUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asUint160CdUnchecked(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (uint160 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      nextOffset := add(offset, 20)
      ret := shr(96, calldataload(add(encoded.offset, offset)))
    }
  }

  function asUint160Cd(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (uint160 ret, uint nextOffset) {
    (ret, nextOffset) = asUint160CdUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asUint160MemUnchecked(
    bytes memory encoded,
    uint offset
  ) internal pure returns (uint160 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      nextOffset := add(offset, 20)
      ret := mload(add(encoded, nextOffset))
    }
  }

  function asUint160Mem(
    bytes memory encoded,
    uint offset
  ) internal pure returns (uint160 ret, uint nextOffset) {
    (ret, nextOffset) = asUint160MemUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asUint168CdUnchecked(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (uint168 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      nextOffset := add(offset, 21)
      ret := shr(88, calldataload(add(encoded.offset, offset)))
    }
  }

  function asUint168Cd(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (uint168 ret, uint nextOffset) {
    (ret, nextOffset) = asUint168CdUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asUint168MemUnchecked(
    bytes memory encoded,
    uint offset
  ) internal pure returns (uint168 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      nextOffset := add(offset, 21)
      ret := mload(add(encoded, nextOffset))
    }
  }

  function asUint168Mem(
    bytes memory encoded,
    uint offset
  ) internal pure returns (uint168 ret, uint nextOffset) {
    (ret, nextOffset) = asUint168MemUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asUint176CdUnchecked(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (uint176 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      nextOffset := add(offset, 22)
      ret := shr(80, calldataload(add(encoded.offset, offset)))
    }
  }

  function asUint176Cd(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (uint176 ret, uint nextOffset) {
    (ret, nextOffset) = asUint176CdUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asUint176MemUnchecked(
    bytes memory encoded,
    uint offset
  ) internal pure returns (uint176 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      nextOffset := add(offset, 22)
      ret := mload(add(encoded, nextOffset))
    }
  }

  function asUint176Mem(
    bytes memory encoded,
    uint offset
  ) internal pure returns (uint176 ret, uint nextOffset) {
    (ret, nextOffset) = asUint176MemUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asUint184CdUnchecked(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (uint184 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      nextOffset := add(offset, 23)
      ret := shr(72, calldataload(add(encoded.offset, offset)))
    }
  }

  function asUint184Cd(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (uint184 ret, uint nextOffset) {
    (ret, nextOffset) = asUint184CdUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asUint184MemUnchecked(
    bytes memory encoded,
    uint offset
  ) internal pure returns (uint184 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      nextOffset := add(offset, 23)
      ret := mload(add(encoded, nextOffset))
    }
  }

  function asUint184Mem(
    bytes memory encoded,
    uint offset
  ) internal pure returns (uint184 ret, uint nextOffset) {
    (ret, nextOffset) = asUint184MemUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asUint192CdUnchecked(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (uint192 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      nextOffset := add(offset, 24)
      ret := shr(64, calldataload(add(encoded.offset, offset)))
    }
  }

  function asUint192Cd(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (uint192 ret, uint nextOffset) {
    (ret, nextOffset) = asUint192CdUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asUint192MemUnchecked(
    bytes memory encoded,
    uint offset
  ) internal pure returns (uint192 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      nextOffset := add(offset, 24)
      ret := mload(add(encoded, nextOffset))
    }
  }

  function asUint192Mem(
    bytes memory encoded,
    uint offset
  ) internal pure returns (uint192 ret, uint nextOffset) {
    (ret, nextOffset) = asUint192MemUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asUint200CdUnchecked(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (uint200 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      nextOffset := add(offset, 25)
      ret := shr(56, calldataload(add(encoded.offset, offset)))
    }
  }

  function asUint200Cd(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (uint200 ret, uint nextOffset) {
    (ret, nextOffset) = asUint200CdUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asUint200MemUnchecked(
    bytes memory encoded,
    uint offset
  ) internal pure returns (uint200 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      nextOffset := add(offset, 25)
      ret := mload(add(encoded, nextOffset))
    }
  }

  function asUint200Mem(
    bytes memory encoded,
    uint offset
  ) internal pure returns (uint200 ret, uint nextOffset) {
    (ret, nextOffset) = asUint200MemUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asUint208CdUnchecked(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (uint208 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      nextOffset := add(offset, 26)
      ret := shr(48, calldataload(add(encoded.offset, offset)))
    }
  }

  function asUint208Cd(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (uint208 ret, uint nextOffset) {
    (ret, nextOffset) = asUint208CdUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asUint208MemUnchecked(
    bytes memory encoded,
    uint offset
  ) internal pure returns (uint208 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      nextOffset := add(offset, 26)
      ret := mload(add(encoded, nextOffset))
    }
  }

  function asUint208Mem(
    bytes memory encoded,
    uint offset
  ) internal pure returns (uint208 ret, uint nextOffset) {
    (ret, nextOffset) = asUint208MemUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asUint216CdUnchecked(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (uint216 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      nextOffset := add(offset, 27)
      ret := shr(40, calldataload(add(encoded.offset, offset)))
    }
  }

  function asUint216Cd(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (uint216 ret, uint nextOffset) {
    (ret, nextOffset) = asUint216CdUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asUint216MemUnchecked(
    bytes memory encoded,
    uint offset
  ) internal pure returns (uint216 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      nextOffset := add(offset, 27)
      ret := mload(add(encoded, nextOffset))
    }
  }

  function asUint216Mem(
    bytes memory encoded,
    uint offset
  ) internal pure returns (uint216 ret, uint nextOffset) {
    (ret, nextOffset) = asUint216MemUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asUint224CdUnchecked(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (uint224 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      nextOffset := add(offset, 28)
      ret := shr(32, calldataload(add(encoded.offset, offset)))
    }
  }

  function asUint224Cd(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (uint224 ret, uint nextOffset) {
    (ret, nextOffset) = asUint224CdUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asUint224MemUnchecked(
    bytes memory encoded,
    uint offset
  ) internal pure returns (uint224 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      nextOffset := add(offset, 28)
      ret := mload(add(encoded, nextOffset))
    }
  }

  function asUint224Mem(
    bytes memory encoded,
    uint offset
  ) internal pure returns (uint224 ret, uint nextOffset) {
    (ret, nextOffset) = asUint224MemUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asUint232CdUnchecked(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (uint232 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      nextOffset := add(offset, 29)
      ret := shr(24, calldataload(add(encoded.offset, offset)))
    }
  }

  function asUint232Cd(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (uint232 ret, uint nextOffset) {
    (ret, nextOffset) = asUint232CdUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asUint232MemUnchecked(
    bytes memory encoded,
    uint offset
  ) internal pure returns (uint232 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      nextOffset := add(offset, 29)
      ret := mload(add(encoded, nextOffset))
    }
  }

  function asUint232Mem(
    bytes memory encoded,
    uint offset
  ) internal pure returns (uint232 ret, uint nextOffset) {
    (ret, nextOffset) = asUint232MemUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asUint240CdUnchecked(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (uint240 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      nextOffset := add(offset, 30)
      ret := shr(16, calldataload(add(encoded.offset, offset)))
    }
  }

  function asUint240Cd(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (uint240 ret, uint nextOffset) {
    (ret, nextOffset) = asUint240CdUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asUint240MemUnchecked(
    bytes memory encoded,
    uint offset
  ) internal pure returns (uint240 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      nextOffset := add(offset, 30)
      ret := mload(add(encoded, nextOffset))
    }
  }

  function asUint240Mem(
    bytes memory encoded,
    uint offset
  ) internal pure returns (uint240 ret, uint nextOffset) {
    (ret, nextOffset) = asUint240MemUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asUint248CdUnchecked(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (uint248 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      nextOffset := add(offset, 31)
      ret := shr(8, calldataload(add(encoded.offset, offset)))
    }
  }

  function asUint248Cd(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (uint248 ret, uint nextOffset) {
    (ret, nextOffset) = asUint248CdUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asUint248MemUnchecked(
    bytes memory encoded,
    uint offset
  ) internal pure returns (uint248 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      nextOffset := add(offset, 31)
      ret := mload(add(encoded, nextOffset))
    }
  }

  function asUint248Mem(
    bytes memory encoded,
    uint offset
  ) internal pure returns (uint248 ret, uint nextOffset) {
    (ret, nextOffset) = asUint248MemUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asUint256CdUnchecked(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (uint256 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      nextOffset := add(offset, 32)
      ret := shr(0, calldataload(add(encoded.offset, offset)))
    }
  }

  function asUint256Cd(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (uint256 ret, uint nextOffset) {
    (ret, nextOffset) = asUint256CdUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asUint256MemUnchecked(
    bytes memory encoded,
    uint offset
  ) internal pure returns (uint256 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      nextOffset := add(offset, 32)
      ret := mload(add(encoded, nextOffset))
    }
  }

  function asUint256Mem(
    bytes memory encoded,
    uint offset
  ) internal pure returns (uint256 ret, uint nextOffset) {
    (ret, nextOffset) = asUint256MemUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asBytes1CdUnchecked(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (bytes1 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      ret := calldataload(add(encoded.offset, offset))
      nextOffset := add(offset, 1)
    }
  }

  function asBytes1Cd(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (bytes1 ret, uint nextOffset) {
    (ret, nextOffset) = asBytes1CdUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asBytes1MemUnchecked(
    bytes memory encoded,
    uint offset
  ) internal pure returns (bytes1 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      ret := mload(add(encoded, add(offset, WORD_SIZE)))
      nextOffset := add(offset, 1)
    }
  }

  function asBytes1Mem(
    bytes memory encoded,
    uint offset
  ) internal pure returns (bytes1 ret, uint nextOffset) {
    (ret, nextOffset) = asBytes1MemUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asBytes2CdUnchecked(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (bytes2 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      ret := calldataload(add(encoded.offset, offset))
      nextOffset := add(offset, 2)
    }
  }

  function asBytes2Cd(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (bytes2 ret, uint nextOffset) {
    (ret, nextOffset) = asBytes2CdUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asBytes2MemUnchecked(
    bytes memory encoded,
    uint offset
  ) internal pure returns (bytes2 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      ret := mload(add(encoded, add(offset, WORD_SIZE)))
      nextOffset := add(offset, 2)
    }
  }

  function asBytes2Mem(
    bytes memory encoded,
    uint offset
  ) internal pure returns (bytes2 ret, uint nextOffset) {
    (ret, nextOffset) = asBytes2MemUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asBytes3CdUnchecked(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (bytes3 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      ret := calldataload(add(encoded.offset, offset))
      nextOffset := add(offset, 3)
    }
  }

  function asBytes3Cd(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (bytes3 ret, uint nextOffset) {
    (ret, nextOffset) = asBytes3CdUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asBytes3MemUnchecked(
    bytes memory encoded,
    uint offset
  ) internal pure returns (bytes3 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      ret := mload(add(encoded, add(offset, WORD_SIZE)))
      nextOffset := add(offset, 3)
    }
  }

  function asBytes3Mem(
    bytes memory encoded,
    uint offset
  ) internal pure returns (bytes3 ret, uint nextOffset) {
    (ret, nextOffset) = asBytes3MemUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asBytes4CdUnchecked(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (bytes4 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      ret := calldataload(add(encoded.offset, offset))
      nextOffset := add(offset, 4)
    }
  }

  function asBytes4Cd(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (bytes4 ret, uint nextOffset) {
    (ret, nextOffset) = asBytes4CdUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asBytes4MemUnchecked(
    bytes memory encoded,
    uint offset
  ) internal pure returns (bytes4 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      ret := mload(add(encoded, add(offset, WORD_SIZE)))
      nextOffset := add(offset, 4)
    }
  }

  function asBytes4Mem(
    bytes memory encoded,
    uint offset
  ) internal pure returns (bytes4 ret, uint nextOffset) {
    (ret, nextOffset) = asBytes4MemUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asBytes5CdUnchecked(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (bytes5 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      ret := calldataload(add(encoded.offset, offset))
      nextOffset := add(offset, 5)
    }
  }

  function asBytes5Cd(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (bytes5 ret, uint nextOffset) {
    (ret, nextOffset) = asBytes5CdUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asBytes5MemUnchecked(
    bytes memory encoded,
    uint offset
  ) internal pure returns (bytes5 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      ret := mload(add(encoded, add(offset, WORD_SIZE)))
      nextOffset := add(offset, 5)
    }
  }

  function asBytes5Mem(
    bytes memory encoded,
    uint offset
  ) internal pure returns (bytes5 ret, uint nextOffset) {
    (ret, nextOffset) = asBytes5MemUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asBytes6CdUnchecked(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (bytes6 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      ret := calldataload(add(encoded.offset, offset))
      nextOffset := add(offset, 6)
    }
  }

  function asBytes6Cd(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (bytes6 ret, uint nextOffset) {
    (ret, nextOffset) = asBytes6CdUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asBytes6MemUnchecked(
    bytes memory encoded,
    uint offset
  ) internal pure returns (bytes6 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      ret := mload(add(encoded, add(offset, WORD_SIZE)))
      nextOffset := add(offset, 6)
    }
  }

  function asBytes6Mem(
    bytes memory encoded,
    uint offset
  ) internal pure returns (bytes6 ret, uint nextOffset) {
    (ret, nextOffset) = asBytes6MemUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asBytes7CdUnchecked(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (bytes7 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      ret := calldataload(add(encoded.offset, offset))
      nextOffset := add(offset, 7)
    }
  }

  function asBytes7Cd(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (bytes7 ret, uint nextOffset) {
    (ret, nextOffset) = asBytes7CdUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asBytes7MemUnchecked(
    bytes memory encoded,
    uint offset
  ) internal pure returns (bytes7 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      ret := mload(add(encoded, add(offset, WORD_SIZE)))
      nextOffset := add(offset, 7)
    }
  }

  function asBytes7Mem(
    bytes memory encoded,
    uint offset
  ) internal pure returns (bytes7 ret, uint nextOffset) {
    (ret, nextOffset) = asBytes7MemUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asBytes8CdUnchecked(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (bytes8 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      ret := calldataload(add(encoded.offset, offset))
      nextOffset := add(offset, 8)
    }
  }

  function asBytes8Cd(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (bytes8 ret, uint nextOffset) {
    (ret, nextOffset) = asBytes8CdUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asBytes8MemUnchecked(
    bytes memory encoded,
    uint offset
  ) internal pure returns (bytes8 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      ret := mload(add(encoded, add(offset, WORD_SIZE)))
      nextOffset := add(offset, 8)
    }
  }

  function asBytes8Mem(
    bytes memory encoded,
    uint offset
  ) internal pure returns (bytes8 ret, uint nextOffset) {
    (ret, nextOffset) = asBytes8MemUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asBytes9CdUnchecked(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (bytes9 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      ret := calldataload(add(encoded.offset, offset))
      nextOffset := add(offset, 9)
    }
  }

  function asBytes9Cd(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (bytes9 ret, uint nextOffset) {
    (ret, nextOffset) = asBytes9CdUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asBytes9MemUnchecked(
    bytes memory encoded,
    uint offset
  ) internal pure returns (bytes9 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      ret := mload(add(encoded, add(offset, WORD_SIZE)))
      nextOffset := add(offset, 9)
    }
  }

  function asBytes9Mem(
    bytes memory encoded,
    uint offset
  ) internal pure returns (bytes9 ret, uint nextOffset) {
    (ret, nextOffset) = asBytes9MemUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asBytes10CdUnchecked(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (bytes10 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      ret := calldataload(add(encoded.offset, offset))
      nextOffset := add(offset, 10)
    }
  }

  function asBytes10Cd(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (bytes10 ret, uint nextOffset) {
    (ret, nextOffset) = asBytes10CdUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asBytes10MemUnchecked(
    bytes memory encoded,
    uint offset
  ) internal pure returns (bytes10 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      ret := mload(add(encoded, add(offset, WORD_SIZE)))
      nextOffset := add(offset, 10)
    }
  }

  function asBytes10Mem(
    bytes memory encoded,
    uint offset
  ) internal pure returns (bytes10 ret, uint nextOffset) {
    (ret, nextOffset) = asBytes10MemUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asBytes11CdUnchecked(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (bytes11 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      ret := calldataload(add(encoded.offset, offset))
      nextOffset := add(offset, 11)
    }
  }

  function asBytes11Cd(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (bytes11 ret, uint nextOffset) {
    (ret, nextOffset) = asBytes11CdUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asBytes11MemUnchecked(
    bytes memory encoded,
    uint offset
  ) internal pure returns (bytes11 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      ret := mload(add(encoded, add(offset, WORD_SIZE)))
      nextOffset := add(offset, 11)
    }
  }

  function asBytes11Mem(
    bytes memory encoded,
    uint offset
  ) internal pure returns (bytes11 ret, uint nextOffset) {
    (ret, nextOffset) = asBytes11MemUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asBytes12CdUnchecked(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (bytes12 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      ret := calldataload(add(encoded.offset, offset))
      nextOffset := add(offset, 12)
    }
  }

  function asBytes12Cd(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (bytes12 ret, uint nextOffset) {
    (ret, nextOffset) = asBytes12CdUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asBytes12MemUnchecked(
    bytes memory encoded,
    uint offset
  ) internal pure returns (bytes12 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      ret := mload(add(encoded, add(offset, WORD_SIZE)))
      nextOffset := add(offset, 12)
    }
  }

  function asBytes12Mem(
    bytes memory encoded,
    uint offset
  ) internal pure returns (bytes12 ret, uint nextOffset) {
    (ret, nextOffset) = asBytes12MemUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asBytes13CdUnchecked(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (bytes13 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      ret := calldataload(add(encoded.offset, offset))
      nextOffset := add(offset, 13)
    }
  }

  function asBytes13Cd(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (bytes13 ret, uint nextOffset) {
    (ret, nextOffset) = asBytes13CdUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asBytes13MemUnchecked(
    bytes memory encoded,
    uint offset
  ) internal pure returns (bytes13 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      ret := mload(add(encoded, add(offset, WORD_SIZE)))
      nextOffset := add(offset, 13)
    }
  }

  function asBytes13Mem(
    bytes memory encoded,
    uint offset
  ) internal pure returns (bytes13 ret, uint nextOffset) {
    (ret, nextOffset) = asBytes13MemUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asBytes14CdUnchecked(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (bytes14 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      ret := calldataload(add(encoded.offset, offset))
      nextOffset := add(offset, 14)
    }
  }

  function asBytes14Cd(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (bytes14 ret, uint nextOffset) {
    (ret, nextOffset) = asBytes14CdUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asBytes14MemUnchecked(
    bytes memory encoded,
    uint offset
  ) internal pure returns (bytes14 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      ret := mload(add(encoded, add(offset, WORD_SIZE)))
      nextOffset := add(offset, 14)
    }
  }

  function asBytes14Mem(
    bytes memory encoded,
    uint offset
  ) internal pure returns (bytes14 ret, uint nextOffset) {
    (ret, nextOffset) = asBytes14MemUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asBytes15CdUnchecked(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (bytes15 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      ret := calldataload(add(encoded.offset, offset))
      nextOffset := add(offset, 15)
    }
  }

  function asBytes15Cd(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (bytes15 ret, uint nextOffset) {
    (ret, nextOffset) = asBytes15CdUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asBytes15MemUnchecked(
    bytes memory encoded,
    uint offset
  ) internal pure returns (bytes15 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      ret := mload(add(encoded, add(offset, WORD_SIZE)))
      nextOffset := add(offset, 15)
    }
  }

  function asBytes15Mem(
    bytes memory encoded,
    uint offset
  ) internal pure returns (bytes15 ret, uint nextOffset) {
    (ret, nextOffset) = asBytes15MemUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asBytes16CdUnchecked(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (bytes16 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      ret := calldataload(add(encoded.offset, offset))
      nextOffset := add(offset, 16)
    }
  }

  function asBytes16Cd(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (bytes16 ret, uint nextOffset) {
    (ret, nextOffset) = asBytes16CdUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asBytes16MemUnchecked(
    bytes memory encoded,
    uint offset
  ) internal pure returns (bytes16 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      ret := mload(add(encoded, add(offset, WORD_SIZE)))
      nextOffset := add(offset, 16)
    }
  }

  function asBytes16Mem(
    bytes memory encoded,
    uint offset
  ) internal pure returns (bytes16 ret, uint nextOffset) {
    (ret, nextOffset) = asBytes16MemUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asBytes17CdUnchecked(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (bytes17 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      ret := calldataload(add(encoded.offset, offset))
      nextOffset := add(offset, 17)
    }
  }

  function asBytes17Cd(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (bytes17 ret, uint nextOffset) {
    (ret, nextOffset) = asBytes17CdUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asBytes17MemUnchecked(
    bytes memory encoded,
    uint offset
  ) internal pure returns (bytes17 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      ret := mload(add(encoded, add(offset, WORD_SIZE)))
      nextOffset := add(offset, 17)
    }
  }

  function asBytes17Mem(
    bytes memory encoded,
    uint offset
  ) internal pure returns (bytes17 ret, uint nextOffset) {
    (ret, nextOffset) = asBytes17MemUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asBytes18CdUnchecked(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (bytes18 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      ret := calldataload(add(encoded.offset, offset))
      nextOffset := add(offset, 18)
    }
  }

  function asBytes18Cd(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (bytes18 ret, uint nextOffset) {
    (ret, nextOffset) = asBytes18CdUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asBytes18MemUnchecked(
    bytes memory encoded,
    uint offset
  ) internal pure returns (bytes18 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      ret := mload(add(encoded, add(offset, WORD_SIZE)))
      nextOffset := add(offset, 18)
    }
  }

  function asBytes18Mem(
    bytes memory encoded,
    uint offset
  ) internal pure returns (bytes18 ret, uint nextOffset) {
    (ret, nextOffset) = asBytes18MemUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asBytes19CdUnchecked(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (bytes19 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      ret := calldataload(add(encoded.offset, offset))
      nextOffset := add(offset, 19)
    }
  }

  function asBytes19Cd(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (bytes19 ret, uint nextOffset) {
    (ret, nextOffset) = asBytes19CdUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asBytes19MemUnchecked(
    bytes memory encoded,
    uint offset
  ) internal pure returns (bytes19 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      ret := mload(add(encoded, add(offset, WORD_SIZE)))
      nextOffset := add(offset, 19)
    }
  }

  function asBytes19Mem(
    bytes memory encoded,
    uint offset
  ) internal pure returns (bytes19 ret, uint nextOffset) {
    (ret, nextOffset) = asBytes19MemUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asBytes20CdUnchecked(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (bytes20 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      ret := calldataload(add(encoded.offset, offset))
      nextOffset := add(offset, 20)
    }
  }

  function asBytes20Cd(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (bytes20 ret, uint nextOffset) {
    (ret, nextOffset) = asBytes20CdUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asBytes20MemUnchecked(
    bytes memory encoded,
    uint offset
  ) internal pure returns (bytes20 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      ret := mload(add(encoded, add(offset, WORD_SIZE)))
      nextOffset := add(offset, 20)
    }
  }

  function asBytes20Mem(
    bytes memory encoded,
    uint offset
  ) internal pure returns (bytes20 ret, uint nextOffset) {
    (ret, nextOffset) = asBytes20MemUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asBytes21CdUnchecked(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (bytes21 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      ret := calldataload(add(encoded.offset, offset))
      nextOffset := add(offset, 21)
    }
  }

  function asBytes21Cd(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (bytes21 ret, uint nextOffset) {
    (ret, nextOffset) = asBytes21CdUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asBytes21MemUnchecked(
    bytes memory encoded,
    uint offset
  ) internal pure returns (bytes21 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      ret := mload(add(encoded, add(offset, WORD_SIZE)))
      nextOffset := add(offset, 21)
    }
  }

  function asBytes21Mem(
    bytes memory encoded,
    uint offset
  ) internal pure returns (bytes21 ret, uint nextOffset) {
    (ret, nextOffset) = asBytes21MemUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asBytes22CdUnchecked(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (bytes22 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      ret := calldataload(add(encoded.offset, offset))
      nextOffset := add(offset, 22)
    }
  }

  function asBytes22Cd(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (bytes22 ret, uint nextOffset) {
    (ret, nextOffset) = asBytes22CdUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asBytes22MemUnchecked(
    bytes memory encoded,
    uint offset
  ) internal pure returns (bytes22 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      ret := mload(add(encoded, add(offset, WORD_SIZE)))
      nextOffset := add(offset, 22)
    }
  }

  function asBytes22Mem(
    bytes memory encoded,
    uint offset
  ) internal pure returns (bytes22 ret, uint nextOffset) {
    (ret, nextOffset) = asBytes22MemUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asBytes23CdUnchecked(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (bytes23 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      ret := calldataload(add(encoded.offset, offset))
      nextOffset := add(offset, 23)
    }
  }

  function asBytes23Cd(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (bytes23 ret, uint nextOffset) {
    (ret, nextOffset) = asBytes23CdUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asBytes23MemUnchecked(
    bytes memory encoded,
    uint offset
  ) internal pure returns (bytes23 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      ret := mload(add(encoded, add(offset, WORD_SIZE)))
      nextOffset := add(offset, 23)
    }
  }

  function asBytes23Mem(
    bytes memory encoded,
    uint offset
  ) internal pure returns (bytes23 ret, uint nextOffset) {
    (ret, nextOffset) = asBytes23MemUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asBytes24CdUnchecked(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (bytes24 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      ret := calldataload(add(encoded.offset, offset))
      nextOffset := add(offset, 24)
    }
  }

  function asBytes24Cd(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (bytes24 ret, uint nextOffset) {
    (ret, nextOffset) = asBytes24CdUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asBytes24MemUnchecked(
    bytes memory encoded,
    uint offset
  ) internal pure returns (bytes24 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      ret := mload(add(encoded, add(offset, WORD_SIZE)))
      nextOffset := add(offset, 24)
    }
  }

  function asBytes24Mem(
    bytes memory encoded,
    uint offset
  ) internal pure returns (bytes24 ret, uint nextOffset) {
    (ret, nextOffset) = asBytes24MemUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asBytes25CdUnchecked(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (bytes25 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      ret := calldataload(add(encoded.offset, offset))
      nextOffset := add(offset, 25)
    }
  }

  function asBytes25Cd(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (bytes25 ret, uint nextOffset) {
    (ret, nextOffset) = asBytes25CdUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asBytes25MemUnchecked(
    bytes memory encoded,
    uint offset
  ) internal pure returns (bytes25 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      ret := mload(add(encoded, add(offset, WORD_SIZE)))
      nextOffset := add(offset, 25)
    }
  }

  function asBytes25Mem(
    bytes memory encoded,
    uint offset
  ) internal pure returns (bytes25 ret, uint nextOffset) {
    (ret, nextOffset) = asBytes25MemUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asBytes26CdUnchecked(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (bytes26 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      ret := calldataload(add(encoded.offset, offset))
      nextOffset := add(offset, 26)
    }
  }

  function asBytes26Cd(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (bytes26 ret, uint nextOffset) {
    (ret, nextOffset) = asBytes26CdUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asBytes26MemUnchecked(
    bytes memory encoded,
    uint offset
  ) internal pure returns (bytes26 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      ret := mload(add(encoded, add(offset, WORD_SIZE)))
      nextOffset := add(offset, 26)
    }
  }

  function asBytes26Mem(
    bytes memory encoded,
    uint offset
  ) internal pure returns (bytes26 ret, uint nextOffset) {
    (ret, nextOffset) = asBytes26MemUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asBytes27CdUnchecked(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (bytes27 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      ret := calldataload(add(encoded.offset, offset))
      nextOffset := add(offset, 27)
    }
  }

  function asBytes27Cd(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (bytes27 ret, uint nextOffset) {
    (ret, nextOffset) = asBytes27CdUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asBytes27MemUnchecked(
    bytes memory encoded,
    uint offset
  ) internal pure returns (bytes27 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      ret := mload(add(encoded, add(offset, WORD_SIZE)))
      nextOffset := add(offset, 27)
    }
  }

  function asBytes27Mem(
    bytes memory encoded,
    uint offset
  ) internal pure returns (bytes27 ret, uint nextOffset) {
    (ret, nextOffset) = asBytes27MemUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asBytes28CdUnchecked(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (bytes28 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      ret := calldataload(add(encoded.offset, offset))
      nextOffset := add(offset, 28)
    }
  }

  function asBytes28Cd(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (bytes28 ret, uint nextOffset) {
    (ret, nextOffset) = asBytes28CdUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asBytes28MemUnchecked(
    bytes memory encoded,
    uint offset
  ) internal pure returns (bytes28 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      ret := mload(add(encoded, add(offset, WORD_SIZE)))
      nextOffset := add(offset, 28)
    }
  }

  function asBytes28Mem(
    bytes memory encoded,
    uint offset
  ) internal pure returns (bytes28 ret, uint nextOffset) {
    (ret, nextOffset) = asBytes28MemUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asBytes29CdUnchecked(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (bytes29 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      ret := calldataload(add(encoded.offset, offset))
      nextOffset := add(offset, 29)
    }
  }

  function asBytes29Cd(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (bytes29 ret, uint nextOffset) {
    (ret, nextOffset) = asBytes29CdUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asBytes29MemUnchecked(
    bytes memory encoded,
    uint offset
  ) internal pure returns (bytes29 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      ret := mload(add(encoded, add(offset, WORD_SIZE)))
      nextOffset := add(offset, 29)
    }
  }

  function asBytes29Mem(
    bytes memory encoded,
    uint offset
  ) internal pure returns (bytes29 ret, uint nextOffset) {
    (ret, nextOffset) = asBytes29MemUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asBytes30CdUnchecked(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (bytes30 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      ret := calldataload(add(encoded.offset, offset))
      nextOffset := add(offset, 30)
    }
  }

  function asBytes30Cd(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (bytes30 ret, uint nextOffset) {
    (ret, nextOffset) = asBytes30CdUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asBytes30MemUnchecked(
    bytes memory encoded,
    uint offset
  ) internal pure returns (bytes30 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      ret := mload(add(encoded, add(offset, WORD_SIZE)))
      nextOffset := add(offset, 30)
    }
  }

  function asBytes30Mem(
    bytes memory encoded,
    uint offset
  ) internal pure returns (bytes30 ret, uint nextOffset) {
    (ret, nextOffset) = asBytes30MemUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asBytes31CdUnchecked(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (bytes31 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      ret := calldataload(add(encoded.offset, offset))
      nextOffset := add(offset, 31)
    }
  }

  function asBytes31Cd(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (bytes31 ret, uint nextOffset) {
    (ret, nextOffset) = asBytes31CdUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asBytes31MemUnchecked(
    bytes memory encoded,
    uint offset
  ) internal pure returns (bytes31 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      ret := mload(add(encoded, add(offset, WORD_SIZE)))
      nextOffset := add(offset, 31)
    }
  }

  function asBytes31Mem(
    bytes memory encoded,
    uint offset
  ) internal pure returns (bytes31 ret, uint nextOffset) {
    (ret, nextOffset) = asBytes31MemUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asBytes32CdUnchecked(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (bytes32 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      ret := calldataload(add(encoded.offset, offset))
      nextOffset := add(offset, 32)
    }
  }

  function asBytes32Cd(
    bytes calldata encoded,
    uint offset
  ) internal pure returns (bytes32 ret, uint nextOffset) {
    (ret, nextOffset) = asBytes32CdUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }

  function asBytes32MemUnchecked(
    bytes memory encoded,
    uint offset
  ) internal pure returns (bytes32 ret, uint nextOffset) {
    /// @solidity memory-safe-assembly
    assembly {
      ret := mload(add(encoded, add(offset, WORD_SIZE)))
      nextOffset := add(offset, 32)
    }
  }

  function asBytes32Mem(
    bytes memory encoded,
    uint offset
  ) internal pure returns (bytes32 ret, uint nextOffset) {
    (ret, nextOffset) = asBytes32MemUnchecked(encoded, offset);
    checkBound(nextOffset, encoded.length);
  }
}

// SPDX-License-Identifier: Apache 2
pragma solidity ^0.8.14;

import {IWormhole}                          from "wormhole-sdk/interfaces/IWormhole.sol";
import {WORD_SIZE}                          from "wormhole-sdk/constants/Common.sol";
import {BytesParsing}                       from "wormhole-sdk/libraries/BytesParsing.sol";
import {UncheckedIndexing}                  from "wormhole-sdk/libraries/UncheckedIndexing.sol";
import {GuardianSignature, VaaBody, VaaLib} from "wormhole-sdk/libraries/VaaLib.sol";
import {eagerAnd, eagerOr}                  from "wormhole-sdk/Utils.sol";

// ╭────────────────────────────────────────────────────────────────────────────────────────╮
// │ Library for "client-side" parsing and verification of VAAs / Guardian signed messages. │
// ╰────────────────────────────────────────────────────────────────────────────────────────╯
//
// Offers significant gas savings over calling the CoreBridge due to:
//  * its much more efficient implementation
//  * by avoiding external call encoding and decoding overheads
// Comes at the expense of larger contract bytecode.
//
// When verifying a single VAA, decodeAndVerifyVaaCd is maximally gas efficient.
// However, when verifying multiple VAAs/signed messages, the most gas efficient choice is to do
//   some manual parsing (e.g. by directly using VaaLib) and to explicitly fetch the guardian set
//   (which is very likely to be the same for all messages) via `getGuardiansOrEmpty` or
//   `getGuardiansOrLatest` and reuse it, rather than to look it up again and again, as a call
//   to decodeAndVerifyVaaCd would do.
//
// Function Overview:
//  * decodeAndVerifyVaa: Cd and Mem variants for verifying a VAA and decoding/returning its body
//  * isVerifiedByQuorum: 2x2=4 variants for verifying a hash (directly passed to ecrecover):
//    * Cd <> Mem
//    * guardianSetIndex:
//      - fetches the guardian set from the CoreBridge with a fallback to the latest guardian set
//          if the specified one is expired as an ad-hoc repair attempt
//    * guardianAddresses:
//      - only tries to verify against the provided guardian addresses, no fallback
//  * readUnchecked: Cd and Mem variants for unchecked index access into a GuardianSignature array
//  * minSigsForQuorum

library CoreBridgeLib {
  using UncheckedIndexing for address[];
  using BytesParsing for bytes;
  using VaaLib for bytes;

  //avoid solc error:
  //Only direct number constants and references to such constants are supported by inline assembly.
  uint internal constant GUARDIAN_SIGNATURE_STRUCT_SIZE = 128; //4 * WORD_SIZE;

  error VerificationFailed();

  function minSigsForQuorum(uint numGuardians) internal pure returns (uint) { unchecked {
    return numGuardians * 2 / 3 + 1;
  }}

  //skip out-of-bounds checks by using assembly
  function readUncheckedCd(
    GuardianSignature[] calldata arr,
    uint i
  ) internal pure returns (GuardianSignature calldata ret) {
    assembly ("memory-safe") {
      ret := add(arr.offset, mul(i, GUARDIAN_SIGNATURE_STRUCT_SIZE))
    }
  }

  function readUncheckedMem(
    GuardianSignature[] memory arr,
    uint i
  ) internal pure returns (GuardianSignature memory ret) {
    assembly ("memory-safe") {
      ret := mload(add(add(arr, WORD_SIZE), mul(i, WORD_SIZE)))
    }
  }

  //this function is the most efficient choice when verifying multiple messages because it allows
  //  library users to reuse the same guardian set for multiple messages (thus avoiding redundant
  //  external calls and the associated allocations and checks)
  function isVerifiedByQuorumCd(
    bytes32 hash,
    GuardianSignature[] calldata guardianSignatures,
    address[] memory guardians
  ) internal pure returns (bool) { unchecked {
    uint guardianCount = guardians.length;
    uint signatureCount = guardianSignatures.length; //optimization puts var on stack
    if (signatureCount < minSigsForQuorum(guardianCount))
      return false;

    bool isFirstSignature = true; //optimization instead of always checking i == 0
    uint prevGuardianIndex;
    for (uint i = 0; i < signatureCount; ++i) {
      GuardianSignature memory sig = readUncheckedCd(guardianSignatures, i);
      uint guardianIndex = sig.guardianIndex;
      if (_failsVerification(
        hash,
        guardianIndex,
        sig.r, sig.s, sig.v,
        guardians,
        guardianCount,
        prevGuardianIndex,
        isFirstSignature
      ))
        return false;

      prevGuardianIndex = guardianIndex;
      isFirstSignature = false;
    }
    return true;
  }}

  function isVerifiedByQuorumMem(
    bytes32 hash,
    GuardianSignature[] memory guardianSignatures,
    address[] memory guardians
  ) internal pure returns (bool) { unchecked {
    uint guardianCount = guardians.length;
    uint signatureCount = guardianSignatures.length; //optimization puts var on stack
    if (signatureCount < minSigsForQuorum(guardianCount))
      return false;

    bool isFirstSignature = true; //optimization instead of always checking i == 0
    uint prevGuardianIndex;
    for (uint i = 0; i < signatureCount; ++i) {
      GuardianSignature memory sig = readUncheckedMem(guardianSignatures, i);
      uint guardianIndex = sig.guardianIndex;
      if (_failsVerification(
        hash,
        guardianIndex,
        sig.r, sig.s, sig.v,
        guardians,
        guardianCount,
        prevGuardianIndex,
        isFirstSignature
      ))
        return false;

      prevGuardianIndex = guardianIndex;
      isFirstSignature = false;
    }
    return true;
  }}

  function decodeAndVerifyVaaCd(
    address wormhole,
    bytes calldata encodedVaa
  ) internal view returns (
    uint32  timestamp,
    uint32  nonce,
    uint16  emitterChainId,
    bytes32 emitterAddress,
    uint64  sequence,
    uint8   consistencyLevel,
    bytes calldata payload
  ) { unchecked {
    uint offset = VaaLib.checkVaaVersionCd(encodedVaa);
    uint32 guardianSetIndex;
    (guardianSetIndex, offset) = encodedVaa.asUint32CdUnchecked(offset);

    address[] memory guardians = getGuardiansOrLatest(wormhole, guardianSetIndex);
    uint guardianCount = guardians.length; //optimization puts var on stack thus avoids mload
    uint signatureCount;
    (signatureCount, offset) = encodedVaa.asUint8CdUnchecked(offset);
    //this check will also handle empty guardian sets, because minSigsForQuorum(0) is 1 and so
    //  subsequent signature verification will fail
    if (signatureCount < minSigsForQuorum(guardianCount))
      revert VerificationFailed();

    uint envelopeOffset = offset + signatureCount * VaaLib.GUARDIAN_SIGNATURE_SIZE;
    bytes32 vaaHash = encodedVaa.calcVaaDoubleHashCd(envelopeOffset);

    bool isFirstSignature = true; //optimization instead of always checking i == 0
    uint prevGuardianIndex;
    for (uint i = 0; i < signatureCount; ++i) {
      uint guardianIndex; bytes32 r; bytes32 s; uint8 v;
      (guardianIndex, r, s, v, offset) = encodedVaa.decodeGuardianSignatureCdUnchecked(offset);
      if (_failsVerification(
        vaaHash,
        guardianIndex,
        r, s, v,
        guardians,
        guardianCount,
        prevGuardianIndex,
        isFirstSignature
      ))
        revert VerificationFailed();

      prevGuardianIndex = guardianIndex;
      isFirstSignature = false;
    }

    return encodedVaa.decodeVaaBodyCd(envelopeOffset);
  }}

  function decodeAndVerifyVaaMem(
    address wormhole,
    bytes memory encodedVaa
  ) internal view returns (
    uint32  timestamp,
    uint32  nonce,
    uint16  emitterChainId,
    bytes32 emitterAddress,
    uint64  sequence,
    uint8   consistencyLevel,
    bytes memory payload
  ) {
    (timestamp, nonce, emitterChainId, emitterAddress, sequence, consistencyLevel, payload, ) =
      decodeAndVerifyVaaMem(wormhole, encodedVaa, 0, encodedVaa.length);
  }

  function decodeAndVerifyVaaMem(
    address wormhole,
    bytes memory encodedVaa,
    uint offset,
    uint vaaLength
  ) internal view returns (
    uint32  timestamp,
    uint32  nonce,
    uint16  emitterChainId,
    bytes32 emitterAddress,
    uint64  sequence,
    uint8   consistencyLevel,
    bytes memory payload,
    uint    newOffset
  ) { unchecked {
    offset = VaaLib.checkVaaVersionMemUnchecked(encodedVaa, offset);
    uint32 guardianSetIndex;
    (guardianSetIndex, offset) = encodedVaa.asUint32MemUnchecked(offset);

    address[] memory guardians = getGuardiansOrLatest(wormhole, guardianSetIndex);
    uint guardianCount = guardians.length;

    uint signatureCount;
    (signatureCount, offset) = encodedVaa.asUint8MemUnchecked(offset);
    //this check will also handle empty guardian sets, because minSigsForQuorum(0) is 1 and so
    //  subsequent signature verification will fail
    if (signatureCount < minSigsForQuorum(guardianCount))
      revert VerificationFailed();

    uint envelopeOffset = offset + signatureCount * VaaLib.GUARDIAN_SIGNATURE_SIZE;
    bytes32 vaaHash = encodedVaa.calcVaaDoubleHashMem(envelopeOffset, vaaLength);

    bool isFirstSignature = true; //optimization instead of always checking i == 0
    uint prevGuardianIndex;
    for (uint i = 0; i < signatureCount; ++i) {
      uint guardianIndex; bytes32 r; bytes32 s; uint8 v;
      (guardianIndex, r, s, v, offset) = encodedVaa.decodeGuardianSignatureMemUnchecked(offset);
      if (_failsVerification(
        vaaHash,
        guardianIndex,
        r, s, v,
        guardians,
        guardianCount,
        prevGuardianIndex,
        isFirstSignature
      ))
        revert VerificationFailed();

      prevGuardianIndex = guardianIndex;
      isFirstSignature = false;
    }

    ( timestamp,
      nonce,
      emitterChainId,
      emitterAddress,
      sequence,
      consistencyLevel,
      payload,
      newOffset
    ) = encodedVaa.decodeVaaBodyMemUnchecked(envelopeOffset, vaaLength);
  }}

  function isVerifiedByQuorumCd(
    address wormhole,
    bytes32 hash,
    GuardianSignature[] calldata guardianSignatures,
    uint32 guardianSetIndex
  ) internal view returns (bool) {
    address[] memory guardians = getGuardiansOrLatest(wormhole, guardianSetIndex);
    return isVerifiedByQuorumCd(hash, guardianSignatures, guardians);
  }

  function isVerifiedByQuorumMem(
    address wormhole,
    bytes32 hash,
    GuardianSignature[] memory guardianSignatures,
    uint32 guardianSetIndex
  ) internal view returns (bool) {
    address[] memory guardians = getGuardiansOrLatest(wormhole, guardianSetIndex);
    return isVerifiedByQuorumMem(hash, guardianSignatures, guardians);
  }

  //returns empty array if the guardian set is expired
  //has more predictable gas costs (guaranteed to only do one external call)
  function getGuardiansOrEmpty(
    address wormhole,
    uint32 guardianSetIndex
  ) internal view returns (address[] memory guardians) {
    IWormhole.GuardianSet memory guardianSet = IWormhole(wormhole).getGuardianSet(guardianSetIndex);
    if (!_isExpired(guardianSet))
      guardians = guardianSet.keys;
  }

  //returns associated guardian set or latest guardian set if the specified one is expired
  //has more variable gas costs but has a chance of doing an ad-hoc "repair" of the VAA in case
  //  the specified signatures are valid for the latest guardian set as well (about a 30 % chance
  //  for the typical guardian set rotation where one guardian address gets replaced).
  function getGuardiansOrLatest(
    address wormhole,
    uint32 guardianSetIndex
  ) internal view returns (address[] memory guardians) {
    IWormhole.GuardianSet memory guardianSet = IWormhole(wormhole).getGuardianSet(guardianSetIndex);
    if (_isExpired(guardianSet))
      //if the specified guardian set is expired, we try using the current guardian set as an adhoc
      //  repair attempt (there's almost certainly never more than 2 valid guardian sets at a time)
      guardianSet = IWormhole(wormhole).getGuardianSet(
        IWormhole(wormhole).getCurrentGuardianSetIndex()
      );

    guardians = guardianSet.keys;
  }

  //negated for optimization because we always want to act on incorrect signatures and so save a NOT
  function _failsVerification(
    bytes32 hash,
    uint guardianIndex,
    bytes32 r,
    bytes32 s,
    uint8 v,
    address[] memory guardians,
    uint guardianCount,
    uint prevGuardianIndex,
    bool isFirstSignature
  ) private pure returns (bool) {
    address signatory = ecrecover(hash, v, r, s);
    address guardian = guardians.readUnchecked(guardianIndex);
    //check that:
    // * the guardian indicies are in strictly ascending order (only after the first signature)
    //     this is itself an optimization to efficiently prevent having the same guardian signature
    //     included twice
    // * that the guardian index is not out of bounds
    // * that the signatory is the guardian
    //
    // the core bridge also includes a separate check that signatory is not the zero address
    //   but this is already covered by comparing that the signatory matches the guardian which
    //   [can never be the zero address](https://github.com/wormhole-foundation/wormhole/blob/1dbe8459b96e182932d0dd5ae4b6bbce6f48cb09/ethereum/contracts/Setters.sol#L20)
    return eagerOr(
      eagerOr(
        !eagerOr(isFirstSignature, guardianIndex > prevGuardianIndex),
        guardianIndex >= guardianCount
      ),
      signatory != guardian
    );
  }

  function _isExpired(IWormhole.GuardianSet memory guardianSet) private view returns (bool) {
    uint expirationTime = guardianSet.expirationTime;
    return eagerAnd(expirationTime != 0, expirationTime < block.timestamp);
  }
}

File 9 of 21 : Utils.sol
// SPDX-License-Identifier: Apache 2
pragma solidity ^0.8.4;

import {
  tokenOrNativeTransfer
} from "wormhole-sdk/utils/Transfer.sol";
import {
  reRevert
} from "wormhole-sdk/utils/Revert.sol";
import {
  NotAnEvmAddress,
  toUniversalAddress,
  fromUniversalAddress
} from "wormhole-sdk/utils/UniversalAddress.sol";
import {
  keccak256Word,
  keccak256SliceUnchecked,
  keccak256Cd
} from "wormhole-sdk/utils/Keccak.sol";
import {
  eagerAnd,
  eagerOr
} from "wormhole-sdk/utils/EagerOps.sol";

// SPDX-License-Identifier: MIT
pragma solidity 0.8.28;

import {IBridgeController} from "./IBridgeController.sol";
import {IMakinaGovernable} from "./IMakinaGovernable.sol";

interface IMachineEndpoint is IBridgeController, IMakinaGovernable {
    /// @notice Manages the transfer of tokens between a machine and a caliber. The transfer direction depends on the caller.
    /// @param token The address of the token.
    /// @param amount The amount of tokens to transfer.
    /// @param data ABI-encoded parameters required for bridge-related transfers. Ignored for transfers between a machine and its hub caliber.
    function manageTransfer(address token, uint256 amount, bytes calldata data) external;
}

// SPDX-License-Identifier: MIT
pragma solidity 0.8.28;

interface IMakinaGovernable {
    event AccountingAgentAdded(address indexed newAgent);
    event AccountingAgentRemoved(address indexed agent);
    event MechanicChanged(address indexed oldMechanic, address indexed newMechanic);
    event RecoveryModeChanged(bool recoveryMode);
    event RestrictedAccountingModeChanged(bool restrictedAccountingMode);
    event RiskManagerChanged(address indexed oldRiskManager, address indexed newRiskManager);
    event RiskManagerTimelockChanged(address indexed oldRiskManagerTimelock, address indexed newRiskManagerTimelock);
    event SecurityCouncilChanged(address indexed oldSecurityCouncil, address indexed newSecurityCouncil);

    /// @notice Initialization parameters.
    /// @param initialMechanic The address of the initial mechanic.
    /// @param initialSecurityCouncil The address of the initial security council.
    /// @param initialRiskManager The address of the initial risk manager.
    /// @param initialRiskManagerTimelock The address of the initial risk manager timelock.
    /// @param initialAuthority The address of the initial authority.
    /// @param initialRestrictedAccountingMode The initial value for the restricted accounting mode.
    struct MakinaGovernableInitParams {
        address initialMechanic;
        address initialSecurityCouncil;
        address initialRiskManager;
        address initialRiskManagerTimelock;
        address initialAuthority;
        bool initialRestrictedAccountingMode;
    }

    /// @notice Address of the mechanic.
    function mechanic() external view returns (address);

    /// @notice Address of the security council.
    function securityCouncil() external view returns (address);

    /// @notice Address of the risk manager.
    function riskManager() external view returns (address);

    /// @notice Address of the risk manager timelock.
    function riskManagerTimelock() external view returns (address);

    /// @notice True if the contract is in recovery mode, false otherwise.
    function recoveryMode() external view returns (bool);

    /// @notice True if the contract is in restricted accounting mode, false otherwise.
    function restrictedAccountingMode() external view returns (bool);

    /// @notice User => Whether the user is an accounting agent
    function isAccountingAgent(address agent) external view returns (bool);

    /// @notice User => Whether the user is the current operator
    ///         The operator is either the mechanic or the security council depending on the recovery mode.
    function isOperator(address user) external view returns (bool);

    /// @notice User => Whether the user is authorized to perform accounting operations under current settings
    function isAccountingAuthorized(address user) external view returns (bool);

    /// @notice Sets a new mechanic.
    /// @param newMechanic The address of new mechanic.
    function setMechanic(address newMechanic) external;

    /// @notice Sets a new security council.
    /// @param newSecurityCouncil The address of the new security council.
    function setSecurityCouncil(address newSecurityCouncil) external;

    /// @notice Sets a new risk manager.
    /// @param newRiskManager The address of the new risk manager.
    function setRiskManager(address newRiskManager) external;

    /// @notice Sets a new risk manager timelock.
    /// @param newRiskManagerTimelock The address of the new risk manager timelock.
    function setRiskManagerTimelock(address newRiskManagerTimelock) external;

    /// @notice Sets the recovery mode.
    /// @param enabled True to enable recovery mode, false to disable it.
    function setRecoveryMode(bool enabled) external;

    /// @notice Sets the restricted accounting mode.
    /// @param enabled True to enable restricted accounting mode, false to disable it.
    function setRestrictedAccountingMode(bool enabled) external;

    /// @notice Adds a new accounting agent.
    /// @param newAgent The address of the new accounting agent.
    function addAccountingAgent(address newAgent) external;

    /// @notice Removes an accounting agent.
    /// @param agent The address of the accounting agent to remove.
    function removeAccountingAgent(address agent) external;
}

File 12 of 21 : Common.sol
// SPDX-License-Identifier: Apache 2
pragma solidity ^0.8.4;

// ┌──────────────────────────────────────────────────────────────────────────────┐
// │ NOTE: We can't define e.g. WORD_SIZE_MINUS_ONE via WORD_SIZE - 1 because     │
// │       of solc restrictions on what constants can be used in inline assembly. │
// └──────────────────────────────────────────────────────────────────────────────┘

uint256 constant WORD_SIZE = 32;
uint256 constant WORD_SIZE_MINUS_ONE = 31; //=0x1f=0b00011111
//see section "prefer `< MAX + 1` over `<= MAX` for const comparison" in docs/Optimization.md
uint256 constant WORD_SIZE_PLUS_ONE = 33;

uint256 constant SCRATCH_SPACE_PTR = 0x00;
uint256 constant SCRATCH_SPACE_SIZE = 64;

uint256 constant FREE_MEMORY_PTR = 0x40;

// SPDX-License-Identifier: Apache 2
pragma solidity ^0.8.14; //for (bugfixed) support of `using ... global;` syntax for libraries

import {WORD_SIZE} from "wormhole-sdk/constants/Common.sol";

// ╭──────────────────────────────────────────────────────────────────────╮
// │ Library for [reading from/writing to] memory without bounds checking │
// ╰──────────────────────────────────────────────────────────────────────╯

library UncheckedIndexing {
  function readUnchecked(bytes memory arr, uint index) internal pure returns (uint256 ret) {
    /// @solidity memory-safe-assembly
    assembly { ret := mload(add(add(arr, WORD_SIZE), index)) }
  }

  function writeUnchecked(bytes memory arr, uint index, uint256 value) internal pure {
    /// @solidity memory-safe-assembly
    assembly { mstore(add(add(arr, WORD_SIZE), index), value) }
  }

  function readUnchecked(address[] memory arr, uint index) internal pure returns (address ret) {
    bytes memory arrBytes;
    /// @solidity memory-safe-assembly
    assembly { arrBytes := arr }
    uint256 raw = readUnchecked(arrBytes, _mulWordSize(index));
    /// @solidity memory-safe-assembly
    assembly { ret := raw }
  }

  //it is assumed that value is never dirty here (it's hard to create a dirty address)
  //  see https://docs.soliditylang.org/en/latest/internals/variable_cleanup.html
  function writeUnchecked(address[] memory arr, uint index, address value) internal pure {
    bytes memory arrBytes;
    /// @solidity memory-safe-assembly
    assembly { arrBytes := arr }
    writeUnchecked(arrBytes, _mulWordSize(index), uint256(uint160(value)));
  }

  function readUnchecked(uint256[] memory arr, uint index) internal pure returns (uint256 ret) {
    bytes memory arrBytes;
    /// @solidity memory-safe-assembly
    assembly { arrBytes := arr }
    return readUnchecked(arrBytes, _mulWordSize(index));
  }

  function writeUnchecked(uint256[] memory arr, uint index, uint256 value) internal pure {
    bytes memory arrBytes;
    /// @solidity memory-safe-assembly
    assembly { arrBytes := arr }
    writeUnchecked(arrBytes, _mulWordSize(index), value);
  }

  function _mulWordSize(uint index) private pure returns (uint) { unchecked {
    return index * WORD_SIZE;
  }}
}

File 14 of 21 : Transfer.sol
// SPDX-License-Identifier: Apache 2
pragma solidity ^0.8.19;

import {IERC20} from "IERC20/IERC20.sol";
import {SafeERC20} from "SafeERC20/SafeERC20.sol";

error PaymentFailure(address target);

//Note: Always forwards all gas, so consider gas griefing attack opportunities by the recipient.
//Note: Don't use this method if you need events for 0 amount transfers.
function tokenOrNativeTransfer(address tokenOrZeroForNative, address to, uint256 amount) {
  if (amount == 0)
    return;

  if (tokenOrZeroForNative == address(0)) {
    (bool success, ) = to.call{value: amount}(new bytes(0));
    if (!success)
      revert PaymentFailure(to);
  }
  else
    SafeERC20.safeTransfer(IERC20(tokenOrZeroForNative), to, amount);
}

File 15 of 21 : Revert.sol
// SPDX-License-Identifier: Apache 2
pragma solidity ^0.8.19;

import {WORD_SIZE} from "wormhole-sdk/constants/Common.sol";

//bubble up errors from low level calls
function reRevert(bytes memory err) pure {
  assembly ("memory-safe") {
    revert(add(err, WORD_SIZE), mload(err))
  }
}

// SPDX-License-Identifier: Apache 2
pragma solidity ^0.8.19;

error NotAnEvmAddress(bytes32);

function toUniversalAddress(address addr) pure returns (bytes32 universalAddr) {
  universalAddr = bytes32(uint256(uint160(addr)));
}

function fromUniversalAddress(bytes32 universalAddr) pure returns (address addr) {
  if (bytes12(universalAddr) != 0)
    revert NotAnEvmAddress(universalAddr);

  assembly ("memory-safe") {
    addr := universalAddr
  }
}

// SPDX-License-Identifier: Apache 2
pragma solidity ^0.8.4;

import {WORD_SIZE, SCRATCH_SPACE_PTR, FREE_MEMORY_PTR} from "wormhole-sdk/constants/Common.sol";

function keccak256Word(bytes32 word) pure returns (bytes32 hash) {
  /// @solidity memory-safe-assembly
  assembly {
    mstore(SCRATCH_SPACE_PTR, word)
    hash := keccak256(SCRATCH_SPACE_PTR, WORD_SIZE)
  }
}

function keccak256SliceUnchecked(
  bytes memory encoded,
  uint offset,
  uint length
) pure returns (bytes32 hash) {
  /// @solidity memory-safe-assembly
  assembly {
    // The length of the bytes type `length` field is that of a word in memory
    let ptr := add(add(encoded, offset), WORD_SIZE)
    hash := keccak256(ptr, length)
  }
}

function keccak256Cd(
  bytes calldata encoded
) pure returns (bytes32 hash) {
  /// @solidity memory-safe-assembly
  assembly {
    let freeMemory := mload(FREE_MEMORY_PTR)
    calldatacopy(freeMemory, encoded.offset, encoded.length)
    hash := keccak256(freeMemory, encoded.length)
  }
}

File 18 of 21 : EagerOps.sol
// SPDX-License-Identifier: Apache 2
pragma solidity ^0.8.4;

//see Optimization.md for rationale on avoiding short-circuiting
function eagerAnd(bool lhs, bool rhs) pure returns (bool ret) {
  /// @solidity memory-safe-assembly
  assembly {
    ret := and(lhs, rhs)
  }
}

//see Optimization.md for rationale on avoiding short-circuiting
function eagerOr(bool lhs, bool rhs) pure returns (bool ret) {
  /// @solidity memory-safe-assembly
  assembly {
    ret := or(lhs, rhs)
  }
}

// SPDX-License-Identifier: MIT
pragma solidity 0.8.28;

interface IBridgeController {
    event BridgeAdapterCreated(uint16 indexed bridgeId, address indexed adapter);
    event MaxBridgeLossBpsChanged(
        uint16 indexed bridgeId, uint256 indexed oldMaxBridgeLossBps, uint256 indexed newMaxBridgeLossBps
    );
    event BridgingStateReset(address indexed token);
    event OutTransferEnabledSet(uint256 indexed bridgeId, bool enabled);

    /// @notice Bridge ID => Is bridge adapter deployed.
    function isBridgeSupported(uint16 bridgeId) external view returns (bool);

    /// @notice Bridge ID => Is outgoing transfer enabled.
    function isOutTransferEnabled(uint16 bridgeId) external view returns (bool);

    /// @notice Bridge ID => Address of the associated bridge adapter.
    function getBridgeAdapter(uint16 bridgeId) external view returns (address);

    /// @notice Bridge ID => Max allowed value loss in basis points for transfers via this bridge.
    function getMaxBridgeLossBps(uint16 bridgeId) external view returns (uint256);

    /// @notice Deploys a new BridgeAdapter instance.
    /// @param bridgeId The ID of the bridge.
    /// @param initialMaxBridgeLossBps The initial maximum allowed value loss in basis points for transfers via this bridge.
    /// @param initData The optional initialization data for the bridge adapter.
    /// @return The address of the deployed BridgeAdapter.
    function createBridgeAdapter(uint16 bridgeId, uint256 initialMaxBridgeLossBps, bytes calldata initData)
        external
        returns (address);

    /// @notice Sets the maximum allowed value loss in basis points for transfers via this bridge.
    /// @param bridgeId The ID of the bridge.
    /// @param maxBridgeLossBps The maximum allowed value loss in basis points.
    function setMaxBridgeLossBps(uint16 bridgeId, uint256 maxBridgeLossBps) external;

    /// @notice Sets the outgoing transfer enabled status for a bridge.
    /// @param bridgeId The ID of the bridge.
    /// @param enabled True to enable outgoing transfer for the given bridge ID, false to disable.
    function setOutTransferEnabled(uint16 bridgeId, bool enabled) external;

    /// @notice Executes a scheduled outgoing bridge transfer.
    /// @param bridgeId The ID of the bridge.
    /// @param transferId The ID of the transfer to execute.
    /// @param data The optional data needed to execute the transfer.
    function sendOutBridgeTransfer(uint16 bridgeId, uint256 transferId, bytes calldata data) external;

    /// @notice Registers a message hash as authorized for an incoming bridge transfer.
    /// @param bridgeId The ID of the bridge.
    /// @param messageHash The hash of the message to authorize.
    function authorizeInBridgeTransfer(uint16 bridgeId, bytes32 messageHash) external;

    /// @notice Transfers a received bridge transfer out of the adapter.
    /// @param bridgeId The ID of the bridge.
    /// @param transferId The ID of the transfer to claim.
    function claimInBridgeTransfer(uint16 bridgeId, uint256 transferId) external;

    /// @notice Cancels an outgoing bridge transfer.
    /// @param bridgeId The ID of the bridge.
    /// @param transferId The ID of the transfer to cancel.
    function cancelOutBridgeTransfer(uint16 bridgeId, uint256 transferId) external;

    /// @notice Resets internal bridge counters for a given token, and withdraw token balances held by all bridge adapters.
    /// @dev This function is intended to be used by the DAO to realign bridge accounting state and maintain protocol consistency,
    ///      typically in response to operator deviations, external bridge discrepancies, or unbounded counter growth.
    /// @param token The address of the token.
    function resetBridgingState(address token) external;
}

// SPDX-License-Identifier: Apache 2

pragma solidity ^0.8.0;

//https://eips.ethereum.org/EIPS/eip-20
interface IERC20 {
  event Transfer(address indexed from, address indexed to, uint256 value);
  event Approval(address indexed owner, address indexed spender, uint256 value);

  function totalSupply() external view returns (uint256);
  function balanceOf(address account) external view returns (uint256);
  function allowance(address owner, address spender) external view returns (uint256);

  function transfer(address to, uint256 amount) external returns (bool);
  function approve(address spender, uint256 amount) external returns (bool);
  function transferFrom(address from, address to, uint256 amount) external returns (bool);
}

// SPDX-License-Identifier: Apache 2
pragma solidity ^0.8.4;

import {IERC20} from "IERC20/IERC20.sol";
import {WORD_SIZE, SCRATCH_SPACE_PTR} from "wormhole-sdk/constants/Common.sol";

//Like OpenZeppelin's SafeERC20.sol, but slimmed down and more gas efficient.
//
//The main difference to OZ's implementation (besides the missing functions) is that we skip the
//  EXTCODESIZE check that OZ does upon successful calls to ensure that an actual contract was
//  called. The rationale for omitting this check is that ultimately the contract using the token
//  has to verify that it "makes sense" for its use case regardless. Otherwise, a random token, or
//  even just a contract that always returns true, could be passed, which makes this check
//  superfluous in the final analysis.
//
//We also save on code size by not duplicating the assembly code in two separate functions.
//  Otoh, we simply swallow revert reasons of failing token operations instead of bubbling them up.
//  This is less clean and makes debugging harder, but is likely still a worthwhile trade-off
//    given the cost in gas and code size.
library SafeERC20 {
  error SafeERC20FailedOperation(address token);

  function safeTransfer(IERC20 token, address to, uint256 value) internal {
    _revertOnFailure(token, abi.encodeCall(token.transfer, (to, value)));
  }

  function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
    _revertOnFailure(token, abi.encodeCall(token.transferFrom, (from, to, value)));
  }

  function forceApprove(IERC20 token, address spender, uint256 value) internal {
    bytes memory approveCall = abi.encodeCall(token.approve, (spender, value));

    if (!_callWithOptionalReturnCheck(token, approveCall)) {
      _revertOnFailure(token, abi.encodeCall(token.approve, (spender, 0)));
      _revertOnFailure(token, approveCall);
    }
  }

  function _callWithOptionalReturnCheck(
    IERC20 token,
    bytes memory encodedCall
  ) private returns (bool success) {
    /// @solidity memory-safe-assembly
    assembly {
      mstore(SCRATCH_SPACE_PTR, 0)
      success := call( //see https://www.evm.codes/?fork=cancun#f1
        gas(),                       //gas
        token,                       //callee
        0,                           //value
        add(encodedCall, WORD_SIZE), //input ptr
        mload(encodedCall),          //input size
        SCRATCH_SPACE_PTR,           //output ptr
        WORD_SIZE                    //output size
      )
      //calls to addresses without code are always successful
      if success {
        success := or(iszero(returndatasize()), mload(SCRATCH_SPACE_PTR))
      }
    }
  }

  function _revertOnFailure(IERC20 token, bytes memory encodedCall) private {
    if (!_callWithOptionalReturnCheck(token, encodedCall))
      revert SafeERC20FailedOperation(address(token));
  }
}

Settings
{
  "remappings": [
    "@makina-core/=lib/makina-core/src/",
    "@makina-core-test/=lib/makina-core/test/",
    "@makina-core-script/=lib/makina-core/script/",
    "@openzeppelin/contracts/=lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/",
    "@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/",
    "@balancer-v2-interfaces/=lib/balancer-v2-monorepo/pkg/interfaces/contracts/",
    "@balancer-v3-interfaces/=lib/balancer-v3-monorepo/pkg/interfaces/contracts/",
    "@morpho/=lib/morpho-blue/src/",
    "@aave/=lib/aave-v3-origin/src/contracts/",
    "@balancer-labs/=lib/balancer-v2-monorepo/../../node_modules/@balancer-labs/",
    "@enso-weiroll/=lib/makina-core/lib/enso-weiroll/contracts/",
    "@layerzerolabs/lz-evm-messagelib-v2/=lib/makina-core/lib/LayerZero-v2/packages/layerzero-v2/evm/messagelib/",
    "@layerzerolabs/lz-evm-oapp-v2/=lib/makina-core/lib/LayerZero-v2/packages/layerzero-v2/evm/oapp/",
    "@layerzerolabs/lz-evm-protocol-v2/=lib/makina-core/lib/LayerZero-v2/packages/layerzero-v2/evm/protocol/",
    "@layerzerolabs/oapp-evm/=lib/makina-core/lib/devtools/packages/oapp-evm/",
    "@layerzerolabs/oft-evm/=lib/makina-core/lib/devtools/packages/oft-evm/",
    "@layerzerolabs/test-evm/=lib/makina-core/lib/devtools/packages/test-devtools-evm-foundry/",
    "@wormhole/sdk/=lib/makina-core/lib/wormhole-solidity-sdk/src/",
    "IERC20/=lib/makina-core/lib/wormhole-solidity-sdk/src/interfaces/token/",
    "LayerZero-v2/=lib/makina-core/lib/",
    "SafeERC20/=lib/makina-core/lib/wormhole-solidity-sdk/src/libraries/",
    "aave-v3-origin/=lib/aave-v3-origin/",
    "balancer-v2-monorepo/=lib/balancer-v2-monorepo/",
    "balancer-v3-monorepo/=lib/balancer-v3-monorepo/",
    "devtools/=lib/makina-core/lib/devtools/packages/toolbox-foundry/src/",
    "ds-test/=lib/aave-v3-origin/lib/forge-std/lib/ds-test/src/",
    "enso-weiroll/=lib/makina-core/lib/enso-weiroll/contracts/",
    "erc4626-tests/=lib/openzeppelin-contracts-upgradeable/lib/erc4626-tests/",
    "forge-std/=lib/forge-std/src/",
    "halmos-cheatcodes/=lib/openzeppelin-contracts-upgradeable/lib/halmos-cheatcodes/src/",
    "makina-core/=lib/makina-core/",
    "morpho-blue/=lib/morpho-blue/",
    "openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/",
    "openzeppelin-contracts/=lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/",
    "solidity-utils/=lib/aave-v3-origin/lib/solidity-utils/",
    "wormhole-sdk/=lib/makina-core/lib/wormhole-solidity-sdk/src/",
    "wormhole-solidity-sdk/=lib/makina-core/lib/wormhole-solidity-sdk/src/"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 150
  },
  "metadata": {
    "useLiteralContent": false,
    "bytecodeHash": "ipfs",
    "appendCBOR": true
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "evmVersion": "cancun",
  "viaIR": false
}

Contract Security Audit

Contract ABI

API
[{"inputs":[],"name":"ChainIdMismatch","type":"error"},{"inputs":[],"name":"InvalidContractAddress","type":"error"},{"inputs":[],"name":"InvalidFunctionSignature","type":"error"},{"inputs":[{"internalType":"uint256","name":"received","type":"uint256"},{"internalType":"uint256","name":"expected","type":"uint256"}],"name":"InvalidPayloadLength","type":"error"},{"inputs":[],"name":"InvalidResponseVersion","type":"error"},{"inputs":[],"name":"NumberOfResponsesMismatch","type":"error"},{"inputs":[],"name":"RequestTypeMismatch","type":"error"},{"inputs":[],"name":"UnexpectedNumberOfResults","type":"error"},{"inputs":[],"name":"UnexpectedResultLength","type":"error"},{"inputs":[{"internalType":"uint8","name":"received","type":"uint8"}],"name":"UnsupportedQueryType","type":"error"},{"inputs":[],"name":"VerificationFailed","type":"error"},{"inputs":[],"name":"VersionMismatch","type":"error"},{"inputs":[{"internalType":"uint8","name":"received","type":"uint8"},{"internalType":"uint8","name":"expected","type":"uint8"}],"name":"WrongQueryType","type":"error"},{"inputs":[],"name":"ZeroQueries","type":"error"},{"inputs":[{"internalType":"address","name":"wormhole","type":"address"},{"internalType":"bytes","name":"response","type":"bytes"},{"components":[{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"uint8","name":"guardianIndex","type":"uint8"}],"internalType":"struct GuardianSignature[]","name":"signatures","type":"tuple[]"}],"name":"decodeAndVerifyQueryResponse","outputs":[{"components":[{"internalType":"uint8","name":"version","type":"uint8"},{"internalType":"uint16","name":"senderChainId","type":"uint16"},{"internalType":"uint32","name":"nonce","type":"uint32"},{"internalType":"bytes","name":"requestId","type":"bytes"},{"components":[{"internalType":"uint16","name":"chainId","type":"uint16"},{"internalType":"uint8","name":"queryType","type":"uint8"},{"internalType":"bytes","name":"request","type":"bytes"},{"internalType":"bytes","name":"response","type":"bytes"}],"internalType":"struct PerChainQueryResponse[]","name":"responses","type":"tuple[]"}],"internalType":"struct QueryResponse","name":"ret","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint16","name":"chainId","type":"uint16"},{"internalType":"uint8","name":"queryType","type":"uint8"},{"internalType":"bytes","name":"request","type":"bytes"},{"internalType":"bytes","name":"response","type":"bytes"}],"internalType":"struct PerChainQueryResponse","name":"pcr","type":"tuple"},{"internalType":"address","name":"caliberMailbox","type":"address"}],"name":"getAccountingData","outputs":[{"components":[{"internalType":"uint256","name":"netAum","type":"uint256"},{"internalType":"bytes[]","name":"positions","type":"bytes[]"},{"internalType":"bytes[]","name":"baseTokens","type":"bytes[]"},{"internalType":"bytes[]","name":"bridgesIn","type":"bytes[]"},{"internalType":"bytes[]","name":"bridgesOut","type":"bytes[]"}],"internalType":"struct ICaliberMailbox.SpokeCaliberAccountingData","name":"","type":"tuple"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"}]

6118d0610034600b8282823980515f1a607314602857634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040526004361061003f575f3560e01c8063437b9b3e14610043578063586c2a021461006d575b5f5ffd5b610056610051366004611114565b61008d565b60405161006492919061126c565b60405180910390f35b61008061007b36600461133b565b61022c565b60405161006491906113e9565b6100be6040518060a001604052805f8152602001606081526020016060815260200160608152602001606081525090565b5f5f6100c9856102ab565b90508060800151516001146100f157604051633a279ba160e01b815260040160405180910390fd5b6040805160018082528183019092525f916020808301908036833750506040805160018082528183019092529293505f9291506020808301908036833701905050905085825f81518110610147576101476114db565b60200260200101906001600160a01b031690816001600160a01b031681525050636775608d60e01b815f81518110610181576101816114db565b60200260200101906001600160e01b03191690816001600160e01b031916815250506101cb83608001515f815181106101bc576101bc6114db565b60200260200101518383610505565b82608001515f815181106101e1576101e16114db565b60200260200101516040015180602001905181019061020091906115d9565b620f4240846040015161021391906116cb565b9095506001600160401b031693505050505b9250929050565b610234610f8c565b6102a186868686868b6001600160a01b0316631cfe79516040518163ffffffff1660e01b8152600401602060405180830381865afa158015610278573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061029c9190611717565b61055f565b9695505050505050565b6102ec6040518060a00160405280606081526020015f6001600160401b031681526020015f6001600160401b031681526020015f8152602001606081525090565b602082015160ff1660011461032b5760208201516040516396b8e05b60e01b815260ff9091166004820152600160248201526044015b60405180910390fd5b5f5f5f61034583866040015161058a90919063ffffffff16565b90855260408681015182016001908101516060808a0180518801600801516001600160401b0390811660208c01528151890160280151928b0192909252805188016030015190911693890193909352915185016031908101519190930195509190930192915060ff808216908316146103d15760405163179ef5bb60e21b815260040160405180910390fd5b8160ff166001600160401b038111156103ec576103ec610fb8565b60405190808252806020026020018201604052801561044957816020015b61043660405180606001604052805f6001600160a01b0316815260200160608152602001606081525090565b81526020019060019003908161040a5790505b5060808601525f5b8260ff168110156104dd575f86608001518281518110610473576104736114db565b602002602001015190506104948689604001516105b590919063ffffffff16565b6001600160a01b03909116825260408901519096506104b3908761058a565b602083019190915260608901519096506104cd908661058a565b6040909201529350600101610451565b506104ed866040015151856105ca565b6104fc866060015151846105ca565b50505050919050565b81511561051857825161051890836105f8565b80511561055a57600483602001515110156105465760405163403b6ec560e11b815260040160405180910390fd5b6020838101510151610558818361065e565b505b505050565b610567610f8c565b6105758787878787876106c6565b61057f8686610701565b979650505050505050565b60048183018101516060918301906105a9858363ffffffff8416610b8e565b90969095509350505050565b60148183018101515f918291829185016105a9565b8082146105f45760405163061bc83560e51b81526004810183905260248101829052604401610322565b5050565b80515f5b8181101561064457828181518110610616576106166114db565b60200260200101516001600160a01b0316846001600160a01b03160361063c5750505050565b6001016105fc565b5060405163a710429d60e01b815260040160405180910390fd5b80515f5b818110156106ac5782818151811061067c5761067c6114db565b60200260200101516001600160e01b031916846001600160e01b031916036106a45750505050565b600101610662565b5060405163403b6ec560e11b815260040160405180910390fd5b6106dc866106d48787610bdf565b858585610bf9565b6106f95760405163439cc0cd60e01b815260040160405180910390fd5b505050505050565b610709610f8c565b823560f81c80825260019081146107325760405162ecb0bd60e51b815260040160405180910390fd5b8381013560f01c6020830181905260029091019061076a9082901561075857602061075b565b60415b8187019260ff90911691820190565b82828080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152505050506060860152845160048083019550888301803560e01c9550600590930193509091013560f81c9060ff1681146107e85760405163714f551360e01b815260040160405180910390fd5b50858101803560e01c60408601526005909101906004013560f81c5f8190036108245760405163bb6b170d60e01b815260040160405180910390fd5b63ffffffff80841685019081905f90610843908b908b908590610c1316565b9350905060ff8082169085161461086d5760405163084ae4a360e41b815260040160405180910390fd5b8360ff166001600160401b0381111561088857610888610fb8565b6040519080825280602002602001820160405280156108db57816020015b604080516080810182525f80825260208201526060918101829052818101919091528152602001906001900390816108a65790505b5060808901525f5b8460ff16811015610b4c57858b013560f01c600287018a60800151838151811061090f5761090f6114db565b602090810291909101015161ffff9290921690915260808a0151805191975060028601958d013560f01c918390811061094a5761094a6114db565b60200260200101515f015161ffff168161ffff161461097c5760405163a179f8c960e01b815260040160405180910390fd5b868c013560f81c600188018b60800151848151811061099d5761099d6114db565b60200260200101516020018199508260ff1660ff1681525050506109e18a6080015183815181106109d0576109d06114db565b602002602001015160200151610c25565b60808a0151805160018701968e013560f81c919084908110610a0557610a056114db565b60200260200101516020015160ff168160ff1614610a3657604051630216496160e01b815260040160405180910390fd5b878d016004818101913560e01c90818b010182828080601f0160208091040260200160405190810160405280939291908181526020018383808284375f81840152601f19601f8201169050808301925050505050505091509091508c608001518581518110610aa757610aa76114db565b6020908102919091010151604001919091529750858d016004818101913560e01c908189010182828080601f0160208091040260200160405190810160405280939291908181526020018383808284375f81840152601f19601f8201169050808301925050505050505091509091508c608001518581518110610b2c57610b2c6114db565b6020026020010151606001819850829052505050508060010190506108e3565b50848214610b775760405163061bc83560e51b81526004810183905260248101869052604401610322565b610b8189846105ca565b5050505050505092915050565b604051828201601f831680610ba1575060205b80830184810186838901015b81831015610bc5578051835260209283019201610bad565b5050848452601f19601f8201166040525050935093915050565b5f610bf2610bed8484610c5c565b610c6e565b9392505050565b5f5f610c058784610cb7565b905061057f86868684610e2a565b9182013560f81c926001909201919050565b610c3660ff82168015906005101790565b15610c59576040516351ee585360e01b815260ff82166004820152602401610322565b50565b5f604051828482379190912092915050565b5f6040518060600160405280602381526020016118786023913982604051602001610c9a929190611730565b604051602081830303815290604052805190602001209050919050565b604051637ca8cbad60e11b815263ffffffff821660048201526060905f906001600160a01b0385169063f951975a906024015f60405180830381865afa158015610d03573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052610d2a919081019061174a565b9050610d45816020015163ffffffff16801515429091101690565b15610e2257836001600160a01b031663f951975a856001600160a01b0316631cfe79516040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d95573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610db99190611717565b6040516001600160e01b031960e084901b16815263ffffffff9190911660048201526024015f60405180830381865afa158015610df8573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052610e1f919081019061174a565b90505b519392505050565b80515f908360016003600284020401811015610e4a575f92505050610ec2565b60015f805b83811015610eb8575f610e6d608083028b0136819003810190611826565b90505f816060015160ff169050610e968c82845f0151856020015186604001518e8d8b8d610eca565b15610eaa575f975050505050505050610ec2565b5f9450925050600101610e4f565b5060019450505050505b949350505050565b604080515f808252602082018084528c905260ff8816928201929092526060810189905260808101889052819060019060a0016020604051602081039080840390855afa158015610f1d573d5f5f3e3d5ffd5b5050604051601f19015191505f9050610f36878c610f70565b9050610f60868c1015868d1186171517826001600160a01b0316846001600160a01b031614151790565b9c9b505050505050505050505050565b5f8281610f838260208602016020015190565b95945050505050565b6040805160a0810182525f80825260208201819052918101919091526060808201819052608082015290565b634e487b7160e01b5f52604160045260245ffd5b604051608081016001600160401b0381118282101715610fee57610fee610fb8565b60405290565b60405160a081016001600160401b0381118282101715610fee57610fee610fb8565b604080519081016001600160401b0381118282101715610fee57610fee610fb8565b604051601f8201601f191681016001600160401b038111828210171561106057611060610fb8565b604052919050565b803560ff81168114611078575f5ffd5b919050565b5f6001600160401b0382111561109557611095610fb8565b50601f01601f191660200190565b5f82601f8301126110b2575f5ffd5b81356110c56110c08261107d565b611038565b8181528460208386010111156110d9575f5ffd5b816020850160208301375f918101602001919091529392505050565b6001600160a01b0381168114610c59575f5ffd5b8035611078816110f5565b5f5f60408385031215611125575f5ffd5b82356001600160401b0381111561113a575f5ffd5b83016080818603121561114b575f5ffd5b611153610fcc565b813561ffff81168114611164575f5ffd5b815261117260208301611068565b602082015260408201356001600160401b0381111561118f575f5ffd5b61119b878285016110a3565b60408301525060608201356001600160401b038111156111b9575f5ffd5b6111c5878285016110a3565b60608301525092506111db905060208401611109565b90509250929050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b5f82825180855260208501945060208160051b830101602085015f5b8381101561126057601f1985840301885261124a8383516111e4565b602098890198909350919091019060010161122e565b50909695505050505050565b60408152825160408201525f602084015160a0606084015261129160e0840182611212565b90506040850151603f198483030160808501526112ae8282611212565b9150506060850151603f198483030160a08501526112cc8282611212565b9150506080850151603f198483030160c08501526112ea8282611212565b925050508260208301529392505050565b5f5f83601f84011261130b575f5ffd5b5081356001600160401b03811115611321575f5ffd5b6020830191508360208260071b8501011115610225575f5ffd5b5f5f5f5f5f6060868803121561134f575f5ffd5b853561135a816110f5565b945060208601356001600160401b03811115611374575f5ffd5b8601601f81018813611384575f5ffd5b80356001600160401b03811115611399575f5ffd5b8860208284010111156113aa575f5ffd5b6020919091019450925060408601356001600160401b038111156113cc575f5ffd5b6113d8888289016112fb565b969995985093965092949392505050565b6020815260ff825116602082015261ffff602083015116604082015263ffffffff60408301511660608201525f606083015160a0608084015261142f60c08401826111e4565b6080850151848203601f190160a0860152805180835291925060209081019181840191600582901b8501015f5b828110156114cf57601f19868303018452845161ffff815116835260ff602082015116602084015260408101516080604085015261149d60808501826111e4565b90506060820151915083810360608501526114b881836111e4565b60209788019796909601959350505060010161145c565b50979650505050505050565b634e487b7160e01b5f52603260045260245ffd5b5f6001600160401b0382111561150757611507610fb8565b5060051b60200190565b5f82601f830112611520575f5ffd5b815161152e6110c0826114ef565b8082825260208201915060208360051b86010192508583111561154f575f5ffd5b602085015b838110156115cf5780516001600160401b03811115611571575f5ffd5b8601603f81018813611581575f5ffd5b60208101516115926110c08261107d565b8181526040838301018a10156115a6575f5ffd5b8160408401602083015e5f60208383010152808652505050602083019250602081019050611554565b5095945050505050565b5f602082840312156115e9575f5ffd5b81516001600160401b038111156115fe575f5ffd5b820160a0818503121561160f575f5ffd5b611617610ff4565b8151815260208201516001600160401b03811115611633575f5ffd5b61163f86828501611511565b60208301525060408201516001600160401b0381111561165d575f5ffd5b61166986828501611511565b60408301525060608201516001600160401b03811115611687575f5ffd5b61169386828501611511565b60608301525060808201516001600160401b038111156116b1575f5ffd5b6116bd86828501611511565b608083015250949350505050565b5f6001600160401b038316806116ef57634e487b7160e01b5f52601260045260245ffd5b806001600160401b0384160491505092915050565b805163ffffffff81168114611078575f5ffd5b5f60208284031215611727575f5ffd5b610bf282611704565b5f83518060208601845e9190910191825250602001919050565b5f6020828403121561175a575f5ffd5b81516001600160401b0381111561176f575f5ffd5b820160408185031215611780575f5ffd5b611788611016565b81516001600160401b0381111561179d575f5ffd5b8201601f810186136117ad575f5ffd5b80516117bb6110c0826114ef565b8082825260208201915060208360051b8501019250888311156117dc575f5ffd5b6020840193505b828410156118075783516117f6816110f5565b8252602093840193909101906117e3565b84525061181991505060208301611704565b6020820152949350505050565b5f6080828403128015611837575f5ffd5b50611840610fcc565b823581526020808401359082015261185a60408401611068565b604082015261186b60608401611068565b6060820152939250505056fe71756572795f726573706f6e73655f303030303030303030303030303030303030307ca264697066735822122034eda57296f1839d0267b77a23e93b47c1136cec60f2ca51d16b7a95733a509364736f6c634300081c0033

Deployed Bytecode

0x73efc2bfa5dab062d0ee4c9dd955536e44d5ce4db5301460806040526004361061003f575f3560e01c8063437b9b3e14610043578063586c2a021461006d575b5f5ffd5b610056610051366004611114565b61008d565b60405161006492919061126c565b60405180910390f35b61008061007b36600461133b565b61022c565b60405161006491906113e9565b6100be6040518060a001604052805f8152602001606081526020016060815260200160608152602001606081525090565b5f5f6100c9856102ab565b90508060800151516001146100f157604051633a279ba160e01b815260040160405180910390fd5b6040805160018082528183019092525f916020808301908036833750506040805160018082528183019092529293505f9291506020808301908036833701905050905085825f81518110610147576101476114db565b60200260200101906001600160a01b031690816001600160a01b031681525050636775608d60e01b815f81518110610181576101816114db565b60200260200101906001600160e01b03191690816001600160e01b031916815250506101cb83608001515f815181106101bc576101bc6114db565b60200260200101518383610505565b82608001515f815181106101e1576101e16114db565b60200260200101516040015180602001905181019061020091906115d9565b620f4240846040015161021391906116cb565b9095506001600160401b031693505050505b9250929050565b610234610f8c565b6102a186868686868b6001600160a01b0316631cfe79516040518163ffffffff1660e01b8152600401602060405180830381865afa158015610278573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061029c9190611717565b61055f565b9695505050505050565b6102ec6040518060a00160405280606081526020015f6001600160401b031681526020015f6001600160401b031681526020015f8152602001606081525090565b602082015160ff1660011461032b5760208201516040516396b8e05b60e01b815260ff9091166004820152600160248201526044015b60405180910390fd5b5f5f5f61034583866040015161058a90919063ffffffff16565b90855260408681015182016001908101516060808a0180518801600801516001600160401b0390811660208c01528151890160280151928b0192909252805188016030015190911693890193909352915185016031908101519190930195509190930192915060ff808216908316146103d15760405163179ef5bb60e21b815260040160405180910390fd5b8160ff166001600160401b038111156103ec576103ec610fb8565b60405190808252806020026020018201604052801561044957816020015b61043660405180606001604052805f6001600160a01b0316815260200160608152602001606081525090565b81526020019060019003908161040a5790505b5060808601525f5b8260ff168110156104dd575f86608001518281518110610473576104736114db565b602002602001015190506104948689604001516105b590919063ffffffff16565b6001600160a01b03909116825260408901519096506104b3908761058a565b602083019190915260608901519096506104cd908661058a565b6040909201529350600101610451565b506104ed866040015151856105ca565b6104fc866060015151846105ca565b50505050919050565b81511561051857825161051890836105f8565b80511561055a57600483602001515110156105465760405163403b6ec560e11b815260040160405180910390fd5b6020838101510151610558818361065e565b505b505050565b610567610f8c565b6105758787878787876106c6565b61057f8686610701565b979650505050505050565b60048183018101516060918301906105a9858363ffffffff8416610b8e565b90969095509350505050565b60148183018101515f918291829185016105a9565b8082146105f45760405163061bc83560e51b81526004810183905260248101829052604401610322565b5050565b80515f5b8181101561064457828181518110610616576106166114db565b60200260200101516001600160a01b0316846001600160a01b03160361063c5750505050565b6001016105fc565b5060405163a710429d60e01b815260040160405180910390fd5b80515f5b818110156106ac5782818151811061067c5761067c6114db565b60200260200101516001600160e01b031916846001600160e01b031916036106a45750505050565b600101610662565b5060405163403b6ec560e11b815260040160405180910390fd5b6106dc866106d48787610bdf565b858585610bf9565b6106f95760405163439cc0cd60e01b815260040160405180910390fd5b505050505050565b610709610f8c565b823560f81c80825260019081146107325760405162ecb0bd60e51b815260040160405180910390fd5b8381013560f01c6020830181905260029091019061076a9082901561075857602061075b565b60415b8187019260ff90911691820190565b82828080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152505050506060860152845160048083019550888301803560e01c9550600590930193509091013560f81c9060ff1681146107e85760405163714f551360e01b815260040160405180910390fd5b50858101803560e01c60408601526005909101906004013560f81c5f8190036108245760405163bb6b170d60e01b815260040160405180910390fd5b63ffffffff80841685019081905f90610843908b908b908590610c1316565b9350905060ff8082169085161461086d5760405163084ae4a360e41b815260040160405180910390fd5b8360ff166001600160401b0381111561088857610888610fb8565b6040519080825280602002602001820160405280156108db57816020015b604080516080810182525f80825260208201526060918101829052818101919091528152602001906001900390816108a65790505b5060808901525f5b8460ff16811015610b4c57858b013560f01c600287018a60800151838151811061090f5761090f6114db565b602090810291909101015161ffff9290921690915260808a0151805191975060028601958d013560f01c918390811061094a5761094a6114db565b60200260200101515f015161ffff168161ffff161461097c5760405163a179f8c960e01b815260040160405180910390fd5b868c013560f81c600188018b60800151848151811061099d5761099d6114db565b60200260200101516020018199508260ff1660ff1681525050506109e18a6080015183815181106109d0576109d06114db565b602002602001015160200151610c25565b60808a0151805160018701968e013560f81c919084908110610a0557610a056114db565b60200260200101516020015160ff168160ff1614610a3657604051630216496160e01b815260040160405180910390fd5b878d016004818101913560e01c90818b010182828080601f0160208091040260200160405190810160405280939291908181526020018383808284375f81840152601f19601f8201169050808301925050505050505091509091508c608001518581518110610aa757610aa76114db565b6020908102919091010151604001919091529750858d016004818101913560e01c908189010182828080601f0160208091040260200160405190810160405280939291908181526020018383808284375f81840152601f19601f8201169050808301925050505050505091509091508c608001518581518110610b2c57610b2c6114db565b6020026020010151606001819850829052505050508060010190506108e3565b50848214610b775760405163061bc83560e51b81526004810183905260248101869052604401610322565b610b8189846105ca565b5050505050505092915050565b604051828201601f831680610ba1575060205b80830184810186838901015b81831015610bc5578051835260209283019201610bad565b5050848452601f19601f8201166040525050935093915050565b5f610bf2610bed8484610c5c565b610c6e565b9392505050565b5f5f610c058784610cb7565b905061057f86868684610e2a565b9182013560f81c926001909201919050565b610c3660ff82168015906005101790565b15610c59576040516351ee585360e01b815260ff82166004820152602401610322565b50565b5f604051828482379190912092915050565b5f6040518060600160405280602381526020016118786023913982604051602001610c9a929190611730565b604051602081830303815290604052805190602001209050919050565b604051637ca8cbad60e11b815263ffffffff821660048201526060905f906001600160a01b0385169063f951975a906024015f60405180830381865afa158015610d03573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052610d2a919081019061174a565b9050610d45816020015163ffffffff16801515429091101690565b15610e2257836001600160a01b031663f951975a856001600160a01b0316631cfe79516040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d95573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610db99190611717565b6040516001600160e01b031960e084901b16815263ffffffff9190911660048201526024015f60405180830381865afa158015610df8573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052610e1f919081019061174a565b90505b519392505050565b80515f908360016003600284020401811015610e4a575f92505050610ec2565b60015f805b83811015610eb8575f610e6d608083028b0136819003810190611826565b90505f816060015160ff169050610e968c82845f0151856020015186604001518e8d8b8d610eca565b15610eaa575f975050505050505050610ec2565b5f9450925050600101610e4f565b5060019450505050505b949350505050565b604080515f808252602082018084528c905260ff8816928201929092526060810189905260808101889052819060019060a0016020604051602081039080840390855afa158015610f1d573d5f5f3e3d5ffd5b5050604051601f19015191505f9050610f36878c610f70565b9050610f60868c1015868d1186171517826001600160a01b0316846001600160a01b031614151790565b9c9b505050505050505050505050565b5f8281610f838260208602016020015190565b95945050505050565b6040805160a0810182525f80825260208201819052918101919091526060808201819052608082015290565b634e487b7160e01b5f52604160045260245ffd5b604051608081016001600160401b0381118282101715610fee57610fee610fb8565b60405290565b60405160a081016001600160401b0381118282101715610fee57610fee610fb8565b604080519081016001600160401b0381118282101715610fee57610fee610fb8565b604051601f8201601f191681016001600160401b038111828210171561106057611060610fb8565b604052919050565b803560ff81168114611078575f5ffd5b919050565b5f6001600160401b0382111561109557611095610fb8565b50601f01601f191660200190565b5f82601f8301126110b2575f5ffd5b81356110c56110c08261107d565b611038565b8181528460208386010111156110d9575f5ffd5b816020850160208301375f918101602001919091529392505050565b6001600160a01b0381168114610c59575f5ffd5b8035611078816110f5565b5f5f60408385031215611125575f5ffd5b82356001600160401b0381111561113a575f5ffd5b83016080818603121561114b575f5ffd5b611153610fcc565b813561ffff81168114611164575f5ffd5b815261117260208301611068565b602082015260408201356001600160401b0381111561118f575f5ffd5b61119b878285016110a3565b60408301525060608201356001600160401b038111156111b9575f5ffd5b6111c5878285016110a3565b60608301525092506111db905060208401611109565b90509250929050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b5f82825180855260208501945060208160051b830101602085015f5b8381101561126057601f1985840301885261124a8383516111e4565b602098890198909350919091019060010161122e565b50909695505050505050565b60408152825160408201525f602084015160a0606084015261129160e0840182611212565b90506040850151603f198483030160808501526112ae8282611212565b9150506060850151603f198483030160a08501526112cc8282611212565b9150506080850151603f198483030160c08501526112ea8282611212565b925050508260208301529392505050565b5f5f83601f84011261130b575f5ffd5b5081356001600160401b03811115611321575f5ffd5b6020830191508360208260071b8501011115610225575f5ffd5b5f5f5f5f5f6060868803121561134f575f5ffd5b853561135a816110f5565b945060208601356001600160401b03811115611374575f5ffd5b8601601f81018813611384575f5ffd5b80356001600160401b03811115611399575f5ffd5b8860208284010111156113aa575f5ffd5b6020919091019450925060408601356001600160401b038111156113cc575f5ffd5b6113d8888289016112fb565b969995985093965092949392505050565b6020815260ff825116602082015261ffff602083015116604082015263ffffffff60408301511660608201525f606083015160a0608084015261142f60c08401826111e4565b6080850151848203601f190160a0860152805180835291925060209081019181840191600582901b8501015f5b828110156114cf57601f19868303018452845161ffff815116835260ff602082015116602084015260408101516080604085015261149d60808501826111e4565b90506060820151915083810360608501526114b881836111e4565b60209788019796909601959350505060010161145c565b50979650505050505050565b634e487b7160e01b5f52603260045260245ffd5b5f6001600160401b0382111561150757611507610fb8565b5060051b60200190565b5f82601f830112611520575f5ffd5b815161152e6110c0826114ef565b8082825260208201915060208360051b86010192508583111561154f575f5ffd5b602085015b838110156115cf5780516001600160401b03811115611571575f5ffd5b8601603f81018813611581575f5ffd5b60208101516115926110c08261107d565b8181526040838301018a10156115a6575f5ffd5b8160408401602083015e5f60208383010152808652505050602083019250602081019050611554565b5095945050505050565b5f602082840312156115e9575f5ffd5b81516001600160401b038111156115fe575f5ffd5b820160a0818503121561160f575f5ffd5b611617610ff4565b8151815260208201516001600160401b03811115611633575f5ffd5b61163f86828501611511565b60208301525060408201516001600160401b0381111561165d575f5ffd5b61166986828501611511565b60408301525060608201516001600160401b03811115611687575f5ffd5b61169386828501611511565b60608301525060808201516001600160401b038111156116b1575f5ffd5b6116bd86828501611511565b608083015250949350505050565b5f6001600160401b038316806116ef57634e487b7160e01b5f52601260045260245ffd5b806001600160401b0384160491505092915050565b805163ffffffff81168114611078575f5ffd5b5f60208284031215611727575f5ffd5b610bf282611704565b5f83518060208601845e9190910191825250602001919050565b5f6020828403121561175a575f5ffd5b81516001600160401b0381111561176f575f5ffd5b820160408185031215611780575f5ffd5b611788611016565b81516001600160401b0381111561179d575f5ffd5b8201601f810186136117ad575f5ffd5b80516117bb6110c0826114ef565b8082825260208201915060208360051b8501019250888311156117dc575f5ffd5b6020840193505b828410156118075783516117f6816110f5565b8252602093840193909101906117e3565b84525061181991505060208301611704565b6020820152949350505050565b5f6080828403128015611837575f5ffd5b50611840610fcc565b823581526020808401359082015261185a60408401611068565b604082015261186b60608401611068565b6060820152939250505056fe71756572795f726573706f6e73655f303030303030303030303030303030303030307ca264697066735822122034eda57296f1839d0267b77a23e93b47c1136cec60f2ca51d16b7a95733a509364736f6c634300081c0033

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export  ]

A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.