Source Code
Overview
ETH Balance
0 ETH
Eth Value
$0.00View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Source Code Verified (Exact Match)
Contract Name:
CometblsClient
Compiler Version
v0.8.27+commit.40a35a09
Optimization Enabled:
Yes with 10000 runs
Other Settings:
prague EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
pragma solidity ^0.8.27;
import "@openzeppelin-upgradeable/contracts/proxy/utils/Initializable.sol";
import "@openzeppelin-upgradeable/contracts/proxy/utils/UUPSUpgradeable.sol";
import
"@openzeppelin-upgradeable/contracts/access/manager/AccessManagedUpgradeable.sol";
import "@openzeppelin-upgradeable/contracts/utils/PausableUpgradeable.sol";
import "../core/02-client/ILightClient.sol";
import "../core/24-host/IBCStore.sol";
import "../core/24-host/IBCCommitment.sol";
import "../lib/Common.sol";
import "../lib/ICS23.sol";
import "../lib/CometblsZKVerifier.sol";
import "../lib/ICS23Verifier.sol";
import "../internal/Versioned.sol";
struct SignedHeader {
uint64 height;
uint64 secs;
uint64 nanos;
bytes32 validatorsHash;
bytes32 nextValidatorsHash;
bytes32 appHash;
}
struct Header {
SignedHeader signedHeader;
uint64 trustedHeight;
bytes zeroKnowledgeProof;
}
struct ClientState {
bytes31 chainId;
uint64 trustingPeriod;
uint64 maxClockDrift;
uint64 frozenHeight;
uint64 latestHeight;
bytes32 contractAddress;
}
struct ConsensusState {
uint64 timestamp;
bytes32 appHash;
bytes32 nextValidatorsHash;
}
struct Misbehaviour {
Header headerA;
Header headerB;
}
library CometblsClientLib {
error ErrNotIBC();
error ErrTrustedConsensusStateNotFound();
error ErrUntrustedHeightLTETrustedHeight();
error ErrUntrustedTimestampLTETrustedTimestamp();
error ErrHeaderExpired();
error ErrMaxClockDriftExceeded();
error ErrInvalidZKP();
error ErrInvalidUntrustedValidatorsHash();
error ErrInvalidMisbehaviourHeadersSequence();
error ErrInvalidMisbehaviour();
error ErrClientFrozen();
error ErrInvalidInitialConsensusState();
function isExpired(
uint64 headerTime,
uint64 trustingPeriod,
uint64 currentTime
) internal pure returns (bool) {
return uint256(currentTime)
> (uint256(headerTime) + uint256(trustingPeriod));
}
function encodeMemory(
Header memory header
) internal pure returns (bytes memory) {
return abi.encode(
header.signedHeader, header.trustedHeight, header.zeroKnowledgeProof
);
}
function encode(
Header calldata header
) internal pure returns (bytes memory) {
return abi.encode(
header.signedHeader, header.trustedHeight, header.zeroKnowledgeProof
);
}
function decodeHeader(
bytes calldata bz
) internal pure returns (Header calldata) {
Header calldata header;
assembly {
header := bz.offset
}
return header;
}
function decodeMisbehaviour(
bytes calldata bz
) internal pure returns (Misbehaviour calldata) {
Misbehaviour calldata misbehaviour;
assembly {
misbehaviour := bz.offset
}
return misbehaviour;
}
function encodeMemory(
ClientState memory clientState
) internal pure returns (bytes memory) {
return abi.encode(
clientState.chainId,
clientState.trustingPeriod,
clientState.maxClockDrift,
clientState.frozenHeight,
clientState.latestHeight,
clientState.contractAddress
);
}
function decodeClientState(
bytes calldata bz
) internal pure returns (ClientState calldata) {
ClientState calldata clientState;
assembly {
clientState := bz.offset
}
return clientState;
}
function encodeMemory(
ConsensusState memory consensusState
) internal pure returns (bytes memory) {
return abi.encode(
consensusState.timestamp,
consensusState.appHash,
consensusState.nextValidatorsHash
);
}
function decodeConsensusState(
bytes calldata bz
) internal pure returns (ConsensusState calldata) {
ConsensusState calldata consensusState;
assembly {
consensusState := bz.offset
}
return consensusState;
}
function decodeConsensusStateMemory(
bytes memory bz
) internal pure returns (ConsensusState memory) {
ConsensusState memory consensusState;
(uint64 timestamp, bytes32 appHash, bytes32 nextValidatorsHash) =
abi.decode(bz, (uint64, bytes32, bytes32));
consensusState.timestamp = timestamp;
consensusState.appHash = appHash;
consensusState.nextValidatorsHash = nextValidatorsHash;
return consensusState;
}
function commit(
ConsensusState memory consensusState
) internal pure returns (bytes32) {
return keccak256(encodeMemory(consensusState));
}
function commit(
ClientState memory clientState
) internal pure returns (bytes32) {
return keccak256(encodeMemory(clientState));
}
function chainIdToString(
bytes31 source
) internal pure returns (string memory result) {
uint8 offset = 0;
while (source[offset] == 0 && offset < 31) {
offset++;
}
assembly {
result := mload(0x40)
// new "memory end" including padding (the string isn't larger than 32 bytes)
mstore(0x40, add(result, 0x40))
// store length in memory
mstore(result, sub(31, offset))
// write actual data
mstore(add(result, 0x20), shl(mul(offset, 8), source))
}
}
}
contract CometblsClient is
ILightClient,
IForceLightClient,
Initializable,
UUPSUpgradeable,
AccessManagedUpgradeable,
PausableUpgradeable,
Versioned
{
using CometblsClientLib for *;
address public immutable IBC_HANDLER;
mapping(uint32 => ClientState) private clientStates;
mapping(uint32 => mapping(uint64 => ConsensusState)) private consensusStates;
constructor(
address _ibcHandler
) {
_disableInitializers();
IBC_HANDLER = _ibcHandler;
}
function initialize(
address authority
) public initializer {
__AccessManaged_init(authority);
__UUPSUpgradeable_init();
__Pausable_init();
}
function createClient(
address,
uint32 clientId,
bytes calldata clientStateBytes,
bytes calldata consensusStateBytes,
address
)
external
override
onlyIBC
whenNotPaused
returns (
ConsensusStateUpdate memory update,
string memory counterpartyChainId
)
{
ClientState calldata clientState = clientStateBytes.decodeClientState();
ConsensusState calldata consensusState =
consensusStateBytes.decodeConsensusState();
if (clientState.latestHeight == 0 || consensusState.timestamp == 0) {
revert CometblsClientLib.ErrInvalidInitialConsensusState();
}
clientStates[clientId] = clientState;
consensusStates[clientId][clientState.latestHeight] = consensusState;
return (
ConsensusStateUpdate({
clientStateCommitment: clientState.commit(),
consensusStateCommitment: consensusState.commit(),
height: clientState.latestHeight
}),
CometblsClientLib.chainIdToString(clientState.chainId)
);
}
function misbehaviour(
address,
uint32 clientId,
bytes calldata clientMessageBytes,
address
) external override onlyIBC whenNotPaused {
Misbehaviour calldata m = clientMessageBytes.decodeMisbehaviour();
ClientState storage clientState = clientStates[clientId];
bool fraud =
checkMisbehaviour(clientId, clientState, m.headerA, m.headerB);
if (!fraud) {
revert CometblsClientLib.ErrInvalidMisbehaviour();
}
// Similar to tendermint https://github.com/cosmos/ibc-go/blob/bbdcc8c6e965c8a2f607dfb2b61cd13712dd966a/modules/light-clients/07-tendermint/misbehaviour.go#L19
clientState.frozenHeight = 1;
}
function checkMisbehaviour(
uint32 clientId,
ClientState storage clientState,
Header calldata headerA,
Header calldata headerB
) internal returns (bool) {
// Ensures that A > B to simplify the misbehaviour of time violation check
if (headerA.signedHeader.height < headerB.signedHeader.height) {
revert CometblsClientLib.ErrInvalidMisbehaviourHeadersSequence();
}
ConsensusState storage consensusStateA =
consensusStates[clientId][headerA.trustedHeight];
ConsensusState storage consensusStateB =
consensusStates[clientId][headerB.trustedHeight];
// Check that the headers would have been accepted in an update
(, uint64 untrustedTimestampA) =
verifyHeader(headerA, consensusStateA, clientState);
(, uint64 untrustedTimestampB) =
verifyHeader(headerB, consensusStateB, clientState);
if (headerA.signedHeader.height == headerB.signedHeader.height) {
bytes32 hashA = keccak256(abi.encode(headerA.signedHeader));
bytes32 hashB = keccak256(abi.encode(headerB.signedHeader));
if (hashA != hashB) {
// Misbehaviour of a fork
return true;
}
} else {
// Guarantee that A > B
if (untrustedTimestampA <= untrustedTimestampB) {
// Misbehaviour of time violation
return true;
}
}
return false;
}
function checkOverwriteMisbehavior(
uint64 untrustedTimestamp,
bytes32 untrustedAppHash,
bytes32 untrustedNextValidatorsHash,
ConsensusState storage overwrittenConsensusState
) internal returns (bool) {
if (
untrustedTimestamp != overwrittenConsensusState.timestamp
|| untrustedAppHash != overwrittenConsensusState.appHash
|| untrustedNextValidatorsHash
!= overwrittenConsensusState.nextValidatorsHash
) {
return true;
}
return false;
}
function verifyHeader(
Header calldata header,
ConsensusState storage consensusState,
ClientState storage clientState
) internal returns (uint64, uint64) {
if (consensusState.timestamp == 0) {
revert CometblsClientLib.ErrTrustedConsensusStateNotFound();
}
uint64 untrustedHeightNumber = header.signedHeader.height;
uint64 trustedHeightNumber = header.trustedHeight;
if (untrustedHeightNumber <= trustedHeightNumber) {
revert CometblsClientLib.ErrUntrustedHeightLTETrustedHeight();
}
uint64 trustedTimestamp = consensusState.timestamp;
// Normalize to nanosecond because ibc-go recvPacket expects nanos...
uint64 untrustedTimestamp =
header.signedHeader.secs * 1e9 + header.signedHeader.nanos;
if (untrustedTimestamp <= trustedTimestamp) {
revert CometblsClientLib.ErrUntrustedTimestampLTETrustedTimestamp();
}
// Normalize to nanosecond because ibc-go recvPacket expects nanos...
uint64 currentTime = uint64(block.timestamp * 1e9);
if (
CometblsClientLib.isExpired(
trustedTimestamp, clientState.trustingPeriod, currentTime
)
) {
revert CometblsClientLib.ErrHeaderExpired();
}
uint64 maxClockDrift = currentTime + clientState.maxClockDrift;
if (untrustedTimestamp >= maxClockDrift) {
revert CometblsClientLib.ErrMaxClockDriftExceeded();
}
/*
We want to verify that 1/3 of trusted valset & 2/3 of untrusted valset signed.
In adjacent verification, trusted vals = untrusted vals.
In non adjacent verification, untrusted vals are coming from the untrusted header.
*/
bytes32 trustedValidatorsHash = consensusState.nextValidatorsHash;
bool adjacent = untrustedHeightNumber == trustedHeightNumber + 1;
if (adjacent) {
if (header.signedHeader.validatorsHash != trustedValidatorsHash) {
revert CometblsClientLib.ErrInvalidUntrustedValidatorsHash();
}
}
bool ok = internalVerifyZKP(
header.zeroKnowledgeProof,
clientState.chainId,
trustedValidatorsHash,
header.signedHeader
);
if (!ok) {
revert CometblsClientLib.ErrInvalidZKP();
}
return (untrustedHeightNumber, untrustedTimestamp);
}
function updateClient(
address,
uint32 clientId,
bytes calldata clientMessageBytes,
address
)
external
override
onlyIBC
whenNotPaused
returns (ConsensusStateUpdate memory)
{
ClientState storage clientState = clientStates[clientId];
if (clientState.frozenHeight > 0) {
revert CometblsClientLib.ErrClientFrozen();
}
Header calldata header = clientMessageBytes.decodeHeader();
ConsensusState storage consensusState =
consensusStates[clientId][header.trustedHeight];
(uint64 untrustedHeightNumber, uint64 untrustedTimestamp) =
verifyHeader(header, consensusState, clientState);
// Update states
if (untrustedHeightNumber > clientState.latestHeight) {
clientState.latestHeight = untrustedHeightNumber;
}
consensusState = consensusStates[clientId][untrustedHeightNumber];
// Verify misbehavior on overwrite
if (consensusState.timestamp != 0) {
if (
checkOverwriteMisbehavior(
untrustedTimestamp,
header.signedHeader.appHash,
header.signedHeader.nextValidatorsHash,
consensusState
)
) {
clientState.frozenHeight = 1;
}
// Noop
} else {
consensusState.timestamp = untrustedTimestamp;
consensusState.appHash = header.signedHeader.appHash;
consensusState.nextValidatorsHash =
header.signedHeader.nextValidatorsHash;
}
return ConsensusStateUpdate({
clientStateCommitment: clientState.commit(),
consensusStateCommitment: consensusState.commit(),
height: untrustedHeightNumber
});
}
function forceUpdateClient(
address,
uint32 clientId,
bytes calldata clientStateBytes,
bytes calldata consensusStateBytes
) external onlyIBC whenNotPaused returns (ConsensusStateUpdate memory) {
ClientState calldata clientState = clientStateBytes.decodeClientState();
ConsensusState calldata consensusState =
consensusStateBytes.decodeConsensusState();
clientStates[clientId] = clientState;
consensusStates[clientId][clientState.latestHeight] = consensusState;
return ConsensusStateUpdate({
clientStateCommitment: clientState.commit(),
consensusStateCommitment: consensusState.commit(),
height: clientState.latestHeight
});
}
function verifyMembership(
uint32 clientId,
uint64 height,
bytes calldata proof,
bytes calldata path,
bytes calldata value
) external virtual whenNotPaused returns (bool) {
if (isFrozenImpl(clientId)) {
revert CometblsClientLib.ErrClientFrozen();
}
bytes32 contractAddress = clientStates[clientId].contractAddress;
bytes32 appHash = consensusStates[clientId][height].appHash;
return ICS23Verifier.verifyMembership(
appHash,
proof,
IBCStoreLib.WASMD_MODULE_STORE_KEY,
abi.encodePacked(
IBCStoreLib.WASMD_CONTRACT_STORE_PREFIX,
contractAddress,
IBCStoreLib.IBC_UNION_COSMWASM_COMMITMENT_PREFIX,
path
),
value
);
}
function verifyNonMembership(
uint32 clientId,
uint64 height,
bytes calldata proof,
bytes calldata path
) external virtual whenNotPaused returns (bool) {
if (isFrozenImpl(clientId)) {
revert CometblsClientLib.ErrClientFrozen();
}
bytes32 contractAddress = clientStates[clientId].contractAddress;
bytes32 appHash = consensusStates[clientId][height].appHash;
return ICS23Verifier.verifyNonMembership(
appHash,
proof,
IBCStoreLib.WASMD_MODULE_STORE_KEY,
abi.encodePacked(
IBCStoreLib.WASMD_CONTRACT_STORE_PREFIX,
contractAddress,
IBCStoreLib.IBC_UNION_COSMWASM_COMMITMENT_PREFIX,
path
)
);
}
function getClientState(
uint32 clientId
) external view returns (bytes memory) {
return clientStates[clientId].encodeMemory();
}
function getConsensusState(
uint32 clientId,
uint64 height
) external view returns (bytes memory) {
return consensusStates[clientId][height].encodeMemory();
}
function getTimestampAtHeight(
uint32 clientId,
uint64 height
) external view override returns (uint64) {
return consensusStates[clientId][height].timestamp;
}
function getLatestHeight(
uint32 clientId
) external view override returns (uint64) {
return clientStates[clientId].latestHeight;
}
function isFrozen(
uint32 clientId
) external view virtual whenNotPaused returns (bool) {
return isFrozenImpl(clientId);
}
function isFrozenImpl(
uint32 clientId
) internal view returns (bool) {
return clientStates[clientId].frozenHeight > 0;
}
// ZKP VERIFICATION
uint256 constant PRIME_R =
21888242871839275222246405745257275088548364400416034343698204186575808495617;
uint256 constant PRIME_R_MINUS_ONE = PRIME_R - 1;
bytes constant HMAC_I =
hex"75595B5342747A653636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636";
bytes constant HMAC_O =
hex"1F333139281E100F5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C";
function hmac_keccak(
bytes memory message
) internal pure returns (bytes32) {
return keccak256(
abi.encodePacked(
HMAC_O, keccak256(abi.encodePacked(HMAC_I, message))
)
);
}
// Union whitepaper: (1) H_{hmac_r}
function hashToField(
bytes memory message
) internal pure returns (uint256) {
return (uint256(hmac_keccak(message)) % PRIME_R_MINUS_ONE) + 1;
}
struct ZKP {
uint256[8] proof;
uint256[2] proofCommitment;
uint256[2] proofCommitmentPOK;
}
function verifyZKP(
bytes calldata zkpBytes,
bytes31 chainId,
bytes32 trustedValidatorsHash,
SignedHeader calldata header
) public virtual returns (bool) {
return
internalVerifyZKP(zkpBytes, chainId, trustedValidatorsHash, header);
}
function internalVerifyZKP(
bytes calldata zkpBytes,
bytes31 chainId,
bytes32 trustedValidatorsHash,
SignedHeader calldata header
) internal virtual returns (bool) {
ZKP calldata zkp;
assembly {
zkp := zkpBytes.offset
}
uint256 commitmentHash =
hashToField(abi.encodePacked(zkp.proofCommitment));
// Drop the most significant byte to fit in F_r
bytes32 inputsHash = sha256(
abi.encodePacked(
bytes32(uint256(uint248(chainId))),
bytes32(uint256(header.height)),
bytes32(uint256(header.secs)),
bytes32(uint256(header.nanos)),
header.validatorsHash,
header.nextValidatorsHash,
header.appHash,
trustedValidatorsHash
)
) & 0x00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
uint256[2] memory publicInputs = [
uint256(inputsHash),
// Gnark commitment API extend internal inputs with the following commitment hash and proof commitment
// See https://github.com/ConsenSys/gnark/issues/652
commitmentHash
];
return CometblsZKVerifier.verifyProof(
zkp.proof, zkp.proofCommitment, zkp.proofCommitmentPOK, publicInputs
);
}
function _authorizeUpgrade(
address newImplementation
) internal override restricted {}
function pause() public restricted {
_pause();
}
function unpause() public restricted {
_unpause();
}
function _onlyIBC() internal view {
if (msg.sender != IBC_HANDLER) {
revert CometblsClientLib.ErrNotIBC();
}
}
modifier onlyIBC() {
_onlyIBC();
_;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (proxy/utils/Initializable.sol)
pragma solidity ^0.8.20;
/**
* @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
* behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an
* external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
* function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
*
* The initialization functions use a version number. Once a version number is used, it is consumed and cannot be
* reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in
* case an upgrade adds a module that needs to be initialized.
*
* For example:
*
* [.hljs-theme-light.nopadding]
* ```solidity
* contract MyToken is ERC20Upgradeable {
* function initialize() initializer public {
* __ERC20_init("MyToken", "MTK");
* }
* }
*
* contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {
* function initializeV2() reinitializer(2) public {
* __ERC20Permit_init("MyToken");
* }
* }
* ```
*
* TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
* possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.
*
* CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
* that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
*
* [CAUTION]
* ====
* Avoid leaving a contract uninitialized.
*
* An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation
* contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke
* the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:
*
* [.hljs-theme-light.nopadding]
* ```
* /// @custom:oz-upgrades-unsafe-allow constructor
* constructor() {
* _disableInitializers();
* }
* ```
* ====
*/
abstract contract Initializable {
/**
* @dev Storage of the initializable contract.
*
* It's implemented on a custom ERC-7201 namespace to reduce the risk of storage collisions
* when using with upgradeable contracts.
*
* @custom:storage-location erc7201:openzeppelin.storage.Initializable
*/
struct InitializableStorage {
/**
* @dev Indicates that the contract has been initialized.
*/
uint64 _initialized;
/**
* @dev Indicates that the contract is in the process of being initialized.
*/
bool _initializing;
}
// keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Initializable")) - 1)) & ~bytes32(uint256(0xff))
bytes32 private constant INITIALIZABLE_STORAGE = 0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00;
/**
* @dev The contract is already initialized.
*/
error InvalidInitialization();
/**
* @dev The contract is not initializing.
*/
error NotInitializing();
/**
* @dev Triggered when the contract has been initialized or reinitialized.
*/
event Initialized(uint64 version);
/**
* @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,
* `onlyInitializing` functions can be used to initialize parent contracts.
*
* Similar to `reinitializer(1)`, except that in the context of a constructor an `initializer` may be invoked any
* number of times. This behavior in the constructor can be useful during testing and is not expected to be used in
* production.
*
* Emits an {Initialized} event.
*/
modifier initializer() {
// solhint-disable-next-line var-name-mixedcase
InitializableStorage storage $ = _getInitializableStorage();
// Cache values to avoid duplicated sloads
bool isTopLevelCall = !$._initializing;
uint64 initialized = $._initialized;
// Allowed calls:
// - initialSetup: the contract is not in the initializing state and no previous version was
// initialized
// - construction: the contract is initialized at version 1 (no reininitialization) and the
// current contract is just being deployed
bool initialSetup = initialized == 0 && isTopLevelCall;
bool construction = initialized == 1 && address(this).code.length == 0;
if (!initialSetup && !construction) {
revert InvalidInitialization();
}
$._initialized = 1;
if (isTopLevelCall) {
$._initializing = true;
}
_;
if (isTopLevelCall) {
$._initializing = false;
emit Initialized(1);
}
}
/**
* @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the
* contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be
* used to initialize parent contracts.
*
* A reinitializer may be used after the original initialization step. This is essential to configure modules that
* are added through upgrades and that require initialization.
*
* When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`
* cannot be nested. If one is invoked in the context of another, execution will revert.
*
* Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in
* a contract, executing them in the right order is up to the developer or operator.
*
* WARNING: Setting the version to 2**64 - 1 will prevent any future reinitialization.
*
* Emits an {Initialized} event.
*/
modifier reinitializer(uint64 version) {
// solhint-disable-next-line var-name-mixedcase
InitializableStorage storage $ = _getInitializableStorage();
if ($._initializing || $._initialized >= version) {
revert InvalidInitialization();
}
$._initialized = version;
$._initializing = true;
_;
$._initializing = false;
emit Initialized(version);
}
/**
* @dev Modifier to protect an initialization function so that it can only be invoked by functions with the
* {initializer} and {reinitializer} modifiers, directly or indirectly.
*/
modifier onlyInitializing() {
_checkInitializing();
_;
}
/**
* @dev Reverts if the contract is not in an initializing state. See {onlyInitializing}.
*/
function _checkInitializing() internal view virtual {
if (!_isInitializing()) {
revert NotInitializing();
}
}
/**
* @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.
* Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized
* to any version. It is recommended to use this to lock implementation contracts that are designed to be called
* through proxies.
*
* Emits an {Initialized} event the first time it is successfully executed.
*/
function _disableInitializers() internal virtual {
// solhint-disable-next-line var-name-mixedcase
InitializableStorage storage $ = _getInitializableStorage();
if ($._initializing) {
revert InvalidInitialization();
}
if ($._initialized != type(uint64).max) {
$._initialized = type(uint64).max;
emit Initialized(type(uint64).max);
}
}
/**
* @dev Returns the highest version that has been initialized. See {reinitializer}.
*/
function _getInitializedVersion() internal view returns (uint64) {
return _getInitializableStorage()._initialized;
}
/**
* @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.
*/
function _isInitializing() internal view returns (bool) {
return _getInitializableStorage()._initializing;
}
/**
* @dev Returns a pointer to the storage namespace.
*/
// solhint-disable-next-line var-name-mixedcase
function _getInitializableStorage() private pure returns (InitializableStorage storage $) {
assembly {
$.slot := INITIALIZABLE_STORAGE
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.2.0) (proxy/utils/UUPSUpgradeable.sol)
pragma solidity ^0.8.22;
import {IERC1822Proxiable} from "@openzeppelin/contracts/interfaces/draft-IERC1822.sol";
import {ERC1967Utils} from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Utils.sol";
import {Initializable} from "./Initializable.sol";
/**
* @dev An upgradeability mechanism designed for UUPS proxies. The functions included here can perform an upgrade of an
* {ERC1967Proxy}, when this contract is set as the implementation behind such a proxy.
*
* A security mechanism ensures that an upgrade does not turn off upgradeability accidentally, although this risk is
* reinstated if the upgrade retains upgradeability but removes the security mechanism, e.g. by replacing
* `UUPSUpgradeable` with a custom implementation of upgrades.
*
* The {_authorizeUpgrade} function must be overridden to include access restriction to the upgrade mechanism.
*/
abstract contract UUPSUpgradeable is Initializable, IERC1822Proxiable {
/// @custom:oz-upgrades-unsafe-allow state-variable-immutable
address private immutable __self = address(this);
/**
* @dev The version of the upgrade interface of the contract. If this getter is missing, both `upgradeTo(address)`
* and `upgradeToAndCall(address,bytes)` are present, and `upgradeTo` must be used if no function should be called,
* while `upgradeToAndCall` will invoke the `receive` function if the second argument is the empty byte string.
* If the getter returns `"5.0.0"`, only `upgradeToAndCall(address,bytes)` is present, and the second argument must
* be the empty byte string if no function should be called, making it impossible to invoke the `receive` function
* during an upgrade.
*/
string public constant UPGRADE_INTERFACE_VERSION = "5.0.0";
/**
* @dev The call is from an unauthorized context.
*/
error UUPSUnauthorizedCallContext();
/**
* @dev The storage `slot` is unsupported as a UUID.
*/
error UUPSUnsupportedProxiableUUID(bytes32 slot);
/**
* @dev Check that the execution is being performed through a delegatecall call and that the execution context is
* a proxy contract with an implementation (as defined in ERC-1967) pointing to self. This should only be the case
* for UUPS and transparent proxies that are using the current contract as their implementation. Execution of a
* function through ERC-1167 minimal proxies (clones) would not normally pass this test, but is not guaranteed to
* fail.
*/
modifier onlyProxy() {
_checkProxy();
_;
}
/**
* @dev Check that the execution is not being performed through a delegate call. This allows a function to be
* callable on the implementing contract but not through proxies.
*/
modifier notDelegated() {
_checkNotDelegated();
_;
}
function __UUPSUpgradeable_init() internal onlyInitializing {
}
function __UUPSUpgradeable_init_unchained() internal onlyInitializing {
}
/**
* @dev Implementation of the ERC-1822 {proxiableUUID} function. This returns the storage slot used by the
* implementation. It is used to validate the implementation's compatibility when performing an upgrade.
*
* IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks
* bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this
* function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier.
*/
function proxiableUUID() external view virtual notDelegated returns (bytes32) {
return ERC1967Utils.IMPLEMENTATION_SLOT;
}
/**
* @dev Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call
* encoded in `data`.
*
* Calls {_authorizeUpgrade}.
*
* Emits an {Upgraded} event.
*
* @custom:oz-upgrades-unsafe-allow-reachable delegatecall
*/
function upgradeToAndCall(address newImplementation, bytes memory data) public payable virtual onlyProxy {
_authorizeUpgrade(newImplementation);
_upgradeToAndCallUUPS(newImplementation, data);
}
/**
* @dev Reverts if the execution is not performed via delegatecall or the execution
* context is not of a proxy with an ERC-1967 compliant implementation pointing to self.
* See {_onlyProxy}.
*/
function _checkProxy() internal view virtual {
if (
address(this) == __self || // Must be called through delegatecall
ERC1967Utils.getImplementation() != __self // Must be called through an active proxy
) {
revert UUPSUnauthorizedCallContext();
}
}
/**
* @dev Reverts if the execution is performed via delegatecall.
* See {notDelegated}.
*/
function _checkNotDelegated() internal view virtual {
if (address(this) != __self) {
// Must not be called through delegatecall
revert UUPSUnauthorizedCallContext();
}
}
/**
* @dev Function that should revert when `msg.sender` is not authorized to upgrade the contract. Called by
* {upgradeToAndCall}.
*
* Normally, this function will use an xref:access.adoc[access control] modifier such as {Ownable-onlyOwner}.
*
* ```solidity
* function _authorizeUpgrade(address) internal onlyOwner {}
* ```
*/
function _authorizeUpgrade(address newImplementation) internal virtual;
/**
* @dev Performs an implementation upgrade with a security check for UUPS proxies, and additional setup call.
*
* As a security check, {proxiableUUID} is invoked in the new implementation, and the return value
* is expected to be the implementation slot in ERC-1967.
*
* Emits an {IERC1967-Upgraded} event.
*/
function _upgradeToAndCallUUPS(address newImplementation, bytes memory data) private {
try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) {
if (slot != ERC1967Utils.IMPLEMENTATION_SLOT) {
revert UUPSUnsupportedProxiableUUID(slot);
}
ERC1967Utils.upgradeToAndCall(newImplementation, data);
} catch {
// The implementation is not UUPS
revert ERC1967Utils.ERC1967InvalidImplementation(newImplementation);
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (access/manager/AccessManaged.sol)
pragma solidity ^0.8.20;
import {IAuthority} from "@openzeppelin/contracts/access/manager/IAuthority.sol";
import {AuthorityUtils} from "@openzeppelin/contracts/access/manager/AuthorityUtils.sol";
import {IAccessManager} from "@openzeppelin/contracts/access/manager/IAccessManager.sol";
import {IAccessManaged} from "@openzeppelin/contracts/access/manager/IAccessManaged.sol";
import {ContextUpgradeable} from "../../utils/ContextUpgradeable.sol";
import {Initializable} from "../../proxy/utils/Initializable.sol";
/**
* @dev This contract module makes available a {restricted} modifier. Functions decorated with this modifier will be
* permissioned according to an "authority": a contract like {AccessManager} that follows the {IAuthority} interface,
* implementing a policy that allows certain callers to access certain functions.
*
* IMPORTANT: The `restricted` modifier should never be used on `internal` functions, judiciously used in `public`
* functions, and ideally only used in `external` functions. See {restricted}.
*/
abstract contract AccessManagedUpgradeable is Initializable, ContextUpgradeable, IAccessManaged {
/// @custom:storage-location erc7201:openzeppelin.storage.AccessManaged
struct AccessManagedStorage {
address _authority;
bool _consumingSchedule;
}
// keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.AccessManaged")) - 1)) & ~bytes32(uint256(0xff))
bytes32 private constant AccessManagedStorageLocation = 0xf3177357ab46d8af007ab3fdb9af81da189e1068fefdc0073dca88a2cab40a00;
function _getAccessManagedStorage() private pure returns (AccessManagedStorage storage $) {
assembly {
$.slot := AccessManagedStorageLocation
}
}
/**
* @dev Initializes the contract connected to an initial authority.
*/
function __AccessManaged_init(address initialAuthority) internal onlyInitializing {
__AccessManaged_init_unchained(initialAuthority);
}
function __AccessManaged_init_unchained(address initialAuthority) internal onlyInitializing {
_setAuthority(initialAuthority);
}
/**
* @dev Restricts access to a function as defined by the connected Authority for this contract and the
* caller and selector of the function that entered the contract.
*
* [IMPORTANT]
* ====
* In general, this modifier should only be used on `external` functions. It is okay to use it on `public`
* functions that are used as external entry points and are not called internally. Unless you know what you're
* doing, it should never be used on `internal` functions. Failure to follow these rules can have critical security
* implications! This is because the permissions are determined by the function that entered the contract, i.e. the
* function at the bottom of the call stack, and not the function where the modifier is visible in the source code.
* ====
*
* [WARNING]
* ====
* Avoid adding this modifier to the https://docs.soliditylang.org/en/v0.8.20/contracts.html#receive-ether-function[`receive()`]
* function or the https://docs.soliditylang.org/en/v0.8.20/contracts.html#fallback-function[`fallback()`]. These
* functions are the only execution paths where a function selector cannot be unambiguously determined from the calldata
* since the selector defaults to `0x00000000` in the `receive()` function and similarly in the `fallback()` function
* if no calldata is provided. (See {_checkCanCall}).
*
* The `receive()` function will always panic whereas the `fallback()` may panic depending on the calldata length.
* ====
*/
modifier restricted() {
_checkCanCall(_msgSender(), _msgData());
_;
}
/// @inheritdoc IAccessManaged
function authority() public view virtual returns (address) {
AccessManagedStorage storage $ = _getAccessManagedStorage();
return $._authority;
}
/// @inheritdoc IAccessManaged
function setAuthority(address newAuthority) public virtual {
address caller = _msgSender();
if (caller != authority()) {
revert AccessManagedUnauthorized(caller);
}
if (newAuthority.code.length == 0) {
revert AccessManagedInvalidAuthority(newAuthority);
}
_setAuthority(newAuthority);
}
/// @inheritdoc IAccessManaged
function isConsumingScheduledOp() public view returns (bytes4) {
AccessManagedStorage storage $ = _getAccessManagedStorage();
return $._consumingSchedule ? this.isConsumingScheduledOp.selector : bytes4(0);
}
/**
* @dev Transfers control to a new authority. Internal function with no access restriction. Allows bypassing the
* permissions set by the current authority.
*/
function _setAuthority(address newAuthority) internal virtual {
AccessManagedStorage storage $ = _getAccessManagedStorage();
$._authority = newAuthority;
emit AuthorityUpdated(newAuthority);
}
/**
* @dev Reverts if the caller is not allowed to call the function identified by a selector. Panics if the calldata
* is less than 4 bytes long.
*/
function _checkCanCall(address caller, bytes calldata data) internal virtual {
AccessManagedStorage storage $ = _getAccessManagedStorage();
(bool immediate, uint32 delay) = AuthorityUtils.canCallWithDelay(
authority(),
caller,
address(this),
bytes4(data[0:4])
);
if (!immediate) {
if (delay > 0) {
$._consumingSchedule = true;
IAccessManager(authority()).consumeScheduledOp(caller, data);
$._consumingSchedule = false;
} else {
revert AccessManagedUnauthorized(caller);
}
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/Pausable.sol)
pragma solidity ^0.8.20;
import {ContextUpgradeable} from "../utils/ContextUpgradeable.sol";
import {Initializable} from "../proxy/utils/Initializable.sol";
/**
* @dev Contract module which allows children to implement an emergency stop
* mechanism that can be triggered by an authorized account.
*
* This module is used through inheritance. It will make available the
* modifiers `whenNotPaused` and `whenPaused`, which can be applied to
* the functions of your contract. Note that they will not be pausable by
* simply including this module, only once the modifiers are put in place.
*/
abstract contract PausableUpgradeable is Initializable, ContextUpgradeable {
/// @custom:storage-location erc7201:openzeppelin.storage.Pausable
struct PausableStorage {
bool _paused;
}
// keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Pausable")) - 1)) & ~bytes32(uint256(0xff))
bytes32 private constant PausableStorageLocation = 0xcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f03300;
function _getPausableStorage() private pure returns (PausableStorage storage $) {
assembly {
$.slot := PausableStorageLocation
}
}
/**
* @dev Emitted when the pause is triggered by `account`.
*/
event Paused(address account);
/**
* @dev Emitted when the pause is lifted by `account`.
*/
event Unpaused(address account);
/**
* @dev The operation failed because the contract is paused.
*/
error EnforcedPause();
/**
* @dev The operation failed because the contract is not paused.
*/
error ExpectedPause();
/**
* @dev Initializes the contract in unpaused state.
*/
function __Pausable_init() internal onlyInitializing {
__Pausable_init_unchained();
}
function __Pausable_init_unchained() internal onlyInitializing {
PausableStorage storage $ = _getPausableStorage();
$._paused = false;
}
/**
* @dev Modifier to make a function callable only when the contract is not paused.
*
* Requirements:
*
* - The contract must not be paused.
*/
modifier whenNotPaused() {
_requireNotPaused();
_;
}
/**
* @dev Modifier to make a function callable only when the contract is paused.
*
* Requirements:
*
* - The contract must be paused.
*/
modifier whenPaused() {
_requirePaused();
_;
}
/**
* @dev Returns true if the contract is paused, and false otherwise.
*/
function paused() public view virtual returns (bool) {
PausableStorage storage $ = _getPausableStorage();
return $._paused;
}
/**
* @dev Throws if the contract is paused.
*/
function _requireNotPaused() internal view virtual {
if (paused()) {
revert EnforcedPause();
}
}
/**
* @dev Throws if the contract is not paused.
*/
function _requirePaused() internal view virtual {
if (!paused()) {
revert ExpectedPause();
}
}
/**
* @dev Triggers stopped state.
*
* Requirements:
*
* - The contract must not be paused.
*/
function _pause() internal virtual whenNotPaused {
PausableStorage storage $ = _getPausableStorage();
$._paused = true;
emit Paused(_msgSender());
}
/**
* @dev Returns to normal state.
*
* Requirements:
*
* - The contract must be paused.
*/
function _unpause() internal virtual whenPaused {
PausableStorage storage $ = _getPausableStorage();
$._paused = false;
emit Unpaused(_msgSender());
}
}pragma solidity ^0.8.27;
import "../Types.sol";
struct ConsensusStateUpdate {
bytes32 clientStateCommitment;
bytes32 consensusStateCommitment;
uint64 height;
}
event CreateLensClient(
uint32 indexed clientId,
uint32 indexed l1ClientId,
uint32 indexed l2ClientId,
string l2ChainId
);
/**
* @dev This defines an interface for Light Client contract can be integrated with ibc-solidity.
* You can register the Light Client contract that implements this through `registerClient` on IBCHandler.
*/
interface ILightClient {
/**
* @dev createClient creates a new client with the given state.
* If succeeded, it returns a commitment for the initial state.
*/
function createClient(
address caller,
uint32 clientId,
bytes calldata clientStateBytes,
bytes calldata consensusStateBytes,
address relayer
)
external
returns (
ConsensusStateUpdate memory update,
string memory counterpartyChainId
);
/**
* @dev getTimestampAtHeight returns the timestamp of the consensus state at the given height.
*/
function getTimestampAtHeight(
uint32 clientId,
uint64 height
) external view returns (uint64);
/**
* @dev getLatestHeight returns the latest height of the client state corresponding to `clientId`.
*/
function getLatestHeight(
uint32 clientId
) external view returns (uint64 height);
/**
* @dev updateClient updates the client corresponding to `clientId`.
* If succeeded, it returns a commitment for the updated state.
* If there are no updates for consensus state, this function should returns an empty array as `updates`.
*
* NOTE: updateClient is intended to perform the followings:
* 1. verify a given client message(e.g. header)
* 2. check misbehaviour such like duplicate block height
* 3. if misbehaviour is found, update state accordingly and return
* 4. update state(s) with the client message
* 5. persist the state(s) on the host
*/
function updateClient(
address caller,
uint32 clientId,
bytes calldata clientMessageBytes,
address relayer
) external returns (ConsensusStateUpdate memory update);
/**
* @dev misbehaviour is used for submitting a misbehaviour to `clientId`.
* If succeeded, the client should freeze itself to prevent getting further updates.
*/
function misbehaviour(
address caller,
uint32 clientId,
bytes calldata clientMessageBytes,
address relayer
) external;
/**
* @dev verifyMembership is a generic proof verification method which verifies a proof of the existence of a value at a given CommitmentPath at the specified height.
* The caller is expected to construct the full CommitmentPath from a CommitmentPrefix and a standardized path (as defined in ICS 24).
*/
function verifyMembership(
uint32 clientId,
uint64 height,
bytes calldata proof,
bytes calldata path,
bytes calldata value
) external returns (bool);
/**
* @dev verifyNonMembership is a generic proof verification method which verifies the absence of a given CommitmentPath at a specified height.
* The caller is expected to construct the full CommitmentPath from a CommitmentPrefix and a standardized path (as defined in ICS 24).
*/
function verifyNonMembership(
uint32 clientId,
uint64 height,
bytes calldata proof,
bytes calldata path
) external returns (bool);
/**
* @dev getClientState returns the clientState corresponding to `clientId`.
*/
function getClientState(
uint32 clientId
) external view returns (bytes memory);
/**
* @dev getConsensusState returns the consensusState corresponding to `clientId` and `height`.
*/
function getConsensusState(
uint32 clientId,
uint64 height
) external view returns (bytes memory);
/**
* @dev isFrozen returns whether the `clientId` is frozen or not.
*/
function isFrozen(
uint32 clientId
) external view returns (bool);
}
interface IForceLightClient {
function forceUpdateClient(
address caller,
uint32 clientId,
bytes calldata clientStateBytes,
bytes calldata consensusStateBytes
) external returns (ConsensusStateUpdate memory update);
}pragma solidity ^0.8.27;
import
"@openzeppelin-upgradeable/contracts/access/manager/AccessManagedUpgradeable.sol";
import "../02-client/ILightClient.sol";
import "../05-port/IIBCModule.sol";
import "../Types.sol";
library IBCStoreLib {
bytes public constant WASMD_MODULE_STORE_KEY = bytes("wasm");
bytes1 public constant WASMD_CONTRACT_STORE_PREFIX = 0x03;
bytes1 public constant IBC_UNION_COSMWASM_COMMITMENT_PREFIX = 0x00;
uint256 public constant IBC_UNION_EVM_COMMITMENT_SLOT = 0;
}
abstract contract IBCStore is AccessManagedUpgradeable {
// Commitments
// keccak256(IBC-compatible-store-path) => keccak256(IBC-compatible-commitment)
mapping(bytes32 => bytes32) public commitments;
// ClientType -> Address
mapping(string => address) public clientRegistry;
// ClientId -> ClientType
mapping(uint32 => string) public clientTypes;
// ClientId -> Address
mapping(uint32 => address) public clientImpls;
// ConnectionId -> Connection
mapping(uint32 => IBCConnection) public connections;
// ChannelId -> Channel
mapping(uint32 => IBCChannel) public channels;
// ChannelId -> PortId
mapping(uint32 => address) public channelOwner;
// Sequences for identifier
bytes32 constant nextClientSequencePath = keccak256("nextClientSequence");
bytes32 constant nextConnectionSequencePath =
keccak256("nextConnectionSequence");
bytes32 constant nextChannelSequencePath = keccak256("nextChannelSequence");
function getClient(
uint32 clientId
) public view returns (ILightClient) {
return getClientInternal(clientId);
}
function getClientInternal(
uint32 clientId
) internal view returns (ILightClient) {
address clientImpl = clientImpls[clientId];
if (clientImpl == address(0)) {
revert IBCErrors.ErrClientNotFound();
}
return ILightClient(clientImpl);
}
function lookupModuleByChannel(
uint32 channelId
) internal view virtual returns (IIBCModule) {
address module = channelOwner[channelId];
if (module == address(0)) {
revert IBCErrors.ErrModuleNotFound();
}
return IIBCModule(module);
}
function claimChannel(address portId, uint32 channelId) internal {
channelOwner[channelId] = portId;
}
function authenticateChannelOwner(
uint32 channelId
) internal view returns (bool) {
return msg.sender == channelOwner[channelId];
}
function ensureConnectionState(
uint32 connectionId
) internal view returns (uint32) {
IBCConnection storage connection = connections[connectionId];
if (connection.state != IBCConnectionState.Open) {
revert IBCErrors.ErrInvalidConnectionState();
}
return connection.clientId;
}
function ensureChannelState(
uint32 channelId
) internal view returns (IBCChannel storage) {
IBCChannel storage channel = channels[channelId];
if (channel.state != IBCChannelState.Open) {
revert IBCErrors.ErrInvalidChannelState();
}
return channel;
}
}pragma solidity ^0.8.27;
library IBCCommitment {
uint256 public constant CLIENT_STATE = 0x00;
uint256 public constant CONSENSUS_STATE = 0x01;
uint256 public constant CONNECTIONS = 0x02;
uint256 public constant CHANNELS = 0x03;
uint256 public constant PACKETS = 0x04;
uint256 public constant PACKET_ACKS = 0x05;
function clientStatePath(
uint32 clientId
) internal pure returns (bytes memory) {
return abi.encode(CLIENT_STATE, clientId);
}
function consensusStatePath(
uint32 clientId,
uint64 height
) internal pure returns (bytes memory) {
return abi.encode(CONSENSUS_STATE, clientId, height);
}
function connectionPath(
uint32 connectionId
) internal pure returns (bytes memory) {
return abi.encode(CONNECTIONS, connectionId);
}
function channelPath(
uint32 channelId
) internal pure returns (bytes memory) {
return abi.encode(CHANNELS, channelId);
}
function batchPacketsCommitmentPath(
bytes32 batchHash
) internal pure returns (bytes memory) {
return abi.encode(PACKETS, batchHash);
}
function batchReceiptsCommitmentPath(
bytes32 batchHash
) internal pure returns (bytes memory) {
return abi.encode(PACKET_ACKS, batchHash);
}
// Key generators for Commitment mapping
function clientStateCommitmentKey(
uint32 clientId
) internal pure returns (bytes32) {
return keccak256(clientStatePath(clientId));
}
function consensusStateCommitmentKey(
uint32 clientId,
uint64 height
) internal pure returns (bytes32) {
return keccak256(consensusStatePath(clientId, height));
}
function connectionCommitmentKey(
uint32 connectionId
) internal pure returns (bytes32) {
return keccak256(connectionPath(connectionId));
}
function channelCommitmentKey(
uint32 channelId
) internal pure returns (bytes32) {
return keccak256(channelPath(channelId));
}
function batchPacketsCommitmentKey(
bytes32 batchHash
) internal pure returns (bytes32) {
return keccak256(batchPacketsCommitmentPath(batchHash));
}
function batchReceiptsCommitmentKey(
bytes32 batchHash
) internal pure returns (bytes32) {
return keccak256(batchReceiptsCommitmentPath(batchHash));
}
}pragma solidity ^0.8.27;
struct ProcessedMoment {
uint256 timestamp;
uint256 height;
}pragma solidity ^0.8.27;
import {Math} from "@openzeppelin/contracts/utils/math/Math.sol";
import "./UnionICS23.sol";
library Ics23 {
enum VerifyChainedNonMembershipError {
None,
NonExistenceProofIsNil,
ExistenceProofIsNil,
InvalidProofRoot,
KeyMismatch,
ValueMismatch,
InvalidSpec,
InvalidIntermediateProofRoot,
IntermateProofRootMismatch,
RootMismatch,
VerifyLeft,
VerifyRight,
LeftAndRightKeyEmpty,
RightKeyRange,
LeftKeyRange,
RightProofLeftMost,
LeftProofRightMost,
IsLeftNeighbor
}
function verifyChainedNonMembership(
UnionIcs23.NonExistenceProof calldata nonExistProof,
UnionIcs23.ExistenceProof calldata existProof,
bytes32 root,
bytes memory prefix,
bytes memory key
) internal pure returns (VerifyChainedNonMembershipError) {
(bytes32 subroot, Proof.CalculateRootError rCode) =
Proof.calculateRoot(nonExistProof);
if (rCode != Proof.CalculateRootError.None) {
return VerifyChainedNonMembershipError.InvalidProofRoot;
}
Proof.VerifyNonExistenceError vCode = Proof.verify(
nonExistProof, UnionIcs23.getIavlProofSpec(), subroot, key
);
// Map non existence error to non membership error
if (vCode != Proof.VerifyNonExistenceError.None) {
if (vCode == Proof.VerifyNonExistenceError.VerifyLeft) {
return VerifyChainedNonMembershipError.VerifyLeft;
} else if (
vCode == Proof.VerifyNonExistenceError.LeftAndRightKeyEmpty
) {
return VerifyChainedNonMembershipError.LeftAndRightKeyEmpty;
} else if (vCode == Proof.VerifyNonExistenceError.RightKeyRange) {
return VerifyChainedNonMembershipError.RightKeyRange;
} else if (vCode == Proof.VerifyNonExistenceError.LeftKeyRange) {
return VerifyChainedNonMembershipError.LeftKeyRange;
} else if (
vCode == Proof.VerifyNonExistenceError.RightProofLeftMost
) {
return VerifyChainedNonMembershipError.RightProofLeftMost;
} else if (
vCode == Proof.VerifyNonExistenceError.LeftProofRightMost
) {
return VerifyChainedNonMembershipError.LeftProofRightMost;
} else if (vCode == Proof.VerifyNonExistenceError.IsLeftNeighbor) {
return VerifyChainedNonMembershipError.IsLeftNeighbor;
}
revert(
"verifyChainedNonMembership: non exhaustive pattern matching on VerifyNonExistenceError"
);
}
bytes32 subroot2;
(subroot2, rCode) = Proof.calculateRoot(existProof);
if (rCode != Proof.CalculateRootError.None) {
return VerifyChainedNonMembershipError.InvalidProofRoot;
}
// We don't want the above root calculation to be done again. Since we calculated it, we also don't
// need to check it against anything.
Proof.VerifyExistenceError mCode = Proof.verifyNoRootCheck(
existProof,
UnionIcs23.getTendermintProofSpec(),
prefix,
abi.encodePacked(subroot)
);
if (mCode != Proof.VerifyExistenceError.None) {
if (mCode == Proof.VerifyExistenceError.KeyNotMatching) {
return VerifyChainedNonMembershipError.KeyMismatch;
} else if (mCode == Proof.VerifyExistenceError.ValueNotMatching) {
return VerifyChainedNonMembershipError.ValueMismatch;
} else if (mCode == Proof.VerifyExistenceError.CheckSpec) {
return VerifyChainedNonMembershipError.InvalidSpec;
} else if (mCode == Proof.VerifyExistenceError.CalculateRoot) {
return
VerifyChainedNonMembershipError.InvalidIntermediateProofRoot;
} else if (mCode == Proof.VerifyExistenceError.RootNotMatching) {
return
VerifyChainedNonMembershipError.IntermateProofRootMismatch;
}
revert(
"verifyChainedNonMembership: non exhaustive pattern matching on VerifyNonExistenceError"
);
}
if (root != subroot2) {
return VerifyChainedNonMembershipError.RootMismatch;
}
return VerifyChainedNonMembershipError.None;
}
enum VerifyChainedMembershipError {
None,
ExistenceProofIsNil,
InvalidProofRoot,
KeyMismatch,
ValueMismatch,
InvalidSpec,
InvalidIntermediateProofRoot,
IntermateProofRootMismatch,
RootMismatch
}
function verifyChainedMembership(
UnionIcs23.ExistenceProof[2] calldata proofs,
bytes32 root,
bytes memory prefix,
bytes memory key,
bytes calldata value
) internal pure returns (VerifyChainedMembershipError) {
(bytes32 subroot, Proof.CalculateRootError rCode) =
Proof.calculateRoot(proofs[0]);
if (rCode != Proof.CalculateRootError.None) {
return VerifyChainedMembershipError.InvalidProofRoot;
}
// We don't want the above root calculation to be done again. Since we calculated it, we also don't
// need to check it against anything.
Proof.VerifyExistenceError vCode = Proof.verifyNoRootCheck(
proofs[0], UnionIcs23.getIavlProofSpec(), key, value
);
if (vCode != Proof.VerifyExistenceError.None) {
return convertExistenceError(vCode);
}
// This will check whether the calculated root of `proofs[1]` matches the `root`
vCode = Proof.verify(
proofs[1],
UnionIcs23.getTendermintProofSpec(),
root,
prefix,
abi.encodePacked(subroot)
);
if (vCode != Proof.VerifyExistenceError.None) {
return convertExistenceError(vCode);
}
return VerifyChainedMembershipError.None;
}
function convertExistenceError(
Proof.VerifyExistenceError vCode
) internal pure returns (VerifyChainedMembershipError) {
if (vCode == Proof.VerifyExistenceError.KeyNotMatching) {
return VerifyChainedMembershipError.KeyMismatch;
} else if (vCode == Proof.VerifyExistenceError.ValueNotMatching) {
return VerifyChainedMembershipError.ValueMismatch;
} else if (vCode == Proof.VerifyExistenceError.CheckSpec) {
return VerifyChainedMembershipError.InvalidSpec;
} else if (vCode == Proof.VerifyExistenceError.CalculateRoot) {
return VerifyChainedMembershipError.InvalidIntermediateProofRoot;
} else if (vCode == Proof.VerifyExistenceError.RootNotMatching) {
return VerifyChainedMembershipError.IntermateProofRootMismatch;
}
revert(
"verifyChainedMembership: non exhaustive pattern matching on VerifyExistenceError"
);
}
function isLeft(
UnionIcs23.ExistenceProof calldata left,
bytes calldata key
) private pure returns (bool) {
// CosmosIcs23V1ExistenceProof.isNil does not work
return UnionIcs23.empty(left) || Ops.compare(left.key, key) < 0;
}
function isRight(
UnionIcs23.ExistenceProof calldata right,
bytes calldata key
) private pure returns (bool) {
// CosmosIcs23V1ExistenceProof.isNil does not work
return UnionIcs23.empty(right) || Ops.compare(right.key, key) > 0;
}
}
library Ops {
enum ApplyLeafOpError {
None,
KeyLength,
ValueLength
}
function _sz_varint(
uint256 i
) internal pure returns (uint256) {
uint256 count = 1;
assembly {
i := shr(7, i)
for {} gt(i, 0) {} {
i := shr(7, i)
count := add(count, 1)
}
}
return count;
}
function _encode_varint(
uint256 x,
uint256 p,
bytes memory bs
) internal pure returns (uint256) {
/**
* Refer to https://developers.google.com/protocol-buffers/docs/encoding
*/
uint256 sz = 0;
assembly {
let bsptr := add(bs, p)
let byt := and(x, 0x7f)
for {} gt(shr(7, x), 0) {} {
mstore8(bsptr, or(0x80, byt))
bsptr := add(bsptr, 1)
sz := add(sz, 1)
x := shr(7, x)
byt := and(x, 0x7f)
}
mstore8(bsptr, byt)
sz := add(sz, 1)
}
return sz;
}
// LeafOp operations
function applyLeafOp(
bytes calldata prefix,
bytes calldata key,
bytes calldata value
) internal pure returns (bytes32, ApplyLeafOpError) {
//require(key.length > 0); // dev: Leaf op needs key
if (key.length == 0) return ("", ApplyLeafOpError.KeyLength);
//require(value.length > 0); // dev: Leaf op needs value
if (value.length == 0) return ("", ApplyLeafOpError.ValueLength);
// tm/iavl specs set hashOp for prehash_key to NOOP and lengthOp to VAR_PROTO
bytes memory encodedKey = new bytes(_sz_varint(key.length));
_encode_varint(key.length, 32, encodedKey);
// tm/iavl specs set hashOp for prehash_value to SHA256 and lengthOp to VAR_PROTO
bytes32 hashedValue = sha256(value);
bytes memory encodedValue = new bytes(_sz_varint(32));
_encode_varint(32, 32, encodedValue);
bytes32 data = sha256(
abi.encodePacked(prefix, encodedKey, key, encodedValue, hashedValue)
);
return (data, ApplyLeafOpError.None);
}
enum CheckAgainstSpecError {
None,
MinPrefixLength,
HasPrefix,
MaxPrefixLength
}
enum ApplyInnerOpError {
None,
ChildLength,
DoHash
}
// InnerOp operations
function applyOp(
UnionIcs23.InnerOp calldata innerOp,
bytes32 child
) internal pure returns (bytes32, ApplyInnerOpError) {
//require(child.length > 0); // dev: Inner op needs child value
if (child.length == 0) return ("", ApplyInnerOpError.ChildLength);
bytes memory preImage =
abi.encodePacked(innerOp.prefix, child, innerOp.suffix);
// inner_spec.hash is always SHA256 in the tm/iavl specs
return (sha256(preImage), ApplyInnerOpError.None);
}
function compare(
bytes memory a,
bytes calldata b
) internal pure returns (int256) {
uint256 minLen = Math.min(a.length, b.length);
for (uint256 i; i < minLen; i++) {
bytes1 ai = a[i];
bytes1 bi = b[i];
if (ai < bi) {
return -1;
} else if (ai > bi) {
return 1;
}
}
if (a.length > minLen) {
return 1;
}
if (b.length > minLen) {
return -1;
}
return 0;
}
}
library Proof {
bytes constant empty = new bytes(0);
enum VerifyExistenceError {
None,
KeyNotMatching,
ValueNotMatching,
CheckSpec,
CalculateRoot,
RootNotMatching
}
function verifyNoRootCheck(
UnionIcs23.ExistenceProof calldata proof,
UnionIcs23.ProofSpec memory spec,
bytes memory key,
bytes memory value
) internal pure returns (VerifyExistenceError) {
//require(BytesLib.equal(proof.key, key)); // dev: Provided key doesn't match proof
if (keccak256(proof.key) != keccak256(key)) {
return VerifyExistenceError.KeyNotMatching;
}
//require(BytesLib.equal(proof.value, value)); // dev: Provided value doesn't match proof
if (keccak256(proof.value) != keccak256(value)) {
return VerifyExistenceError.ValueNotMatching;
}
CheckAgainstSpecError cCode = checkAgainstSpec(proof, spec);
if (cCode != CheckAgainstSpecError.None) {
return VerifyExistenceError.CheckSpec;
}
return VerifyExistenceError.None;
}
// ExistenceProof
function verify(
UnionIcs23.ExistenceProof calldata proof,
UnionIcs23.ProofSpec memory spec,
bytes32 commitmentRoot,
bytes memory key,
bytes memory value
) internal pure returns (VerifyExistenceError) {
//require(BytesLib.equal(proof.key, key)); // dev: Provided key doesn't match proof
if (keccak256(proof.key) != keccak256(key)) {
return VerifyExistenceError.KeyNotMatching;
}
//require(BytesLib.equal(proof.value, value)); // dev: Provided value doesn't match proof
if (keccak256(proof.value) != keccak256(value)) {
return VerifyExistenceError.ValueNotMatching;
}
CheckAgainstSpecError cCode = checkAgainstSpec(proof, spec);
if (cCode != CheckAgainstSpecError.None) {
return VerifyExistenceError.CheckSpec;
}
(bytes32 root, CalculateRootError rCode) = calculateRoot(proof);
if (rCode != CalculateRootError.None) {
return VerifyExistenceError.CalculateRoot;
}
//require(BytesLib.equal(root, commitmentRoot)); // dev: Calculated root doesn't match provided root
if (root != commitmentRoot) {
return VerifyExistenceError.RootNotMatching;
}
return VerifyExistenceError.None;
}
enum CalculateRootError {
None,
LeafNil,
LeafOp,
PathOp,
EmptyProof
}
function calculateRoot(
UnionIcs23.ExistenceProof calldata proof
) internal pure returns (bytes32, CalculateRootError) {
//require(LeafOp.isNil(proof.leaf) == false); // dev: Existence Proof needs defined LeafOp
if (proof.leafPrefix.length == 0) {
return ("", CalculateRootError.LeafNil);
}
(bytes32 root, Ops.ApplyLeafOpError lCode) =
Ops.applyLeafOp(proof.leafPrefix, proof.key, proof.value);
if (lCode != Ops.ApplyLeafOpError.None) {
return ("", CalculateRootError.LeafOp);
}
uint256 proofPathLength = proof.path.length;
for (uint256 i; i < proofPathLength; i++) {
Ops.ApplyInnerOpError iCode;
(root, iCode) = Ops.applyOp(proof.path[i], root);
if (iCode != Ops.ApplyInnerOpError.None) {
return ("", CalculateRootError.PathOp);
}
}
return (root, CalculateRootError.None);
}
enum CheckAgainstSpecError {
None,
EmptyLeaf,
OpsCheckAgainstSpec,
InnerOpsDepthTooShort,
InnerOpsDepthTooLong
}
function checkAgainstSpec(
UnionIcs23.ExistenceProof calldata proof,
UnionIcs23.ProofSpec memory spec
) internal pure returns (CheckAgainstSpecError) {
// LeafOp.isNil does not work
//require(LeafOp._empty(proof.leaf) == false); // dev: Existence Proof needs defined LeafOp
// TODO(aeryz): check if there is isempty function in solidity
if (proof.leafPrefix.length == 0) {
return CheckAgainstSpecError.EmptyLeaf;
}
// LeafOp's checkAgainstSpec is inlined here since we only need to check the prefix here
//require(hasprefix); // dev: checkAgainstSpec for LeafOp - Leaf Prefix doesn't start with
// Both specs have the prefix 0x00
if (proof.leafPrefix[0] != 0) {
return CheckAgainstSpecError.OpsCheckAgainstSpec;
}
// we don't do any checks regarding min_depth, max_depth since they both are 0 in both specs
uint256 max = spec.maxPrefixLength + spec.childSize;
uint256 proofPathLength = proof.path.length;
for (uint256 i; i < proofPathLength; i++) {
UnionIcs23.InnerOp calldata innerOp = proof.path[i];
// innerOp.prefix is hardcoded to be 0 in both specs
if (
innerOp.prefix.length < spec.minPrefixLength
|| innerOp.prefix[0] == 0 || innerOp.prefix.length > max
) {
return CheckAgainstSpecError.OpsCheckAgainstSpec;
}
}
return CheckAgainstSpecError.None;
}
enum VerifyNonExistenceError {
None,
VerifyLeft,
VerifyRight,
LeftAndRightKeyEmpty,
RightKeyRange,
LeftKeyRange,
RightProofLeftMost,
LeftProofRightMost,
IsLeftNeighbor
}
// CosmosIcs23V1NonExistenceProof
function verify(
UnionIcs23.NonExistenceProof calldata proof,
UnionIcs23.ProofSpec memory spec,
bytes32 commitmentRoot,
bytes memory key
) internal pure returns (VerifyNonExistenceError) {
bytes calldata leftKey = proof.left.key;
bytes calldata rightKey = proof.right.key;
// CosmosIcs23V1ExistenceProof.isNil does not work
if (!UnionIcs23.empty(proof.left)) {
VerifyExistenceError eCode = verify(
proof.left,
spec,
commitmentRoot,
proof.left.key,
proof.left.value
);
if (eCode != VerifyExistenceError.None) {
return VerifyNonExistenceError.VerifyLeft;
}
}
if (!UnionIcs23.empty(proof.right)) {
VerifyExistenceError eCode = verify(
proof.right,
spec,
commitmentRoot,
proof.right.key,
proof.right.value
);
if (eCode != VerifyExistenceError.None) {
return VerifyNonExistenceError.VerifyRight;
}
}
// If both proofs are missing, this is not a valid proof
//require(leftKey.length > 0 || rightKey.length > 0); // dev: both left and right proofs missing
if (leftKey.length == 0 && rightKey.length == 0) {
return VerifyNonExistenceError.LeftAndRightKeyEmpty;
}
// Ensure in valid range
if (rightKey.length > 0 && Ops.compare(key, rightKey) >= 0) {
//require(Ops.compare(key, rightKey) < 0); // dev: key is not left of right proof
return VerifyNonExistenceError.RightKeyRange;
}
if (leftKey.length > 0 && Ops.compare(key, leftKey) <= 0) {
//require(Ops.compare(key, leftKey) > 0); // dev: key is not right of left proof
return VerifyNonExistenceError.LeftKeyRange;
}
if (leftKey.length == 0) {
//require(isLeftMost(spec, proof.right.path, proof.right.path.length)); // dev: left proof missing, right proof must be left-most
if (!isLeftMost(spec, proof.right.path, proof.right.path.length)) {
return VerifyNonExistenceError.RightProofLeftMost;
}
} else if (rightKey.length == 0) {
//require(isRightMost(spec, proof.left.path, proof.left.path.length)); // dev: isRightMost: right proof missing, left proof must be right-most
if (!isRightMost(spec, proof.left.path, proof.left.path.length)) {
return VerifyNonExistenceError.LeftProofRightMost;
}
} else {
//require(isLeftNeighbor(spec, proof.left.path, proof.right.path)); // dev: isLeftNeighbor: right proof missing, left proof must be right-most
bool isLeftNeigh =
isLeftNeighbor(spec, proof.left.path, proof.right.path);
if (!isLeftNeigh) {
return VerifyNonExistenceError.IsLeftNeighbor;
}
}
return VerifyNonExistenceError.None;
}
function calculateRoot(
UnionIcs23.NonExistenceProof calldata proof
) internal pure returns (bytes32, CalculateRootError) {
if (!UnionIcs23.empty(proof.left)) {
return calculateRoot(proof.left);
}
if (!UnionIcs23.empty(proof.right)) {
return calculateRoot(proof.right);
}
//revert(); // dev: Nonexistence proof has empty Left and Right proof
return ("", CalculateRootError.EmptyProof);
}
// private
// length must be <= path.length
function isLeftMost(
UnionIcs23.ProofSpec memory spec,
UnionIcs23.InnerOp[] calldata path,
uint256 length
) private pure returns (bool) {
(uint256 minPrefix, uint256 maxPrefix, uint256 suffix) =
getPadding(spec, 0);
for (uint256 i; i < length; i++) {
if (!hasPadding(path[i], minPrefix, maxPrefix, suffix)) {
return false;
}
}
return true;
}
// length must be <= path.length
function isRightMost(
UnionIcs23.ProofSpec memory spec,
UnionIcs23.InnerOp[] calldata path,
uint256 length
) private pure returns (bool) {
(uint256 minPrefix, uint256 maxPrefix, uint256 suffix) =
getPadding(spec, 1);
for (uint256 i; i < length; i++) {
if (!hasPadding(path[i], minPrefix, maxPrefix, suffix)) {
return false;
}
}
return true;
}
function isLeftStep(
UnionIcs23.ProofSpec memory spec,
UnionIcs23.InnerOp calldata left,
UnionIcs23.InnerOp calldata right
) private pure returns (bool) {
(uint256 leftIdx, OrderFromPaddingError lCode) =
orderFromPadding(spec, left);
if (lCode != OrderFromPaddingError.None) return false;
(uint256 rightIdx, OrderFromPaddingError rCode) =
orderFromPadding(spec, right);
if (lCode != OrderFromPaddingError.None) return false;
if (rCode != OrderFromPaddingError.None) return false;
return rightIdx == leftIdx + 1;
}
function isLeftNeighbor(
UnionIcs23.ProofSpec memory spec,
UnionIcs23.InnerOp[] calldata left,
UnionIcs23.InnerOp[] calldata right
) private pure returns (bool) {
uint256 leftIdx = left.length - 1;
uint256 rightIdx = right.length - 1;
while (leftIdx >= 0 && rightIdx >= 0) {
if (
keccak256(left[leftIdx].prefix)
== keccak256(right[rightIdx].prefix)
&& keccak256(left[leftIdx].suffix)
== keccak256(right[rightIdx].suffix)
) {
leftIdx -= 1;
rightIdx -= 1;
continue;
}
break;
}
if (!isLeftStep(spec, left[leftIdx], right[rightIdx])) {
return false;
}
// slicing does not work for ``memory`` types
if (!isRightMost(spec, left, leftIdx)) {
return false;
}
if (!isLeftMost(spec, right, rightIdx)) {
return false;
}
return true;
}
enum OrderFromPaddingError {
None,
NotFound
}
function orderFromPadding(
UnionIcs23.ProofSpec memory spec,
UnionIcs23.InnerOp calldata op
) private pure returns (uint256, OrderFromPaddingError) {
for (uint256 branch; branch < 2; branch++) {
(uint256 minp, uint256 maxp, uint256 suffix) =
getPadding(spec, branch);
if (hasPadding(op, minp, maxp, suffix) == true) {
return (branch, OrderFromPaddingError.None);
}
}
//revert(); // dev: Cannot find any valid spacing for this node
return (0, OrderFromPaddingError.NotFound);
}
function getPadding(
UnionIcs23.ProofSpec memory spec,
uint256 branch
)
private
pure
returns (uint256 minPrefix, uint256 maxPrefix, uint256 suffix)
{
uint256 prefix = branch * spec.childSize;
minPrefix = prefix + spec.minPrefixLength;
maxPrefix = prefix + spec.maxPrefixLength;
suffix = (1 - branch) * spec.childSize;
return (minPrefix, maxPrefix, suffix);
}
function hasPadding(
UnionIcs23.InnerOp calldata op,
uint256 minPrefix,
uint256 maxPrefix,
uint256 suffix
) private pure returns (bool) {
if (op.prefix.length < minPrefix || op.prefix.length > maxPrefix) {
return false;
}
return op.suffix.length == suffix;
}
}pragma solidity ^0.8.27;
/// @title Groth16 verifier template.
/// @author Remco Bloemen
/// @notice Supports verifying Groth16 proofs. Proofs can be in uncompressed
/// (256 bytes) and compressed (128 bytes) format.
library CometblsZKVerifier {
// Addresses of precompiles
uint256 constant PRECOMPILE_MODEXP = 0x05;
uint256 constant PRECOMPILE_ADD = 0x06;
uint256 constant PRECOMPILE_MUL = 0x07;
uint256 constant PRECOMPILE_VERIFY = 0x08;
// Base field Fp order P and scalar field Fr order R.
// For BN254 these are computed as follows:
// t = 4965661367192848881
// P = 36⋅t⁴ + 36⋅t³ + 24⋅t² + 6⋅t + 1
// R = 36⋅t⁴ + 36⋅t³ + 18⋅t² + 6⋅t + 1
uint256 constant P =
0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47;
uint256 constant R =
0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001;
// Extension field Fp2 = Fp[i] / (i² + 1)
// Note: This is the complex extension field of Fp with i² = -1.
// Values in Fp2 are represented as a pair of Fp elements (a₀, a₁) as a₀ + a₁⋅i.
// Note: The order of Fp2 elements is *opposite* that of the pairing contract, which
// expects Fp2 elements in order (a₁, a₀). This is also the order in which
// Fp2 elements are encoded in the public interface as this became convention.
// Constants in Fp
uint256 constant FRACTION_1_2_FP =
0x183227397098d014dc2822db40c0ac2ecbc0b548b438e5469e10460b6c3e7ea4;
uint256 constant FRACTION_27_82_FP =
0x2b149d40ceb8aaae81be18991be06ac3b5b4c5e559dbefa33267e6dc24a138e5;
uint256 constant FRACTION_3_82_FP =
0x2fcd3ac2a640a154eb23960892a85a68f031ca0c8344b23a577dcf1052b9e775;
// Exponents for inversions and square roots mod P
uint256 constant EXP_INVERSE_FP =
0x30644E72E131A029B85045B68181585D97816A916871CA8D3C208C16D87CFD45; // P - 2
uint256 constant EXP_SQRT_FP =
0xC19139CB84C680A6E14116DA060561765E05AA45A1C72A34F082305B61F3F52; // (P + 1) / 4;
// Verifying key
uint256 constant ALPHA_X =
0x245229d9b076b3c0e8a4d70bde8c1cccffa08a9fae7557b165b3b0dbd653e2c7;
uint256 constant ALPHA_Y =
0x253ec85988dbb84e46e94b5efa3373b47a000b4ac6c86b2d4b798d274a182302;
uint256 constant BETA_NEG_X_0 =
0x2424bcc1f60a5472685fd50705b2809626e170120acaf441e133a2bd5e61d244;
uint256 constant BETA_NEG_X_1 =
0x07090a82e8fabbd39299be24705b92cf208ee8b3487f6f2b39ff27978a29a1db;
uint256 constant BETA_NEG_Y_0 =
0x04ddc8d30d5c438ca34091c5d2c6ded571382cba2b3c4fdc4222df2938b4e51e;
uint256 constant BETA_NEG_Y_1 =
0x25833b15e156ae01f2741f4f4120ddb466c52eb83a959f79eb99b23caa7fbf1d;
uint256 constant GAMMA_NEG_X_0 =
0x1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed;
uint256 constant GAMMA_NEG_X_1 =
0x198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c2;
uint256 constant GAMMA_NEG_Y_0 =
0x1d9befcd05a5323e6da4d435f3b617cdb3af83285c2df711ef39c01571827f9d;
uint256 constant GAMMA_NEG_Y_1 =
0x275dc4a288d1afb3cbb1ac09187524c7db36395df7be3b99e673b13a075a65ec;
uint256 constant DELTA_NEG_X_0 =
0x02aca5d2a73f8d34e4b26eee3932365e6526c8d5e2f3347d679c2cb1867104dc;
uint256 constant DELTA_NEG_X_1 =
0x07b8dbefa90bde075a26318e5066db729155514e3c06b888d4e03c56d82c97e6;
uint256 constant DELTA_NEG_Y_0 =
0x1696ccafaefe49a5d8bad8e79630e19b25e5392a203aff0042d0216f254806f5;
uint256 constant DELTA_NEG_Y_1 =
0x2edb19cbb2b6ad0c98fdd7d1845500c26e497dc35e4cdc1cb02cc65dc4ba1bf2;
uint256 constant CONSTANT_X =
0x2f5d8a3817f21d3e453573c90c3cc47b7ff235fad7bdfbd59bbd6ae5d153273e;
uint256 constant CONSTANT_Y =
0x147fa22142b1fd86ce75fc87230a0feac8765d02938784dcfc828d17d7e7c432;
uint256 constant PUB_0_X =
0x2a81b98e1c997bd01a20893a08a46c6804493e838c1a0ff6c8c069ef5ab66b9a;
uint256 constant PUB_0_Y =
0x276938ada8075cec20d4d6a1f157ec94cc7ba6207c98576e98c1ad9d6378fb6f;
uint256 constant PUB_1_X =
0x179496ce140df89ce35c5ee7fb496efdffda5e5d3b95ff9116e2e5df96b36ab7;
uint256 constant PUB_1_Y =
0x0326e7d44688ce5903676b7d646e46a5938c8e5fd8cd54e4d5aa3300649f3cfc;
uint256 constant PEDERSEN_G_X_0 =
0x1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed;
uint256 constant PEDERSEN_G_X_1 =
0x198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c2;
uint256 constant PEDERSEN_G_Y_0 =
0x12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa;
uint256 constant PEDERSEN_G_Y_1 =
0x090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b;
uint256 constant PEDERSEN_G_ROOT_SIGMA_NEG_X_0 =
0x02aca5d2a73f8d34e4b26eee3932365e6526c8d5e2f3347d679c2cb1867104dc;
uint256 constant PEDERSEN_G_ROOT_SIGMA_NEG_X_1 =
0x07b8dbefa90bde075a26318e5066db729155514e3c06b888d4e03c56d82c97e6;
uint256 constant PEDERSEN_G_ROOT_SIGMA_NEG_Y_0 =
0x1696ccafaefe49a5d8bad8e79630e19b25e5392a203aff0042d0216f254806f5;
uint256 constant PEDERSEN_G_ROOT_SIGMA_NEG_Y_1 =
0x2edb19cbb2b6ad0c98fdd7d1845500c26e497dc35e4cdc1cb02cc65dc4ba1bf2;
/// Compute the public input linear combination.
/// @notice Reverts with PublicInputNotInField if the input is not in the field.
/// @notice Computes the multi-scalar-multiplication of the public input
/// elements and the verification key including the constant term.
/// @param input The public inputs. These are elements of the scalar field Fr.
/// @return success the result of the msm.
/// @return x The X coordinate of the resulting G1 point.
/// @return y The Y coordinate of the resulting G1 point.
function publicInputMSM(
uint256[2] calldata proofCommitment,
uint256[2] memory input
) internal view returns (bool success, uint256 x, uint256 y) {
// Note: The ECMUL precompile does not reject unreduced values, so we check this.
// Note: Unrolling this loop does not cost much extra in code-size, the bulk of the
// code-size is in the PUB_ constants.
// ECMUL has input (x, y, scalar) and output (x', y').
// ECADD has input (x1, y1, x2, y2) and output (x', y').
// We call them such that ecmul output is already in the second point
// argument to ECADD so we can have a tight loop.
success = true;
assembly ("memory-safe") {
let f := mload(0x40)
let g := add(f, 0x40)
let s
mstore(f, CONSTANT_X)
mstore(add(f, 0x20), CONSTANT_Y)
// Add the proof commitment
calldatacopy(g, proofCommitment, 0x40)
success :=
and(success, staticcall(gas(), PRECOMPILE_ADD, f, 0x80, f, 0x40))
mstore(g, PUB_0_X)
mstore(add(g, 0x20), PUB_0_Y)
s := mload(input)
mstore(add(g, 0x40), s)
success := and(success, lt(s, R))
success :=
and(success, staticcall(gas(), PRECOMPILE_MUL, g, 0x60, g, 0x40))
success :=
and(success, staticcall(gas(), PRECOMPILE_ADD, f, 0x80, f, 0x40))
mstore(g, PUB_1_X)
mstore(add(g, 0x20), PUB_1_Y)
s := mload(add(input, 32))
mstore(add(g, 0x40), s)
success := and(success, lt(s, R))
success :=
and(success, staticcall(gas(), PRECOMPILE_MUL, g, 0x60, g, 0x40))
success :=
and(success, staticcall(gas(), PRECOMPILE_ADD, f, 0x80, f, 0x40))
x := mload(f)
y := mload(add(f, 0x20))
}
}
function verifyProofCommitmentPOK(
uint256[2] calldata proofCommitment,
uint256[2] calldata proofCommitmentPOK
) internal view returns (bool) {
bool success = true;
assembly ("memory-safe") {
let f := mload(0x40)
calldatacopy(f, proofCommitment, 0x40)
mstore(add(f, 0x40), PEDERSEN_G_X_1)
mstore(add(f, 0x60), PEDERSEN_G_X_0)
mstore(add(f, 0x80), PEDERSEN_G_Y_1)
mstore(add(f, 0xA0), PEDERSEN_G_Y_0)
calldatacopy(add(f, 0xC0), proofCommitmentPOK, 0x40)
mstore(add(f, 0x100), PEDERSEN_G_ROOT_SIGMA_NEG_X_1)
mstore(add(f, 0x120), PEDERSEN_G_ROOT_SIGMA_NEG_X_0)
mstore(add(f, 0x140), PEDERSEN_G_ROOT_SIGMA_NEG_Y_1)
mstore(add(f, 0x160), PEDERSEN_G_ROOT_SIGMA_NEG_Y_0)
success := staticcall(gas(), PRECOMPILE_VERIFY, f, 0x180, f, 0x20)
success := and(success, mload(f))
}
return success;
}
/// Verify an uncompressed Groth16 proof.
/// @notice Reverts with InvalidProof if the proof is invalid or
/// with PublicInputNotInField the public input is not reduced.
/// @notice There is no return value. If the function does not revert, the
/// proof was successfully verified.
/// @param proof the points (A, B, C) in EIP-197 format matching the output
/// of compressProof.
/// @param input the public input field elements in the scalar field Fr.
/// Elements must be reduced.
function verifyProof(
uint256[8] calldata proof,
uint256[2] calldata proofCommitment,
uint256[2] calldata proofCommitmentPOK,
uint256[2] memory input
) internal view returns (bool) {
(bool success, uint256 x, uint256 y) =
publicInputMSM(proofCommitment, input);
if (!success) {
return false;
}
if (!verifyProofCommitmentPOK(proofCommitment, proofCommitmentPOK)) {
return false;
}
// Note: The precompile expects the F2 coefficients in big-endian order.
// Note: The pairing precompile rejects unreduced values, so we won't check that here.
assembly ("memory-safe") {
let f := mload(0x40) // Free memory pointer.
// Copy points (A, B, C) to memory. They are already in correct encoding.
// This is pairing e(A, B) and G1 of e(C, -δ).
calldatacopy(f, proof, 0x100)
// Complete e(C, -δ) and write e(α, -β), e(L_pub, -γ) to memory.
// OPT: This could be better done using a single codecopy, but
// Solidity (unlike standalone Yul) doesn't provide a way to
// to do this.
mstore(add(f, 0x100), DELTA_NEG_X_1)
mstore(add(f, 0x120), DELTA_NEG_X_0)
mstore(add(f, 0x140), DELTA_NEG_Y_1)
mstore(add(f, 0x160), DELTA_NEG_Y_0)
mstore(add(f, 0x180), ALPHA_X)
mstore(add(f, 0x1a0), ALPHA_Y)
mstore(add(f, 0x1c0), BETA_NEG_X_1)
mstore(add(f, 0x1e0), BETA_NEG_X_0)
mstore(add(f, 0x200), BETA_NEG_Y_1)
mstore(add(f, 0x220), BETA_NEG_Y_0)
mstore(add(f, 0x240), x)
mstore(add(f, 0x260), y)
mstore(add(f, 0x280), GAMMA_NEG_X_1)
mstore(add(f, 0x2a0), GAMMA_NEG_X_0)
mstore(add(f, 0x2c0), GAMMA_NEG_Y_1)
mstore(add(f, 0x2e0), GAMMA_NEG_Y_0)
// Check pairing equation.
success := staticcall(gas(), PRECOMPILE_VERIFY, f, 0x300, f, 0x20)
// Also check returned value (both are either 1 or 0).
success := and(success, mload(f))
}
return success;
}
}pragma solidity ^0.8.27;
import "../lib/ICS23.sol";
import "../lib/UnionICS23.sol";
library ICS23Verifier {
function verifyMembership(
bytes32 root,
bytes calldata proof,
bytes memory prefix,
bytes memory path,
bytes calldata value
) internal pure returns (bool) {
UnionIcs23.ExistenceProof[2] calldata existenceProof;
assembly {
existenceProof := proof.offset
}
return Ics23.verifyChainedMembership(
existenceProof, root, prefix, path, value
) == Ics23.VerifyChainedMembershipError.None;
}
struct NonMembershipProof {
UnionIcs23.NonExistenceProof nonexist;
UnionIcs23.ExistenceProof exist;
}
function verifyNonMembership(
bytes32 root,
bytes calldata proof,
bytes memory prefix,
bytes memory path
) internal pure returns (bool) {
NonMembershipProof calldata nonexistenceProof;
assembly {
nonexistenceProof := proof.offset
}
return Ics23.verifyChainedNonMembership(
nonexistenceProof.nonexist,
nonexistenceProof.exist,
root,
prefix,
path
) == Ics23.VerifyChainedNonMembershipError.None;
}
}pragma solidity ^0.8.27;
library VersionedLib {
function gitRev() internal pure returns (string memory) {
return "7113f2661025803021f819add09995fce2f58abf";
}
}
abstract contract Versioned {
function gitRev() public pure returns (string memory) {
return VersionedLib.gitRev();
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (interfaces/draft-IERC1822.sol)
pragma solidity ^0.8.20;
/**
* @dev ERC-1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified
* proxy whose upgrades are fully controlled by the current implementation.
*/
interface IERC1822Proxiable {
/**
* @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation
* address.
*
* IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks
* bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this
* function revert if invoked through a proxy.
*/
function proxiableUUID() external view returns (bytes32);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.2.0) (proxy/ERC1967/ERC1967Utils.sol)
pragma solidity ^0.8.22;
import {IBeacon} from "../beacon/IBeacon.sol";
import {IERC1967} from "../../interfaces/IERC1967.sol";
import {Address} from "../../utils/Address.sol";
import {StorageSlot} from "../../utils/StorageSlot.sol";
/**
* @dev This library provides getters and event emitting update functions for
* https://eips.ethereum.org/EIPS/eip-1967[ERC-1967] slots.
*/
library ERC1967Utils {
/**
* @dev Storage slot with the address of the current implementation.
* This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1.
*/
// solhint-disable-next-line private-vars-leading-underscore
bytes32 internal constant IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
/**
* @dev The `implementation` of the proxy is invalid.
*/
error ERC1967InvalidImplementation(address implementation);
/**
* @dev The `admin` of the proxy is invalid.
*/
error ERC1967InvalidAdmin(address admin);
/**
* @dev The `beacon` of the proxy is invalid.
*/
error ERC1967InvalidBeacon(address beacon);
/**
* @dev An upgrade function sees `msg.value > 0` that may be lost.
*/
error ERC1967NonPayable();
/**
* @dev Returns the current implementation address.
*/
function getImplementation() internal view returns (address) {
return StorageSlot.getAddressSlot(IMPLEMENTATION_SLOT).value;
}
/**
* @dev Stores a new address in the ERC-1967 implementation slot.
*/
function _setImplementation(address newImplementation) private {
if (newImplementation.code.length == 0) {
revert ERC1967InvalidImplementation(newImplementation);
}
StorageSlot.getAddressSlot(IMPLEMENTATION_SLOT).value = newImplementation;
}
/**
* @dev Performs implementation upgrade with additional setup call if data is nonempty.
* This function is payable only if the setup call is performed, otherwise `msg.value` is rejected
* to avoid stuck value in the contract.
*
* Emits an {IERC1967-Upgraded} event.
*/
function upgradeToAndCall(address newImplementation, bytes memory data) internal {
_setImplementation(newImplementation);
emit IERC1967.Upgraded(newImplementation);
if (data.length > 0) {
Address.functionDelegateCall(newImplementation, data);
} else {
_checkNonPayable();
}
}
/**
* @dev Storage slot with the admin of the contract.
* This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1.
*/
// solhint-disable-next-line private-vars-leading-underscore
bytes32 internal constant ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;
/**
* @dev Returns the current admin.
*
* TIP: To get this value clients can read directly from the storage slot shown below (specified by ERC-1967) using
* the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.
* `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`
*/
function getAdmin() internal view returns (address) {
return StorageSlot.getAddressSlot(ADMIN_SLOT).value;
}
/**
* @dev Stores a new address in the ERC-1967 admin slot.
*/
function _setAdmin(address newAdmin) private {
if (newAdmin == address(0)) {
revert ERC1967InvalidAdmin(address(0));
}
StorageSlot.getAddressSlot(ADMIN_SLOT).value = newAdmin;
}
/**
* @dev Changes the admin of the proxy.
*
* Emits an {IERC1967-AdminChanged} event.
*/
function changeAdmin(address newAdmin) internal {
emit IERC1967.AdminChanged(getAdmin(), newAdmin);
_setAdmin(newAdmin);
}
/**
* @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.
* This is the keccak-256 hash of "eip1967.proxy.beacon" subtracted by 1.
*/
// solhint-disable-next-line private-vars-leading-underscore
bytes32 internal constant BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;
/**
* @dev Returns the current beacon.
*/
function getBeacon() internal view returns (address) {
return StorageSlot.getAddressSlot(BEACON_SLOT).value;
}
/**
* @dev Stores a new beacon in the ERC-1967 beacon slot.
*/
function _setBeacon(address newBeacon) private {
if (newBeacon.code.length == 0) {
revert ERC1967InvalidBeacon(newBeacon);
}
StorageSlot.getAddressSlot(BEACON_SLOT).value = newBeacon;
address beaconImplementation = IBeacon(newBeacon).implementation();
if (beaconImplementation.code.length == 0) {
revert ERC1967InvalidImplementation(beaconImplementation);
}
}
/**
* @dev Change the beacon and trigger a setup call if data is nonempty.
* This function is payable only if the setup call is performed, otherwise `msg.value` is rejected
* to avoid stuck value in the contract.
*
* Emits an {IERC1967-BeaconUpgraded} event.
*
* CAUTION: Invoking this function has no effect on an instance of {BeaconProxy} since v5, since
* it uses an immutable beacon without looking at the value of the ERC-1967 beacon slot for
* efficiency.
*/
function upgradeBeaconToAndCall(address newBeacon, bytes memory data) internal {
_setBeacon(newBeacon);
emit IERC1967.BeaconUpgraded(newBeacon);
if (data.length > 0) {
Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data);
} else {
_checkNonPayable();
}
}
/**
* @dev Reverts if `msg.value` is not zero. It can be used to avoid `msg.value` stuck in the contract
* if an upgrade doesn't perform an initialization call.
*/
function _checkNonPayable() private {
if (msg.value > 0) {
revert ERC1967NonPayable();
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/manager/IAuthority.sol)
pragma solidity ^0.8.20;
/**
* @dev Standard interface for permissioning originally defined in Dappsys.
*/
interface IAuthority {
/**
* @dev Returns true if the caller can invoke on a target the function identified by a function selector.
*/
function canCall(address caller, address target, bytes4 selector) external view returns (bool allowed);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.3.0-rc.0) (access/manager/AuthorityUtils.sol)
pragma solidity ^0.8.20;
import {IAuthority} from "./IAuthority.sol";
library AuthorityUtils {
/**
* @dev Since `AccessManager` implements an extended IAuthority interface, invoking `canCall` with backwards compatibility
* for the preexisting `IAuthority` interface requires special care to avoid reverting on insufficient return data.
* This helper function takes care of invoking `canCall` in a backwards compatible way without reverting.
*/
function canCallWithDelay(
address authority,
address caller,
address target,
bytes4 selector
) internal view returns (bool immediate, uint32 delay) {
bytes memory data = abi.encodeCall(IAuthority.canCall, (caller, target, selector));
assembly ("memory-safe") {
mstore(0x00, 0x00)
mstore(0x20, 0x00)
if staticcall(gas(), authority, add(data, 0x20), mload(data), 0x00, 0x40) {
immediate := mload(0x00)
delay := mload(0x20)
// If delay does not fit in a uint32, return 0 (no delay)
// equivalent to: if gt(delay, 0xFFFFFFFF) { delay := 0 }
delay := mul(delay, iszero(shr(32, delay)))
}
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (access/manager/IAccessManager.sol)
pragma solidity ^0.8.20;
import {Time} from "../../utils/types/Time.sol";
interface IAccessManager {
/**
* @dev A delayed operation was scheduled.
*/
event OperationScheduled(
bytes32 indexed operationId,
uint32 indexed nonce,
uint48 schedule,
address caller,
address target,
bytes data
);
/**
* @dev A scheduled operation was executed.
*/
event OperationExecuted(bytes32 indexed operationId, uint32 indexed nonce);
/**
* @dev A scheduled operation was canceled.
*/
event OperationCanceled(bytes32 indexed operationId, uint32 indexed nonce);
/**
* @dev Informational labelling for a roleId.
*/
event RoleLabel(uint64 indexed roleId, string label);
/**
* @dev Emitted when `account` is granted `roleId`.
*
* NOTE: The meaning of the `since` argument depends on the `newMember` argument.
* If the role is granted to a new member, the `since` argument indicates when the account becomes a member of the role,
* otherwise it indicates the execution delay for this account and roleId is updated.
*/
event RoleGranted(uint64 indexed roleId, address indexed account, uint32 delay, uint48 since, bool newMember);
/**
* @dev Emitted when `account` membership or `roleId` is revoked. Unlike granting, revoking is instantaneous.
*/
event RoleRevoked(uint64 indexed roleId, address indexed account);
/**
* @dev Role acting as admin over a given `roleId` is updated.
*/
event RoleAdminChanged(uint64 indexed roleId, uint64 indexed admin);
/**
* @dev Role acting as guardian over a given `roleId` is updated.
*/
event RoleGuardianChanged(uint64 indexed roleId, uint64 indexed guardian);
/**
* @dev Grant delay for a given `roleId` will be updated to `delay` when `since` is reached.
*/
event RoleGrantDelayChanged(uint64 indexed roleId, uint32 delay, uint48 since);
/**
* @dev Target mode is updated (true = closed, false = open).
*/
event TargetClosed(address indexed target, bool closed);
/**
* @dev Role required to invoke `selector` on `target` is updated to `roleId`.
*/
event TargetFunctionRoleUpdated(address indexed target, bytes4 selector, uint64 indexed roleId);
/**
* @dev Admin delay for a given `target` will be updated to `delay` when `since` is reached.
*/
event TargetAdminDelayUpdated(address indexed target, uint32 delay, uint48 since);
error AccessManagerAlreadyScheduled(bytes32 operationId);
error AccessManagerNotScheduled(bytes32 operationId);
error AccessManagerNotReady(bytes32 operationId);
error AccessManagerExpired(bytes32 operationId);
error AccessManagerLockedRole(uint64 roleId);
error AccessManagerBadConfirmation();
error AccessManagerUnauthorizedAccount(address msgsender, uint64 roleId);
error AccessManagerUnauthorizedCall(address caller, address target, bytes4 selector);
error AccessManagerUnauthorizedConsume(address target);
error AccessManagerUnauthorizedCancel(address msgsender, address caller, address target, bytes4 selector);
error AccessManagerInvalidInitialAdmin(address initialAdmin);
/**
* @dev Check if an address (`caller`) is authorised to call a given function on a given contract directly (with
* no restriction). Additionally, it returns the delay needed to perform the call indirectly through the {schedule}
* & {execute} workflow.
*
* This function is usually called by the targeted contract to control immediate execution of restricted functions.
* Therefore we only return true if the call can be performed without any delay. If the call is subject to a
* previously set delay (not zero), then the function should return false and the caller should schedule the operation
* for future execution.
*
* If `immediate` is true, the delay can be disregarded and the operation can be immediately executed, otherwise
* the operation can be executed if and only if delay is greater than 0.
*
* NOTE: The IAuthority interface does not include the `uint32` delay. This is an extension of that interface that
* is backward compatible. Some contracts may thus ignore the second return argument. In that case they will fail
* to identify the indirect workflow, and will consider calls that require a delay to be forbidden.
*
* NOTE: This function does not report the permissions of the admin functions in the manager itself. These are defined by the
* {AccessManager} documentation.
*/
function canCall(
address caller,
address target,
bytes4 selector
) external view returns (bool allowed, uint32 delay);
/**
* @dev Expiration delay for scheduled proposals. Defaults to 1 week.
*
* IMPORTANT: Avoid overriding the expiration with 0. Otherwise every contract proposal will be expired immediately,
* disabling any scheduling usage.
*/
function expiration() external view returns (uint32);
/**
* @dev Minimum setback for all delay updates, with the exception of execution delays. It
* can be increased without setback (and reset via {revokeRole} in the case event of an
* accidental increase). Defaults to 5 days.
*/
function minSetback() external view returns (uint32);
/**
* @dev Get whether the contract is closed disabling any access. Otherwise role permissions are applied.
*
* NOTE: When the manager itself is closed, admin functions are still accessible to avoid locking the contract.
*/
function isTargetClosed(address target) external view returns (bool);
/**
* @dev Get the role required to call a function.
*/
function getTargetFunctionRole(address target, bytes4 selector) external view returns (uint64);
/**
* @dev Get the admin delay for a target contract. Changes to contract configuration are subject to this delay.
*/
function getTargetAdminDelay(address target) external view returns (uint32);
/**
* @dev Get the id of the role that acts as an admin for the given role.
*
* The admin permission is required to grant the role, revoke the role and update the execution delay to execute
* an operation that is restricted to this role.
*/
function getRoleAdmin(uint64 roleId) external view returns (uint64);
/**
* @dev Get the role that acts as a guardian for a given role.
*
* The guardian permission allows canceling operations that have been scheduled under the role.
*/
function getRoleGuardian(uint64 roleId) external view returns (uint64);
/**
* @dev Get the role current grant delay.
*
* Its value may change at any point without an event emitted following a call to {setGrantDelay}.
* Changes to this value, including effect timepoint are notified in advance by the {RoleGrantDelayChanged} event.
*/
function getRoleGrantDelay(uint64 roleId) external view returns (uint32);
/**
* @dev Get the access details for a given account for a given role. These details include the timepoint at which
* membership becomes active, and the delay applied to all operation by this user that requires this permission
* level.
*
* Returns:
* [0] Timestamp at which the account membership becomes valid. 0 means role is not granted.
* [1] Current execution delay for the account.
* [2] Pending execution delay for the account.
* [3] Timestamp at which the pending execution delay will become active. 0 means no delay update is scheduled.
*/
function getAccess(
uint64 roleId,
address account
) external view returns (uint48 since, uint32 currentDelay, uint32 pendingDelay, uint48 effect);
/**
* @dev Check if a given account currently has the permission level corresponding to a given role. Note that this
* permission might be associated with an execution delay. {getAccess} can provide more details.
*/
function hasRole(uint64 roleId, address account) external view returns (bool isMember, uint32 executionDelay);
/**
* @dev Give a label to a role, for improved role discoverability by UIs.
*
* Requirements:
*
* - the caller must be a global admin
*
* Emits a {RoleLabel} event.
*/
function labelRole(uint64 roleId, string calldata label) external;
/**
* @dev Add `account` to `roleId`, or change its execution delay.
*
* This gives the account the authorization to call any function that is restricted to this role. An optional
* execution delay (in seconds) can be set. If that delay is non 0, the user is required to schedule any operation
* that is restricted to members of this role. The user will only be able to execute the operation after the delay has
* passed, before it has expired. During this period, admin and guardians can cancel the operation (see {cancel}).
*
* If the account has already been granted this role, the execution delay will be updated. This update is not
* immediate and follows the delay rules. For example, if a user currently has a delay of 3 hours, and this is
* called to reduce that delay to 1 hour, the new delay will take some time to take effect, enforcing that any
* operation executed in the 3 hours that follows this update was indeed scheduled before this update.
*
* Requirements:
*
* - the caller must be an admin for the role (see {getRoleAdmin})
* - granted role must not be the `PUBLIC_ROLE`
*
* Emits a {RoleGranted} event.
*/
function grantRole(uint64 roleId, address account, uint32 executionDelay) external;
/**
* @dev Remove an account from a role, with immediate effect. If the account does not have the role, this call has
* no effect.
*
* Requirements:
*
* - the caller must be an admin for the role (see {getRoleAdmin})
* - revoked role must not be the `PUBLIC_ROLE`
*
* Emits a {RoleRevoked} event if the account had the role.
*/
function revokeRole(uint64 roleId, address account) external;
/**
* @dev Renounce role permissions for the calling account with immediate effect. If the sender is not in
* the role this call has no effect.
*
* Requirements:
*
* - the caller must be `callerConfirmation`.
*
* Emits a {RoleRevoked} event if the account had the role.
*/
function renounceRole(uint64 roleId, address callerConfirmation) external;
/**
* @dev Change admin role for a given role.
*
* Requirements:
*
* - the caller must be a global admin
*
* Emits a {RoleAdminChanged} event
*/
function setRoleAdmin(uint64 roleId, uint64 admin) external;
/**
* @dev Change guardian role for a given role.
*
* Requirements:
*
* - the caller must be a global admin
*
* Emits a {RoleGuardianChanged} event
*/
function setRoleGuardian(uint64 roleId, uint64 guardian) external;
/**
* @dev Update the delay for granting a `roleId`.
*
* Requirements:
*
* - the caller must be a global admin
*
* Emits a {RoleGrantDelayChanged} event.
*/
function setGrantDelay(uint64 roleId, uint32 newDelay) external;
/**
* @dev Set the role required to call functions identified by the `selectors` in the `target` contract.
*
* Requirements:
*
* - the caller must be a global admin
*
* Emits a {TargetFunctionRoleUpdated} event per selector.
*/
function setTargetFunctionRole(address target, bytes4[] calldata selectors, uint64 roleId) external;
/**
* @dev Set the delay for changing the configuration of a given target contract.
*
* Requirements:
*
* - the caller must be a global admin
*
* Emits a {TargetAdminDelayUpdated} event.
*/
function setTargetAdminDelay(address target, uint32 newDelay) external;
/**
* @dev Set the closed flag for a contract.
*
* Closing the manager itself won't disable access to admin methods to avoid locking the contract.
*
* Requirements:
*
* - the caller must be a global admin
*
* Emits a {TargetClosed} event.
*/
function setTargetClosed(address target, bool closed) external;
/**
* @dev Return the timepoint at which a scheduled operation will be ready for execution. This returns 0 if the
* operation is not yet scheduled, has expired, was executed, or was canceled.
*/
function getSchedule(bytes32 id) external view returns (uint48);
/**
* @dev Return the nonce for the latest scheduled operation with a given id. Returns 0 if the operation has never
* been scheduled.
*/
function getNonce(bytes32 id) external view returns (uint32);
/**
* @dev Schedule a delayed operation for future execution, and return the operation identifier. It is possible to
* choose the timestamp at which the operation becomes executable as long as it satisfies the execution delays
* required for the caller. The special value zero will automatically set the earliest possible time.
*
* Returns the `operationId` that was scheduled. Since this value is a hash of the parameters, it can reoccur when
* the same parameters are used; if this is relevant, the returned `nonce` can be used to uniquely identify this
* scheduled operation from other occurrences of the same `operationId` in invocations of {execute} and {cancel}.
*
* Emits a {OperationScheduled} event.
*
* NOTE: It is not possible to concurrently schedule more than one operation with the same `target` and `data`. If
* this is necessary, a random byte can be appended to `data` to act as a salt that will be ignored by the target
* contract if it is using standard Solidity ABI encoding.
*/
function schedule(
address target,
bytes calldata data,
uint48 when
) external returns (bytes32 operationId, uint32 nonce);
/**
* @dev Execute a function that is delay restricted, provided it was properly scheduled beforehand, or the
* execution delay is 0.
*
* Returns the nonce that identifies the previously scheduled operation that is executed, or 0 if the
* operation wasn't previously scheduled (if the caller doesn't have an execution delay).
*
* Emits an {OperationExecuted} event only if the call was scheduled and delayed.
*/
function execute(address target, bytes calldata data) external payable returns (uint32);
/**
* @dev Cancel a scheduled (delayed) operation. Returns the nonce that identifies the previously scheduled
* operation that is cancelled.
*
* Requirements:
*
* - the caller must be the proposer, a guardian of the targeted function, or a global admin
*
* Emits a {OperationCanceled} event.
*/
function cancel(address caller, address target, bytes calldata data) external returns (uint32);
/**
* @dev Consume a scheduled operation targeting the caller. If such an operation exists, mark it as consumed
* (emit an {OperationExecuted} event and clean the state). Otherwise, throw an error.
*
* This is useful for contract that want to enforce that calls targeting them were scheduled on the manager,
* with all the verifications that it implies.
*
* Emit a {OperationExecuted} event.
*/
function consumeScheduledOp(address caller, bytes calldata data) external;
/**
* @dev Hashing function for delayed operations.
*/
function hashOperation(address caller, address target, bytes calldata data) external view returns (bytes32);
/**
* @dev Changes the authority of a target managed by this manager instance.
*
* Requirements:
*
* - the caller must be a global admin
*/
function updateAuthority(address target, address newAuthority) external;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/manager/IAccessManaged.sol)
pragma solidity ^0.8.20;
interface IAccessManaged {
/**
* @dev Authority that manages this contract was updated.
*/
event AuthorityUpdated(address authority);
error AccessManagedUnauthorized(address caller);
error AccessManagedRequiredDelay(address caller, uint32 delay);
error AccessManagedInvalidAuthority(address authority);
/**
* @dev Returns the current authority.
*/
function authority() external view returns (address);
/**
* @dev Transfers control to a new authority. The caller must be the current authority.
*/
function setAuthority(address) external;
/**
* @dev Returns true only in the context of a delayed restricted call, at the moment that the scheduled operation is
* being consumed. Prevents denial of service for delayed restricted calls in the case that the contract performs
* attacker controlled calls.
*/
function isConsumingScheduledOp() external view returns (bytes4);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)
pragma solidity ^0.8.20;
import {Initializable} from "../proxy/utils/Initializable.sol";
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract ContextUpgradeable is Initializable {
function __Context_init() internal onlyInitializing {
}
function __Context_init_unchained() internal onlyInitializing {
}
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
function _contextSuffixLength() internal view virtual returns (uint256) {
return 0;
}
}pragma solidity ^0.8.27;
enum IBCConnectionState {
Unspecified,
Init,
TryOpen,
Open
}
struct IBCConnection {
IBCConnectionState state;
uint32 clientId;
uint32 counterpartyClientId;
uint32 counterpartyConnectionId;
}
enum IBCChannelState {
Unspecified,
Init,
TryOpen,
Open,
Closed
}
struct IBCChannel {
IBCChannelState state;
uint32 connectionId;
uint32 counterpartyChannelId;
bytes counterpartyPortId;
string version;
}
struct IBCPacket {
uint32 sourceChannelId;
uint32 destinationChannelId;
bytes data;
uint64 timeoutHeight;
uint64 timeoutTimestamp;
}
library IBCErrors {
error ErrClientTypeAlreadyExists();
error ErrClientTypeNotFound();
error ErrInvalidProof();
error ErrInvalidConnectionState();
error ErrInvalidChannelState();
error ErrUnauthorized();
error ErrLatestTimestampNotFound();
error ErrTimeoutMustBeSet();
error ErrTimeoutHeightUnsupported();
error ErrHeightTimeout();
error ErrTimestampTimeout();
error ErrAcknowledgementIsEmpty();
error ErrPacketNotReceived();
error ErrAcknowledgementAlreadyExists();
error ErrPacketCommitmentNotFound();
error ErrPacketAlreadyAcknowledged();
error ErrTimeoutHeightNotReached();
error ErrTimeoutTimestampNotReached();
error ErrNotEnoughPackets();
error ErrBatchSameChannelOnly();
error ErrCommittedAckNotPresent();
error ErrClientNotFound();
error ErrModuleNotFound();
error ErrPacketAlreadyExist();
}pragma solidity ^0.8.27;
import "../Types.sol";
interface IIBCModuleRecv {
function onRecvPacket(
address caller,
IBCPacket calldata packet,
address relayer,
bytes calldata relayerMsg
) external returns (bytes memory);
function onRecvIntentPacket(
address caller,
IBCPacket calldata packet,
address marketMaker,
bytes calldata marketMakerMsg
) external returns (bytes memory);
}
// IIBCModule defines an interface that implements all the callbacks
// that modules must define as specified in ICS-26
// https://github.com/cosmos/ibc/blob/2921c5cec7b18e4ef77677e16a6b693051ae3b35/spec/core/ics-026-routing-module/README.md
interface IIBCModule is IIBCModuleRecv {
function onChanOpenInit(
address caller,
uint32 connectionId,
uint32 channelId,
string calldata version,
address relayer
) external;
function onChanOpenTry(
address caller,
uint32 connectionId,
uint32 channelId,
uint32 counterpartyChannelId,
string calldata version,
string calldata counterpartyVersion,
address relayer
) external;
function onChanOpenAck(
address caller,
uint32 channelId,
uint32 counterpartyChannelId,
string calldata counterpartyVersion,
address relayer
) external;
function onChanOpenConfirm(
address caller,
uint32 channelId,
address relayer
) external;
function onChanCloseInit(
address caller,
uint32 channelId,
address relayer
) external;
function onChanCloseConfirm(
address caller,
uint32 channelId,
address relayer
) external;
function onAcknowledgementPacket(
address caller,
IBCPacket calldata packet,
bytes calldata acknowledgement,
address relayer
) external;
function onTimeoutPacket(
address caller,
IBCPacket calldata,
address relayer
) external;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.3.0-rc.0) (utils/math/Math.sol)
pragma solidity ^0.8.20;
import {Panic} from "../Panic.sol";
import {SafeCast} from "./SafeCast.sol";
/**
* @dev Standard math utilities missing in the Solidity language.
*/
library Math {
enum Rounding {
Floor, // Toward negative infinity
Ceil, // Toward positive infinity
Trunc, // Toward zero
Expand // Away from zero
}
/**
* @dev Return the 512-bit addition of two uint256.
*
* The result is stored in two 256 variables such that sum = high * 2²⁵⁶ + low.
*/
function add512(uint256 a, uint256 b) internal pure returns (uint256 high, uint256 low) {
assembly ("memory-safe") {
low := add(a, b)
high := lt(low, a)
}
}
/**
* @dev Return the 512-bit multiplication of two uint256.
*
* The result is stored in two 256 variables such that product = high * 2²⁵⁶ + low.
*/
function mul512(uint256 a, uint256 b) internal pure returns (uint256 high, uint256 low) {
// 512-bit multiply [high low] = x * y. Compute the product mod 2²⁵⁶ and mod 2²⁵⁶ - 1, then use
// the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
// variables such that product = high * 2²⁵⁶ + low.
assembly ("memory-safe") {
let mm := mulmod(a, b, not(0))
low := mul(a, b)
high := sub(sub(mm, low), lt(mm, low))
}
}
/**
* @dev Returns the addition of two unsigned integers, with a success flag (no overflow).
*/
function tryAdd(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {
unchecked {
uint256 c = a + b;
success = c >= a;
result = c * SafeCast.toUint(success);
}
}
/**
* @dev Returns the subtraction of two unsigned integers, with a success flag (no overflow).
*/
function trySub(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {
unchecked {
uint256 c = a - b;
success = c <= a;
result = c * SafeCast.toUint(success);
}
}
/**
* @dev Returns the multiplication of two unsigned integers, with a success flag (no overflow).
*/
function tryMul(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {
unchecked {
uint256 c = a * b;
assembly ("memory-safe") {
// Only true when the multiplication doesn't overflow
// (c / a == b) || (a == 0)
success := or(eq(div(c, a), b), iszero(a))
}
// equivalent to: success ? c : 0
result = c * SafeCast.toUint(success);
}
}
/**
* @dev Returns the division of two unsigned integers, with a success flag (no division by zero).
*/
function tryDiv(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {
unchecked {
success = b > 0;
assembly ("memory-safe") {
// The `DIV` opcode returns zero when the denominator is 0.
result := div(a, b)
}
}
}
/**
* @dev Returns the remainder of dividing two unsigned integers, with a success flag (no division by zero).
*/
function tryMod(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {
unchecked {
success = b > 0;
assembly ("memory-safe") {
// The `MOD` opcode returns zero when the denominator is 0.
result := mod(a, b)
}
}
}
/**
* @dev Unsigned saturating addition, bounds to `2²⁵⁶ - 1` instead of overflowing.
*/
function saturatingAdd(uint256 a, uint256 b) internal pure returns (uint256) {
(bool success, uint256 result) = tryAdd(a, b);
return ternary(success, result, type(uint256).max);
}
/**
* @dev Unsigned saturating subtraction, bounds to zero instead of overflowing.
*/
function saturatingSub(uint256 a, uint256 b) internal pure returns (uint256) {
(, uint256 result) = trySub(a, b);
return result;
}
/**
* @dev Unsigned saturating multiplication, bounds to `2²⁵⁶ - 1` instead of overflowing.
*/
function saturatingMul(uint256 a, uint256 b) internal pure returns (uint256) {
(bool success, uint256 result) = tryMul(a, b);
return ternary(success, result, type(uint256).max);
}
/**
* @dev Branchless ternary evaluation for `a ? b : c`. Gas costs are constant.
*
* IMPORTANT: This function may reduce bytecode size and consume less gas when used standalone.
* However, the compiler may optimize Solidity ternary operations (i.e. `a ? b : c`) to only compute
* one branch when needed, making this function more expensive.
*/
function ternary(bool condition, uint256 a, uint256 b) internal pure returns (uint256) {
unchecked {
// branchless ternary works because:
// b ^ (a ^ b) == a
// b ^ 0 == b
return b ^ ((a ^ b) * SafeCast.toUint(condition));
}
}
/**
* @dev Returns the largest of two numbers.
*/
function max(uint256 a, uint256 b) internal pure returns (uint256) {
return ternary(a > b, a, b);
}
/**
* @dev Returns the smallest of two numbers.
*/
function min(uint256 a, uint256 b) internal pure returns (uint256) {
return ternary(a < b, a, b);
}
/**
* @dev Returns the average of two numbers. The result is rounded towards
* zero.
*/
function average(uint256 a, uint256 b) internal pure returns (uint256) {
// (a + b) / 2 can overflow.
return (a & b) + (a ^ b) / 2;
}
/**
* @dev Returns the ceiling of the division of two numbers.
*
* This differs from standard division with `/` in that it rounds towards infinity instead
* of rounding towards zero.
*/
function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
if (b == 0) {
// Guarantee the same behavior as in a regular Solidity division.
Panic.panic(Panic.DIVISION_BY_ZERO);
}
// The following calculation ensures accurate ceiling division without overflow.
// Since a is non-zero, (a - 1) / b will not overflow.
// The largest possible result occurs when (a - 1) / b is type(uint256).max,
// but the largest value we can obtain is type(uint256).max - 1, which happens
// when a = type(uint256).max and b = 1.
unchecked {
return SafeCast.toUint(a > 0) * ((a - 1) / b + 1);
}
}
/**
* @dev Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or
* denominator == 0.
*
* Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) with further edits by
* Uniswap Labs also under MIT license.
*/
function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {
unchecked {
(uint256 high, uint256 low) = mul512(x, y);
// Handle non-overflow cases, 256 by 256 division.
if (high == 0) {
// Solidity will revert if denominator == 0, unlike the div opcode on its own.
// The surrounding unchecked block does not change this fact.
// See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.
return low / denominator;
}
// Make sure the result is less than 2²⁵⁶. Also prevents denominator == 0.
if (denominator <= high) {
Panic.panic(ternary(denominator == 0, Panic.DIVISION_BY_ZERO, Panic.UNDER_OVERFLOW));
}
///////////////////////////////////////////////
// 512 by 256 division.
///////////////////////////////////////////////
// Make division exact by subtracting the remainder from [high low].
uint256 remainder;
assembly ("memory-safe") {
// Compute remainder using mulmod.
remainder := mulmod(x, y, denominator)
// Subtract 256 bit number from 512 bit number.
high := sub(high, gt(remainder, low))
low := sub(low, remainder)
}
// Factor powers of two out of denominator and compute largest power of two divisor of denominator.
// Always >= 1. See https://cs.stackexchange.com/q/138556/92363.
uint256 twos = denominator & (0 - denominator);
assembly ("memory-safe") {
// Divide denominator by twos.
denominator := div(denominator, twos)
// Divide [high low] by twos.
low := div(low, twos)
// Flip twos such that it is 2²⁵⁶ / twos. If twos is zero, then it becomes one.
twos := add(div(sub(0, twos), twos), 1)
}
// Shift in bits from high into low.
low |= high * twos;
// Invert denominator mod 2²⁵⁶. Now that denominator is an odd number, it has an inverse modulo 2²⁵⁶ such
// that denominator * inv ≡ 1 mod 2²⁵⁶. Compute the inverse by starting with a seed that is correct for
// four bits. That is, denominator * inv ≡ 1 mod 2⁴.
uint256 inverse = (3 * denominator) ^ 2;
// Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also
// works in modular arithmetic, doubling the correct bits in each step.
inverse *= 2 - denominator * inverse; // inverse mod 2⁸
inverse *= 2 - denominator * inverse; // inverse mod 2¹⁶
inverse *= 2 - denominator * inverse; // inverse mod 2³²
inverse *= 2 - denominator * inverse; // inverse mod 2⁶⁴
inverse *= 2 - denominator * inverse; // inverse mod 2¹²⁸
inverse *= 2 - denominator * inverse; // inverse mod 2²⁵⁶
// Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
// This will give us the correct result modulo 2²⁵⁶. Since the preconditions guarantee that the outcome is
// less than 2²⁵⁶, this is the final result. We don't need to compute the high bits of the result and high
// is no longer required.
result = low * inverse;
return result;
}
}
/**
* @dev Calculates x * y / denominator with full precision, following the selected rounding direction.
*/
function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {
return mulDiv(x, y, denominator) + SafeCast.toUint(unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0);
}
/**
* @dev Calculates floor(x * y >> n) with full precision. Throws if result overflows a uint256.
*/
function mulShr(uint256 x, uint256 y, uint8 n) internal pure returns (uint256 result) {
unchecked {
(uint256 high, uint256 low) = mul512(x, y);
if (high >= 1 << n) {
Panic.panic(Panic.UNDER_OVERFLOW);
}
return (high << (256 - n)) | (low >> n);
}
}
/**
* @dev Calculates x * y >> n with full precision, following the selected rounding direction.
*/
function mulShr(uint256 x, uint256 y, uint8 n, Rounding rounding) internal pure returns (uint256) {
return mulShr(x, y, n) + SafeCast.toUint(unsignedRoundsUp(rounding) && mulmod(x, y, 1 << n) > 0);
}
/**
* @dev Calculate the modular multiplicative inverse of a number in Z/nZ.
*
* If n is a prime, then Z/nZ is a field. In that case all elements are inversible, except 0.
* If n is not a prime, then Z/nZ is not a field, and some elements might not be inversible.
*
* If the input value is not inversible, 0 is returned.
*
* NOTE: If you know for sure that n is (big) a prime, it may be cheaper to use Fermat's little theorem and get the
* inverse using `Math.modExp(a, n - 2, n)`. See {invModPrime}.
*/
function invMod(uint256 a, uint256 n) internal pure returns (uint256) {
unchecked {
if (n == 0) return 0;
// The inverse modulo is calculated using the Extended Euclidean Algorithm (iterative version)
// Used to compute integers x and y such that: ax + ny = gcd(a, n).
// When the gcd is 1, then the inverse of a modulo n exists and it's x.
// ax + ny = 1
// ax = 1 + (-y)n
// ax ≡ 1 (mod n) # x is the inverse of a modulo n
// If the remainder is 0 the gcd is n right away.
uint256 remainder = a % n;
uint256 gcd = n;
// Therefore the initial coefficients are:
// ax + ny = gcd(a, n) = n
// 0a + 1n = n
int256 x = 0;
int256 y = 1;
while (remainder != 0) {
uint256 quotient = gcd / remainder;
(gcd, remainder) = (
// The old remainder is the next gcd to try.
remainder,
// Compute the next remainder.
// Can't overflow given that (a % gcd) * (gcd // (a % gcd)) <= gcd
// where gcd is at most n (capped to type(uint256).max)
gcd - remainder * quotient
);
(x, y) = (
// Increment the coefficient of a.
y,
// Decrement the coefficient of n.
// Can overflow, but the result is casted to uint256 so that the
// next value of y is "wrapped around" to a value between 0 and n - 1.
x - y * int256(quotient)
);
}
if (gcd != 1) return 0; // No inverse exists.
return ternary(x < 0, n - uint256(-x), uint256(x)); // Wrap the result if it's negative.
}
}
/**
* @dev Variant of {invMod}. More efficient, but only works if `p` is known to be a prime greater than `2`.
*
* From https://en.wikipedia.org/wiki/Fermat%27s_little_theorem[Fermat's little theorem], we know that if p is
* prime, then `a**(p-1) ≡ 1 mod p`. As a consequence, we have `a * a**(p-2) ≡ 1 mod p`, which means that
* `a**(p-2)` is the modular multiplicative inverse of a in Fp.
*
* NOTE: this function does NOT check that `p` is a prime greater than `2`.
*/
function invModPrime(uint256 a, uint256 p) internal view returns (uint256) {
unchecked {
return Math.modExp(a, p - 2, p);
}
}
/**
* @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m)
*
* Requirements:
* - modulus can't be zero
* - underlying staticcall to precompile must succeed
*
* IMPORTANT: The result is only valid if the underlying call succeeds. When using this function, make
* sure the chain you're using it on supports the precompiled contract for modular exponentiation
* at address 0x05 as specified in https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise,
* the underlying function will succeed given the lack of a revert, but the result may be incorrectly
* interpreted as 0.
*/
function modExp(uint256 b, uint256 e, uint256 m) internal view returns (uint256) {
(bool success, uint256 result) = tryModExp(b, e, m);
if (!success) {
Panic.panic(Panic.DIVISION_BY_ZERO);
}
return result;
}
/**
* @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m).
* It includes a success flag indicating if the operation succeeded. Operation will be marked as failed if trying
* to operate modulo 0 or if the underlying precompile reverted.
*
* IMPORTANT: The result is only valid if the success flag is true. When using this function, make sure the chain
* you're using it on supports the precompiled contract for modular exponentiation at address 0x05 as specified in
* https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise, the underlying function will succeed given the lack
* of a revert, but the result may be incorrectly interpreted as 0.
*/
function tryModExp(uint256 b, uint256 e, uint256 m) internal view returns (bool success, uint256 result) {
if (m == 0) return (false, 0);
assembly ("memory-safe") {
let ptr := mload(0x40)
// | Offset | Content | Content (Hex) |
// |-----------|------------|--------------------------------------------------------------------|
// | 0x00:0x1f | size of b | 0x0000000000000000000000000000000000000000000000000000000000000020 |
// | 0x20:0x3f | size of e | 0x0000000000000000000000000000000000000000000000000000000000000020 |
// | 0x40:0x5f | size of m | 0x0000000000000000000000000000000000000000000000000000000000000020 |
// | 0x60:0x7f | value of b | 0x<.............................................................b> |
// | 0x80:0x9f | value of e | 0x<.............................................................e> |
// | 0xa0:0xbf | value of m | 0x<.............................................................m> |
mstore(ptr, 0x20)
mstore(add(ptr, 0x20), 0x20)
mstore(add(ptr, 0x40), 0x20)
mstore(add(ptr, 0x60), b)
mstore(add(ptr, 0x80), e)
mstore(add(ptr, 0xa0), m)
// Given the result < m, it's guaranteed to fit in 32 bytes,
// so we can use the memory scratch space located at offset 0.
success := staticcall(gas(), 0x05, ptr, 0xc0, 0x00, 0x20)
result := mload(0x00)
}
}
/**
* @dev Variant of {modExp} that supports inputs of arbitrary length.
*/
function modExp(bytes memory b, bytes memory e, bytes memory m) internal view returns (bytes memory) {
(bool success, bytes memory result) = tryModExp(b, e, m);
if (!success) {
Panic.panic(Panic.DIVISION_BY_ZERO);
}
return result;
}
/**
* @dev Variant of {tryModExp} that supports inputs of arbitrary length.
*/
function tryModExp(
bytes memory b,
bytes memory e,
bytes memory m
) internal view returns (bool success, bytes memory result) {
if (_zeroBytes(m)) return (false, new bytes(0));
uint256 mLen = m.length;
// Encode call args in result and move the free memory pointer
result = abi.encodePacked(b.length, e.length, mLen, b, e, m);
assembly ("memory-safe") {
let dataPtr := add(result, 0x20)
// Write result on top of args to avoid allocating extra memory.
success := staticcall(gas(), 0x05, dataPtr, mload(result), dataPtr, mLen)
// Overwrite the length.
// result.length > returndatasize() is guaranteed because returndatasize() == m.length
mstore(result, mLen)
// Set the memory pointer after the returned data.
mstore(0x40, add(dataPtr, mLen))
}
}
/**
* @dev Returns whether the provided byte array is zero.
*/
function _zeroBytes(bytes memory byteArray) private pure returns (bool) {
for (uint256 i = 0; i < byteArray.length; ++i) {
if (byteArray[i] != 0) {
return false;
}
}
return true;
}
/**
* @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded
* towards zero.
*
* This method is based on Newton's method for computing square roots; the algorithm is restricted to only
* using integer operations.
*/
function sqrt(uint256 a) internal pure returns (uint256) {
unchecked {
// Take care of easy edge cases when a == 0 or a == 1
if (a <= 1) {
return a;
}
// In this function, we use Newton's method to get a root of `f(x) := x² - a`. It involves building a
// sequence x_n that converges toward sqrt(a). For each iteration x_n, we also define the error between
// the current value as `ε_n = | x_n - sqrt(a) |`.
//
// For our first estimation, we consider `e` the smallest power of 2 which is bigger than the square root
// of the target. (i.e. `2**(e-1) ≤ sqrt(a) < 2**e`). We know that `e ≤ 128` because `(2¹²⁸)² = 2²⁵⁶` is
// bigger than any uint256.
//
// By noticing that
// `2**(e-1) ≤ sqrt(a) < 2**e → (2**(e-1))² ≤ a < (2**e)² → 2**(2*e-2) ≤ a < 2**(2*e)`
// we can deduce that `e - 1` is `log2(a) / 2`. We can thus compute `x_n = 2**(e-1)` using a method similar
// to the msb function.
uint256 aa = a;
uint256 xn = 1;
if (aa >= (1 << 128)) {
aa >>= 128;
xn <<= 64;
}
if (aa >= (1 << 64)) {
aa >>= 64;
xn <<= 32;
}
if (aa >= (1 << 32)) {
aa >>= 32;
xn <<= 16;
}
if (aa >= (1 << 16)) {
aa >>= 16;
xn <<= 8;
}
if (aa >= (1 << 8)) {
aa >>= 8;
xn <<= 4;
}
if (aa >= (1 << 4)) {
aa >>= 4;
xn <<= 2;
}
if (aa >= (1 << 2)) {
xn <<= 1;
}
// We now have x_n such that `x_n = 2**(e-1) ≤ sqrt(a) < 2**e = 2 * x_n`. This implies ε_n ≤ 2**(e-1).
//
// We can refine our estimation by noticing that the middle of that interval minimizes the error.
// If we move x_n to equal 2**(e-1) + 2**(e-2), then we reduce the error to ε_n ≤ 2**(e-2).
// This is going to be our x_0 (and ε_0)
xn = (3 * xn) >> 1; // ε_0 := | x_0 - sqrt(a) | ≤ 2**(e-2)
// From here, Newton's method give us:
// x_{n+1} = (x_n + a / x_n) / 2
//
// One should note that:
// x_{n+1}² - a = ((x_n + a / x_n) / 2)² - a
// = ((x_n² + a) / (2 * x_n))² - a
// = (x_n⁴ + 2 * a * x_n² + a²) / (4 * x_n²) - a
// = (x_n⁴ + 2 * a * x_n² + a² - 4 * a * x_n²) / (4 * x_n²)
// = (x_n⁴ - 2 * a * x_n² + a²) / (4 * x_n²)
// = (x_n² - a)² / (2 * x_n)²
// = ((x_n² - a) / (2 * x_n))²
// ≥ 0
// Which proves that for all n ≥ 1, sqrt(a) ≤ x_n
//
// This gives us the proof of quadratic convergence of the sequence:
// ε_{n+1} = | x_{n+1} - sqrt(a) |
// = | (x_n + a / x_n) / 2 - sqrt(a) |
// = | (x_n² + a - 2*x_n*sqrt(a)) / (2 * x_n) |
// = | (x_n - sqrt(a))² / (2 * x_n) |
// = | ε_n² / (2 * x_n) |
// = ε_n² / | (2 * x_n) |
//
// For the first iteration, we have a special case where x_0 is known:
// ε_1 = ε_0² / | (2 * x_0) |
// ≤ (2**(e-2))² / (2 * (2**(e-1) + 2**(e-2)))
// ≤ 2**(2*e-4) / (3 * 2**(e-1))
// ≤ 2**(e-3) / 3
// ≤ 2**(e-3-log2(3))
// ≤ 2**(e-4.5)
//
// For the following iterations, we use the fact that, 2**(e-1) ≤ sqrt(a) ≤ x_n:
// ε_{n+1} = ε_n² / | (2 * x_n) |
// ≤ (2**(e-k))² / (2 * 2**(e-1))
// ≤ 2**(2*e-2*k) / 2**e
// ≤ 2**(e-2*k)
xn = (xn + a / xn) >> 1; // ε_1 := | x_1 - sqrt(a) | ≤ 2**(e-4.5) -- special case, see above
xn = (xn + a / xn) >> 1; // ε_2 := | x_2 - sqrt(a) | ≤ 2**(e-9) -- general case with k = 4.5
xn = (xn + a / xn) >> 1; // ε_3 := | x_3 - sqrt(a) | ≤ 2**(e-18) -- general case with k = 9
xn = (xn + a / xn) >> 1; // ε_4 := | x_4 - sqrt(a) | ≤ 2**(e-36) -- general case with k = 18
xn = (xn + a / xn) >> 1; // ε_5 := | x_5 - sqrt(a) | ≤ 2**(e-72) -- general case with k = 36
xn = (xn + a / xn) >> 1; // ε_6 := | x_6 - sqrt(a) | ≤ 2**(e-144) -- general case with k = 72
// Because e ≤ 128 (as discussed during the first estimation phase), we know have reached a precision
// ε_6 ≤ 2**(e-144) < 1. Given we're operating on integers, then we can ensure that xn is now either
// sqrt(a) or sqrt(a) + 1.
return xn - SafeCast.toUint(xn > a / xn);
}
}
/**
* @dev Calculates sqrt(a), following the selected rounding direction.
*/
function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = sqrt(a);
return result + SafeCast.toUint(unsignedRoundsUp(rounding) && result * result < a);
}
}
/**
* @dev Return the log in base 2 of a positive value rounded towards zero.
* Returns 0 if given 0.
*/
function log2(uint256 x) internal pure returns (uint256 r) {
// If value has upper 128 bits set, log2 result is at least 128
r = SafeCast.toUint(x > 0xffffffffffffffffffffffffffffffff) << 7;
// If upper 64 bits of 128-bit half set, add 64 to result
r |= SafeCast.toUint((x >> r) > 0xffffffffffffffff) << 6;
// If upper 32 bits of 64-bit half set, add 32 to result
r |= SafeCast.toUint((x >> r) > 0xffffffff) << 5;
// If upper 16 bits of 32-bit half set, add 16 to result
r |= SafeCast.toUint((x >> r) > 0xffff) << 4;
// If upper 8 bits of 16-bit half set, add 8 to result
r |= SafeCast.toUint((x >> r) > 0xff) << 3;
// If upper 4 bits of 8-bit half set, add 4 to result
r |= SafeCast.toUint((x >> r) > 0xf) << 2;
// Shifts value right by the current result and use it as an index into this lookup table:
//
// | x (4 bits) | index | table[index] = MSB position |
// |------------|---------|-----------------------------|
// | 0000 | 0 | table[0] = 0 |
// | 0001 | 1 | table[1] = 0 |
// | 0010 | 2 | table[2] = 1 |
// | 0011 | 3 | table[3] = 1 |
// | 0100 | 4 | table[4] = 2 |
// | 0101 | 5 | table[5] = 2 |
// | 0110 | 6 | table[6] = 2 |
// | 0111 | 7 | table[7] = 2 |
// | 1000 | 8 | table[8] = 3 |
// | 1001 | 9 | table[9] = 3 |
// | 1010 | 10 | table[10] = 3 |
// | 1011 | 11 | table[11] = 3 |
// | 1100 | 12 | table[12] = 3 |
// | 1101 | 13 | table[13] = 3 |
// | 1110 | 14 | table[14] = 3 |
// | 1111 | 15 | table[15] = 3 |
//
// The lookup table is represented as a 32-byte value with the MSB positions for 0-15 in the last 16 bytes.
assembly ("memory-safe") {
r := or(r, byte(shr(r, x), 0x0000010102020202030303030303030300000000000000000000000000000000))
}
}
/**
* @dev Return the log in base 2, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log2(value);
return result + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << result < value);
}
}
/**
* @dev Return the log in base 10 of a positive value rounded towards zero.
* Returns 0 if given 0.
*/
function log10(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >= 10 ** 64) {
value /= 10 ** 64;
result += 64;
}
if (value >= 10 ** 32) {
value /= 10 ** 32;
result += 32;
}
if (value >= 10 ** 16) {
value /= 10 ** 16;
result += 16;
}
if (value >= 10 ** 8) {
value /= 10 ** 8;
result += 8;
}
if (value >= 10 ** 4) {
value /= 10 ** 4;
result += 4;
}
if (value >= 10 ** 2) {
value /= 10 ** 2;
result += 2;
}
if (value >= 10 ** 1) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 10, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log10(value);
return result + SafeCast.toUint(unsignedRoundsUp(rounding) && 10 ** result < value);
}
}
/**
* @dev Return the log in base 256 of a positive value rounded towards zero.
* Returns 0 if given 0.
*
* Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
*/
function log256(uint256 x) internal pure returns (uint256 r) {
// If value has upper 128 bits set, log2 result is at least 128
r = SafeCast.toUint(x > 0xffffffffffffffffffffffffffffffff) << 7;
// If upper 64 bits of 128-bit half set, add 64 to result
r |= SafeCast.toUint((x >> r) > 0xffffffffffffffff) << 6;
// If upper 32 bits of 64-bit half set, add 32 to result
r |= SafeCast.toUint((x >> r) > 0xffffffff) << 5;
// If upper 16 bits of 32-bit half set, add 16 to result
r |= SafeCast.toUint((x >> r) > 0xffff) << 4;
// Add 1 if upper 8 bits of 16-bit half set, and divide accumulated result by 8
return (r >> 3) | SafeCast.toUint((x >> r) > 0xff);
}
/**
* @dev Return the log in base 256, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log256(value);
return result + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << (result << 3) < value);
}
}
/**
* @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers.
*/
function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) {
return uint8(rounding) % 2 == 1;
}
}pragma solidity ^0.8.27;
library UnionIcs23 {
struct ExistenceProof {
bytes key;
bytes value;
bytes leafPrefix;
InnerOp[] path;
}
struct NonExistenceProof {
bytes key;
ExistenceProof left;
ExistenceProof right;
}
struct InnerOp {
bytes prefix;
bytes suffix;
}
struct ProofSpec {
uint256 childSize;
uint256 minPrefixLength;
uint256 maxPrefixLength;
}
// Original spec is as follows, we trimmed the common parts:
// int32[] memory childOrder = new int32[](2);
// childOrder[0] = 0;
// childOrder[1] = 1;
// iavlProofSpec = CosmosIcs23V1ProofSpec.Data({
// leaf_spec: CosmosIcs23V1LeafOp.Data({
// prefix: hex"00",
// prehash_key: CosmosIcs23V1GlobalEnums.HashOp.NO_HASH,
// hash: CosmosIcs23V1GlobalEnums.HashOp.SHA256,
// prehash_value: CosmosIcs23V1GlobalEnums.HashOp.SHA256,
// length: CosmosIcs23V1GlobalEnums.LengthOp.VAR_PROTO
// }),
// inner_spec: CosmosIcs23V1InnerSpec.Data({
// child_order: childOrder,
// child_size: 33,
// min_prefix_length: 4,
// max_prefix_length: 12,
// empty_child: abi.encodePacked(),
// hash: CosmosIcs23V1GlobalEnums.HashOp.SHA256
// }),
// min_depth: 0,
// max_depth: 0
// });
function getIavlProofSpec() internal pure returns (ProofSpec memory) {
return
ProofSpec({childSize: 33, minPrefixLength: 4, maxPrefixLength: 12});
}
// Original spec is as follows, we trimmed the common parts:
// int32[] memory childOrder = new int32[](2);
// childOrder[0] = 0;
// childOrder[1] = 1;
// tendermintProofSpec = CosmosIcs23V1ProofSpec.Data({
// leaf_spec: CosmosIcs23V1LeafOp.Data({
// prefix: hex"00",
// prehash_key: CosmosIcs23V1GlobalEnums.HashOp.NO_HASH,
// hash: CosmosIcs23V1GlobalEnums.HashOp.SHA256,
// prehash_value: CosmosIcs23V1GlobalEnums.HashOp.SHA256,
// length: CosmosIcs23V1GlobalEnums.LengthOp.VAR_PROTO
// }),
// inner_spec: CosmosIcs23V1InnerSpec.Data({
// child_order: childOrder,
// child_size: 32,
// min_prefix_length: 1,
// max_prefix_length: 1,
// empty_child: abi.encodePacked(),
// hash: CosmosIcs23V1GlobalEnums.HashOp.SHA256
// }),
// min_depth: 0,
// max_depth: 0
// });
function getTendermintProofSpec()
internal
pure
returns (ProofSpec memory)
{
return
ProofSpec({childSize: 32, minPrefixLength: 1, maxPrefixLength: 1});
}
function empty(
NonExistenceProof calldata proof
) internal pure returns (bool) {
if (proof.key.length != 0) {
return false;
}
return empty(proof.left) && empty(proof.right);
}
function empty(
ExistenceProof calldata proof
) internal pure returns (bool) {
if (proof.key.length != 0) {
return false;
}
if (proof.value.length != 0) {
return false;
}
if (proof.leafPrefix.length != 0) {
return false;
}
if (proof.path.length != 0) {
return false;
}
return true;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (proxy/beacon/IBeacon.sol)
pragma solidity ^0.8.20;
/**
* @dev This is the interface that {BeaconProxy} expects of its beacon.
*/
interface IBeacon {
/**
* @dev Must return an address that can be used as a delegate call target.
*
* {UpgradeableBeacon} will check that this address is a contract.
*/
function implementation() external view returns (address);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC1967.sol)
pragma solidity ^0.8.20;
/**
* @dev ERC-1967: Proxy Storage Slots. This interface contains the events defined in the ERC.
*/
interface IERC1967 {
/**
* @dev Emitted when the implementation is upgraded.
*/
event Upgraded(address indexed implementation);
/**
* @dev Emitted when the admin account has changed.
*/
event AdminChanged(address previousAdmin, address newAdmin);
/**
* @dev Emitted when the beacon is changed.
*/
event BeaconUpgraded(address indexed beacon);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.2.0) (utils/Address.sol)
pragma solidity ^0.8.20;
import {Errors} from "./Errors.sol";
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev There's no code at `target` (it is not a contract).
*/
error AddressEmptyCode(address target);
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
if (address(this).balance < amount) {
revert Errors.InsufficientBalance(address(this).balance, amount);
}
(bool success, bytes memory returndata) = recipient.call{value: amount}("");
if (!success) {
_revert(returndata);
}
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason or custom error, it is bubbled
* up by this function (like regular Solidity function calls). However, if
* the call reverted with no returned reason, this function reverts with a
* {Errors.FailedCall} error.
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*/
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
if (address(this).balance < value) {
revert Errors.InsufficientBalance(address(this).balance, value);
}
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata);
}
/**
* @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target
* was not a contract or bubbling up the revert reason (falling back to {Errors.FailedCall}) in case
* of an unsuccessful call.
*/
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata
) internal view returns (bytes memory) {
if (!success) {
_revert(returndata);
} else {
// only check if target is a contract if the call was successful and the return data is empty
// otherwise we already know that it was a contract
if (returndata.length == 0 && target.code.length == 0) {
revert AddressEmptyCode(target);
}
return returndata;
}
}
/**
* @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the
* revert reason or with a default {Errors.FailedCall} error.
*/
function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {
if (!success) {
_revert(returndata);
} else {
return returndata;
}
}
/**
* @dev Reverts with returndata if present. Otherwise reverts with {Errors.FailedCall}.
*/
function _revert(bytes memory returndata) private pure {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
assembly ("memory-safe") {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert Errors.FailedCall();
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/StorageSlot.sol)
// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.
pragma solidity ^0.8.20;
/**
* @dev Library for reading and writing primitive types to specific storage slots.
*
* Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.
* This library helps with reading and writing to such slots without the need for inline assembly.
*
* The functions in this library return Slot structs that contain a `value` member that can be used to read or write.
*
* Example usage to set ERC-1967 implementation slot:
* ```solidity
* contract ERC1967 {
* // Define the slot. Alternatively, use the SlotDerivation library to derive the slot.
* bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
*
* function _getImplementation() internal view returns (address) {
* return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;
* }
*
* function _setImplementation(address newImplementation) internal {
* require(newImplementation.code.length > 0);
* StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
* }
* }
* ```
*
* TIP: Consider using this library along with {SlotDerivation}.
*/
library StorageSlot {
struct AddressSlot {
address value;
}
struct BooleanSlot {
bool value;
}
struct Bytes32Slot {
bytes32 value;
}
struct Uint256Slot {
uint256 value;
}
struct Int256Slot {
int256 value;
}
struct StringSlot {
string value;
}
struct BytesSlot {
bytes value;
}
/**
* @dev Returns an `AddressSlot` with member `value` located at `slot`.
*/
function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {
assembly ("memory-safe") {
r.slot := slot
}
}
/**
* @dev Returns a `BooleanSlot` with member `value` located at `slot`.
*/
function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {
assembly ("memory-safe") {
r.slot := slot
}
}
/**
* @dev Returns a `Bytes32Slot` with member `value` located at `slot`.
*/
function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {
assembly ("memory-safe") {
r.slot := slot
}
}
/**
* @dev Returns a `Uint256Slot` with member `value` located at `slot`.
*/
function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {
assembly ("memory-safe") {
r.slot := slot
}
}
/**
* @dev Returns a `Int256Slot` with member `value` located at `slot`.
*/
function getInt256Slot(bytes32 slot) internal pure returns (Int256Slot storage r) {
assembly ("memory-safe") {
r.slot := slot
}
}
/**
* @dev Returns a `StringSlot` with member `value` located at `slot`.
*/
function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {
assembly ("memory-safe") {
r.slot := slot
}
}
/**
* @dev Returns an `StringSlot` representation of the string storage pointer `store`.
*/
function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {
assembly ("memory-safe") {
r.slot := store.slot
}
}
/**
* @dev Returns a `BytesSlot` with member `value` located at `slot`.
*/
function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {
assembly ("memory-safe") {
r.slot := slot
}
}
/**
* @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.
*/
function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {
assembly ("memory-safe") {
r.slot := store.slot
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/types/Time.sol)
pragma solidity ^0.8.20;
import {Math} from "../math/Math.sol";
import {SafeCast} from "../math/SafeCast.sol";
/**
* @dev This library provides helpers for manipulating time-related objects.
*
* It uses the following types:
* - `uint48` for timepoints
* - `uint32` for durations
*
* While the library doesn't provide specific types for timepoints and duration, it does provide:
* - a `Delay` type to represent duration that can be programmed to change value automatically at a given point
* - additional helper functions
*/
library Time {
using Time for *;
/**
* @dev Get the block timestamp as a Timepoint.
*/
function timestamp() internal view returns (uint48) {
return SafeCast.toUint48(block.timestamp);
}
/**
* @dev Get the block number as a Timepoint.
*/
function blockNumber() internal view returns (uint48) {
return SafeCast.toUint48(block.number);
}
// ==================================================== Delay =====================================================
/**
* @dev A `Delay` is a uint32 duration that can be programmed to change value automatically at a given point in the
* future. The "effect" timepoint describes when the transitions happens from the "old" value to the "new" value.
* This allows updating the delay applied to some operation while keeping some guarantees.
*
* In particular, the {update} function guarantees that if the delay is reduced, the old delay still applies for
* some time. For example if the delay is currently 7 days to do an upgrade, the admin should not be able to set
* the delay to 0 and upgrade immediately. If the admin wants to reduce the delay, the old delay (7 days) should
* still apply for some time.
*
*
* The `Delay` type is 112 bits long, and packs the following:
*
* ```
* | [uint48]: effect date (timepoint)
* | | [uint32]: value before (duration)
* ↓ ↓ ↓ [uint32]: value after (duration)
* 0xAAAAAAAAAAAABBBBBBBBCCCCCCCC
* ```
*
* NOTE: The {get} and {withUpdate} functions operate using timestamps. Block number based delays are not currently
* supported.
*/
type Delay is uint112;
/**
* @dev Wrap a duration into a Delay to add the one-step "update in the future" feature
*/
function toDelay(uint32 duration) internal pure returns (Delay) {
return Delay.wrap(duration);
}
/**
* @dev Get the value at a given timepoint plus the pending value and effect timepoint if there is a scheduled
* change after this timepoint. If the effect timepoint is 0, then the pending value should not be considered.
*/
function _getFullAt(
Delay self,
uint48 timepoint
) private pure returns (uint32 valueBefore, uint32 valueAfter, uint48 effect) {
(valueBefore, valueAfter, effect) = self.unpack();
return effect <= timepoint ? (valueAfter, 0, 0) : (valueBefore, valueAfter, effect);
}
/**
* @dev Get the current value plus the pending value and effect timepoint if there is a scheduled change. If the
* effect timepoint is 0, then the pending value should not be considered.
*/
function getFull(Delay self) internal view returns (uint32 valueBefore, uint32 valueAfter, uint48 effect) {
return _getFullAt(self, timestamp());
}
/**
* @dev Get the current value.
*/
function get(Delay self) internal view returns (uint32) {
(uint32 delay, , ) = self.getFull();
return delay;
}
/**
* @dev Update a Delay object so that it takes a new duration after a timepoint that is automatically computed to
* enforce the old delay at the moment of the update. Returns the updated Delay object and the timestamp when the
* new delay becomes effective.
*/
function withUpdate(
Delay self,
uint32 newValue,
uint32 minSetback
) internal view returns (Delay updatedDelay, uint48 effect) {
uint32 value = self.get();
uint32 setback = uint32(Math.max(minSetback, value > newValue ? value - newValue : 0));
effect = timestamp() + setback;
return (pack(value, newValue, effect), effect);
}
/**
* @dev Split a delay into its components: valueBefore, valueAfter and effect (transition timepoint).
*/
function unpack(Delay self) internal pure returns (uint32 valueBefore, uint32 valueAfter, uint48 effect) {
uint112 raw = Delay.unwrap(self);
valueAfter = uint32(raw);
valueBefore = uint32(raw >> 32);
effect = uint48(raw >> 64);
return (valueBefore, valueAfter, effect);
}
/**
* @dev pack the components into a Delay object.
*/
function pack(uint32 valueBefore, uint32 valueAfter, uint48 effect) internal pure returns (Delay) {
return Delay.wrap((uint112(effect) << 64) | (uint112(valueBefore) << 32) | uint112(valueAfter));
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/Panic.sol)
pragma solidity ^0.8.20;
/**
* @dev Helper library for emitting standardized panic codes.
*
* ```solidity
* contract Example {
* using Panic for uint256;
*
* // Use any of the declared internal constants
* function foo() { Panic.GENERIC.panic(); }
*
* // Alternatively
* function foo() { Panic.panic(Panic.GENERIC); }
* }
* ```
*
* Follows the list from https://github.com/ethereum/solidity/blob/v0.8.24/libsolutil/ErrorCodes.h[libsolutil].
*
* _Available since v5.1._
*/
// slither-disable-next-line unused-state
library Panic {
/// @dev generic / unspecified error
uint256 internal constant GENERIC = 0x00;
/// @dev used by the assert() builtin
uint256 internal constant ASSERT = 0x01;
/// @dev arithmetic underflow or overflow
uint256 internal constant UNDER_OVERFLOW = 0x11;
/// @dev division or modulo by zero
uint256 internal constant DIVISION_BY_ZERO = 0x12;
/// @dev enum conversion error
uint256 internal constant ENUM_CONVERSION_ERROR = 0x21;
/// @dev invalid encoding in storage
uint256 internal constant STORAGE_ENCODING_ERROR = 0x22;
/// @dev empty array pop
uint256 internal constant EMPTY_ARRAY_POP = 0x31;
/// @dev array out of bounds access
uint256 internal constant ARRAY_OUT_OF_BOUNDS = 0x32;
/// @dev resource error (too large allocation or too large array)
uint256 internal constant RESOURCE_ERROR = 0x41;
/// @dev calling invalid internal function
uint256 internal constant INVALID_INTERNAL_FUNCTION = 0x51;
/// @dev Reverts with a panic code. Recommended to use with
/// the internal constants with predefined codes.
function panic(uint256 code) internal pure {
assembly ("memory-safe") {
mstore(0x00, 0x4e487b71)
mstore(0x20, code)
revert(0x1c, 0x24)
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/math/SafeCast.sol)
// This file was procedurally generated from scripts/generate/templates/SafeCast.js.
pragma solidity ^0.8.20;
/**
* @dev Wrappers over Solidity's uintXX/intXX/bool casting operators with added overflow
* checks.
*
* Downcasting from uint256/int256 in Solidity does not revert on overflow. This can
* easily result in undesired exploitation or bugs, since developers usually
* assume that overflows raise errors. `SafeCast` restores this intuition by
* reverting the transaction when such an operation overflows.
*
* Using this library instead of the unchecked operations eliminates an entire
* class of bugs, so it's recommended to use it always.
*/
library SafeCast {
/**
* @dev Value doesn't fit in an uint of `bits` size.
*/
error SafeCastOverflowedUintDowncast(uint8 bits, uint256 value);
/**
* @dev An int value doesn't fit in an uint of `bits` size.
*/
error SafeCastOverflowedIntToUint(int256 value);
/**
* @dev Value doesn't fit in an int of `bits` size.
*/
error SafeCastOverflowedIntDowncast(uint8 bits, int256 value);
/**
* @dev An uint value doesn't fit in an int of `bits` size.
*/
error SafeCastOverflowedUintToInt(uint256 value);
/**
* @dev Returns the downcasted uint248 from uint256, reverting on
* overflow (when the input is greater than largest uint248).
*
* Counterpart to Solidity's `uint248` operator.
*
* Requirements:
*
* - input must fit into 248 bits
*/
function toUint248(uint256 value) internal pure returns (uint248) {
if (value > type(uint248).max) {
revert SafeCastOverflowedUintDowncast(248, value);
}
return uint248(value);
}
/**
* @dev Returns the downcasted uint240 from uint256, reverting on
* overflow (when the input is greater than largest uint240).
*
* Counterpart to Solidity's `uint240` operator.
*
* Requirements:
*
* - input must fit into 240 bits
*/
function toUint240(uint256 value) internal pure returns (uint240) {
if (value > type(uint240).max) {
revert SafeCastOverflowedUintDowncast(240, value);
}
return uint240(value);
}
/**
* @dev Returns the downcasted uint232 from uint256, reverting on
* overflow (when the input is greater than largest uint232).
*
* Counterpart to Solidity's `uint232` operator.
*
* Requirements:
*
* - input must fit into 232 bits
*/
function toUint232(uint256 value) internal pure returns (uint232) {
if (value > type(uint232).max) {
revert SafeCastOverflowedUintDowncast(232, value);
}
return uint232(value);
}
/**
* @dev Returns the downcasted uint224 from uint256, reverting on
* overflow (when the input is greater than largest uint224).
*
* Counterpart to Solidity's `uint224` operator.
*
* Requirements:
*
* - input must fit into 224 bits
*/
function toUint224(uint256 value) internal pure returns (uint224) {
if (value > type(uint224).max) {
revert SafeCastOverflowedUintDowncast(224, value);
}
return uint224(value);
}
/**
* @dev Returns the downcasted uint216 from uint256, reverting on
* overflow (when the input is greater than largest uint216).
*
* Counterpart to Solidity's `uint216` operator.
*
* Requirements:
*
* - input must fit into 216 bits
*/
function toUint216(uint256 value) internal pure returns (uint216) {
if (value > type(uint216).max) {
revert SafeCastOverflowedUintDowncast(216, value);
}
return uint216(value);
}
/**
* @dev Returns the downcasted uint208 from uint256, reverting on
* overflow (when the input is greater than largest uint208).
*
* Counterpart to Solidity's `uint208` operator.
*
* Requirements:
*
* - input must fit into 208 bits
*/
function toUint208(uint256 value) internal pure returns (uint208) {
if (value > type(uint208).max) {
revert SafeCastOverflowedUintDowncast(208, value);
}
return uint208(value);
}
/**
* @dev Returns the downcasted uint200 from uint256, reverting on
* overflow (when the input is greater than largest uint200).
*
* Counterpart to Solidity's `uint200` operator.
*
* Requirements:
*
* - input must fit into 200 bits
*/
function toUint200(uint256 value) internal pure returns (uint200) {
if (value > type(uint200).max) {
revert SafeCastOverflowedUintDowncast(200, value);
}
return uint200(value);
}
/**
* @dev Returns the downcasted uint192 from uint256, reverting on
* overflow (when the input is greater than largest uint192).
*
* Counterpart to Solidity's `uint192` operator.
*
* Requirements:
*
* - input must fit into 192 bits
*/
function toUint192(uint256 value) internal pure returns (uint192) {
if (value > type(uint192).max) {
revert SafeCastOverflowedUintDowncast(192, value);
}
return uint192(value);
}
/**
* @dev Returns the downcasted uint184 from uint256, reverting on
* overflow (when the input is greater than largest uint184).
*
* Counterpart to Solidity's `uint184` operator.
*
* Requirements:
*
* - input must fit into 184 bits
*/
function toUint184(uint256 value) internal pure returns (uint184) {
if (value > type(uint184).max) {
revert SafeCastOverflowedUintDowncast(184, value);
}
return uint184(value);
}
/**
* @dev Returns the downcasted uint176 from uint256, reverting on
* overflow (when the input is greater than largest uint176).
*
* Counterpart to Solidity's `uint176` operator.
*
* Requirements:
*
* - input must fit into 176 bits
*/
function toUint176(uint256 value) internal pure returns (uint176) {
if (value > type(uint176).max) {
revert SafeCastOverflowedUintDowncast(176, value);
}
return uint176(value);
}
/**
* @dev Returns the downcasted uint168 from uint256, reverting on
* overflow (when the input is greater than largest uint168).
*
* Counterpart to Solidity's `uint168` operator.
*
* Requirements:
*
* - input must fit into 168 bits
*/
function toUint168(uint256 value) internal pure returns (uint168) {
if (value > type(uint168).max) {
revert SafeCastOverflowedUintDowncast(168, value);
}
return uint168(value);
}
/**
* @dev Returns the downcasted uint160 from uint256, reverting on
* overflow (when the input is greater than largest uint160).
*
* Counterpart to Solidity's `uint160` operator.
*
* Requirements:
*
* - input must fit into 160 bits
*/
function toUint160(uint256 value) internal pure returns (uint160) {
if (value > type(uint160).max) {
revert SafeCastOverflowedUintDowncast(160, value);
}
return uint160(value);
}
/**
* @dev Returns the downcasted uint152 from uint256, reverting on
* overflow (when the input is greater than largest uint152).
*
* Counterpart to Solidity's `uint152` operator.
*
* Requirements:
*
* - input must fit into 152 bits
*/
function toUint152(uint256 value) internal pure returns (uint152) {
if (value > type(uint152).max) {
revert SafeCastOverflowedUintDowncast(152, value);
}
return uint152(value);
}
/**
* @dev Returns the downcasted uint144 from uint256, reverting on
* overflow (when the input is greater than largest uint144).
*
* Counterpart to Solidity's `uint144` operator.
*
* Requirements:
*
* - input must fit into 144 bits
*/
function toUint144(uint256 value) internal pure returns (uint144) {
if (value > type(uint144).max) {
revert SafeCastOverflowedUintDowncast(144, value);
}
return uint144(value);
}
/**
* @dev Returns the downcasted uint136 from uint256, reverting on
* overflow (when the input is greater than largest uint136).
*
* Counterpart to Solidity's `uint136` operator.
*
* Requirements:
*
* - input must fit into 136 bits
*/
function toUint136(uint256 value) internal pure returns (uint136) {
if (value > type(uint136).max) {
revert SafeCastOverflowedUintDowncast(136, value);
}
return uint136(value);
}
/**
* @dev Returns the downcasted uint128 from uint256, reverting on
* overflow (when the input is greater than largest uint128).
*
* Counterpart to Solidity's `uint128` operator.
*
* Requirements:
*
* - input must fit into 128 bits
*/
function toUint128(uint256 value) internal pure returns (uint128) {
if (value > type(uint128).max) {
revert SafeCastOverflowedUintDowncast(128, value);
}
return uint128(value);
}
/**
* @dev Returns the downcasted uint120 from uint256, reverting on
* overflow (when the input is greater than largest uint120).
*
* Counterpart to Solidity's `uint120` operator.
*
* Requirements:
*
* - input must fit into 120 bits
*/
function toUint120(uint256 value) internal pure returns (uint120) {
if (value > type(uint120).max) {
revert SafeCastOverflowedUintDowncast(120, value);
}
return uint120(value);
}
/**
* @dev Returns the downcasted uint112 from uint256, reverting on
* overflow (when the input is greater than largest uint112).
*
* Counterpart to Solidity's `uint112` operator.
*
* Requirements:
*
* - input must fit into 112 bits
*/
function toUint112(uint256 value) internal pure returns (uint112) {
if (value > type(uint112).max) {
revert SafeCastOverflowedUintDowncast(112, value);
}
return uint112(value);
}
/**
* @dev Returns the downcasted uint104 from uint256, reverting on
* overflow (when the input is greater than largest uint104).
*
* Counterpart to Solidity's `uint104` operator.
*
* Requirements:
*
* - input must fit into 104 bits
*/
function toUint104(uint256 value) internal pure returns (uint104) {
if (value > type(uint104).max) {
revert SafeCastOverflowedUintDowncast(104, value);
}
return uint104(value);
}
/**
* @dev Returns the downcasted uint96 from uint256, reverting on
* overflow (when the input is greater than largest uint96).
*
* Counterpart to Solidity's `uint96` operator.
*
* Requirements:
*
* - input must fit into 96 bits
*/
function toUint96(uint256 value) internal pure returns (uint96) {
if (value > type(uint96).max) {
revert SafeCastOverflowedUintDowncast(96, value);
}
return uint96(value);
}
/**
* @dev Returns the downcasted uint88 from uint256, reverting on
* overflow (when the input is greater than largest uint88).
*
* Counterpart to Solidity's `uint88` operator.
*
* Requirements:
*
* - input must fit into 88 bits
*/
function toUint88(uint256 value) internal pure returns (uint88) {
if (value > type(uint88).max) {
revert SafeCastOverflowedUintDowncast(88, value);
}
return uint88(value);
}
/**
* @dev Returns the downcasted uint80 from uint256, reverting on
* overflow (when the input is greater than largest uint80).
*
* Counterpart to Solidity's `uint80` operator.
*
* Requirements:
*
* - input must fit into 80 bits
*/
function toUint80(uint256 value) internal pure returns (uint80) {
if (value > type(uint80).max) {
revert SafeCastOverflowedUintDowncast(80, value);
}
return uint80(value);
}
/**
* @dev Returns the downcasted uint72 from uint256, reverting on
* overflow (when the input is greater than largest uint72).
*
* Counterpart to Solidity's `uint72` operator.
*
* Requirements:
*
* - input must fit into 72 bits
*/
function toUint72(uint256 value) internal pure returns (uint72) {
if (value > type(uint72).max) {
revert SafeCastOverflowedUintDowncast(72, value);
}
return uint72(value);
}
/**
* @dev Returns the downcasted uint64 from uint256, reverting on
* overflow (when the input is greater than largest uint64).
*
* Counterpart to Solidity's `uint64` operator.
*
* Requirements:
*
* - input must fit into 64 bits
*/
function toUint64(uint256 value) internal pure returns (uint64) {
if (value > type(uint64).max) {
revert SafeCastOverflowedUintDowncast(64, value);
}
return uint64(value);
}
/**
* @dev Returns the downcasted uint56 from uint256, reverting on
* overflow (when the input is greater than largest uint56).
*
* Counterpart to Solidity's `uint56` operator.
*
* Requirements:
*
* - input must fit into 56 bits
*/
function toUint56(uint256 value) internal pure returns (uint56) {
if (value > type(uint56).max) {
revert SafeCastOverflowedUintDowncast(56, value);
}
return uint56(value);
}
/**
* @dev Returns the downcasted uint48 from uint256, reverting on
* overflow (when the input is greater than largest uint48).
*
* Counterpart to Solidity's `uint48` operator.
*
* Requirements:
*
* - input must fit into 48 bits
*/
function toUint48(uint256 value) internal pure returns (uint48) {
if (value > type(uint48).max) {
revert SafeCastOverflowedUintDowncast(48, value);
}
return uint48(value);
}
/**
* @dev Returns the downcasted uint40 from uint256, reverting on
* overflow (when the input is greater than largest uint40).
*
* Counterpart to Solidity's `uint40` operator.
*
* Requirements:
*
* - input must fit into 40 bits
*/
function toUint40(uint256 value) internal pure returns (uint40) {
if (value > type(uint40).max) {
revert SafeCastOverflowedUintDowncast(40, value);
}
return uint40(value);
}
/**
* @dev Returns the downcasted uint32 from uint256, reverting on
* overflow (when the input is greater than largest uint32).
*
* Counterpart to Solidity's `uint32` operator.
*
* Requirements:
*
* - input must fit into 32 bits
*/
function toUint32(uint256 value) internal pure returns (uint32) {
if (value > type(uint32).max) {
revert SafeCastOverflowedUintDowncast(32, value);
}
return uint32(value);
}
/**
* @dev Returns the downcasted uint24 from uint256, reverting on
* overflow (when the input is greater than largest uint24).
*
* Counterpart to Solidity's `uint24` operator.
*
* Requirements:
*
* - input must fit into 24 bits
*/
function toUint24(uint256 value) internal pure returns (uint24) {
if (value > type(uint24).max) {
revert SafeCastOverflowedUintDowncast(24, value);
}
return uint24(value);
}
/**
* @dev Returns the downcasted uint16 from uint256, reverting on
* overflow (when the input is greater than largest uint16).
*
* Counterpart to Solidity's `uint16` operator.
*
* Requirements:
*
* - input must fit into 16 bits
*/
function toUint16(uint256 value) internal pure returns (uint16) {
if (value > type(uint16).max) {
revert SafeCastOverflowedUintDowncast(16, value);
}
return uint16(value);
}
/**
* @dev Returns the downcasted uint8 from uint256, reverting on
* overflow (when the input is greater than largest uint8).
*
* Counterpart to Solidity's `uint8` operator.
*
* Requirements:
*
* - input must fit into 8 bits
*/
function toUint8(uint256 value) internal pure returns (uint8) {
if (value > type(uint8).max) {
revert SafeCastOverflowedUintDowncast(8, value);
}
return uint8(value);
}
/**
* @dev Converts a signed int256 into an unsigned uint256.
*
* Requirements:
*
* - input must be greater than or equal to 0.
*/
function toUint256(int256 value) internal pure returns (uint256) {
if (value < 0) {
revert SafeCastOverflowedIntToUint(value);
}
return uint256(value);
}
/**
* @dev Returns the downcasted int248 from int256, reverting on
* overflow (when the input is less than smallest int248 or
* greater than largest int248).
*
* Counterpart to Solidity's `int248` operator.
*
* Requirements:
*
* - input must fit into 248 bits
*/
function toInt248(int256 value) internal pure returns (int248 downcasted) {
downcasted = int248(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(248, value);
}
}
/**
* @dev Returns the downcasted int240 from int256, reverting on
* overflow (when the input is less than smallest int240 or
* greater than largest int240).
*
* Counterpart to Solidity's `int240` operator.
*
* Requirements:
*
* - input must fit into 240 bits
*/
function toInt240(int256 value) internal pure returns (int240 downcasted) {
downcasted = int240(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(240, value);
}
}
/**
* @dev Returns the downcasted int232 from int256, reverting on
* overflow (when the input is less than smallest int232 or
* greater than largest int232).
*
* Counterpart to Solidity's `int232` operator.
*
* Requirements:
*
* - input must fit into 232 bits
*/
function toInt232(int256 value) internal pure returns (int232 downcasted) {
downcasted = int232(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(232, value);
}
}
/**
* @dev Returns the downcasted int224 from int256, reverting on
* overflow (when the input is less than smallest int224 or
* greater than largest int224).
*
* Counterpart to Solidity's `int224` operator.
*
* Requirements:
*
* - input must fit into 224 bits
*/
function toInt224(int256 value) internal pure returns (int224 downcasted) {
downcasted = int224(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(224, value);
}
}
/**
* @dev Returns the downcasted int216 from int256, reverting on
* overflow (when the input is less than smallest int216 or
* greater than largest int216).
*
* Counterpart to Solidity's `int216` operator.
*
* Requirements:
*
* - input must fit into 216 bits
*/
function toInt216(int256 value) internal pure returns (int216 downcasted) {
downcasted = int216(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(216, value);
}
}
/**
* @dev Returns the downcasted int208 from int256, reverting on
* overflow (when the input is less than smallest int208 or
* greater than largest int208).
*
* Counterpart to Solidity's `int208` operator.
*
* Requirements:
*
* - input must fit into 208 bits
*/
function toInt208(int256 value) internal pure returns (int208 downcasted) {
downcasted = int208(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(208, value);
}
}
/**
* @dev Returns the downcasted int200 from int256, reverting on
* overflow (when the input is less than smallest int200 or
* greater than largest int200).
*
* Counterpart to Solidity's `int200` operator.
*
* Requirements:
*
* - input must fit into 200 bits
*/
function toInt200(int256 value) internal pure returns (int200 downcasted) {
downcasted = int200(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(200, value);
}
}
/**
* @dev Returns the downcasted int192 from int256, reverting on
* overflow (when the input is less than smallest int192 or
* greater than largest int192).
*
* Counterpart to Solidity's `int192` operator.
*
* Requirements:
*
* - input must fit into 192 bits
*/
function toInt192(int256 value) internal pure returns (int192 downcasted) {
downcasted = int192(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(192, value);
}
}
/**
* @dev Returns the downcasted int184 from int256, reverting on
* overflow (when the input is less than smallest int184 or
* greater than largest int184).
*
* Counterpart to Solidity's `int184` operator.
*
* Requirements:
*
* - input must fit into 184 bits
*/
function toInt184(int256 value) internal pure returns (int184 downcasted) {
downcasted = int184(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(184, value);
}
}
/**
* @dev Returns the downcasted int176 from int256, reverting on
* overflow (when the input is less than smallest int176 or
* greater than largest int176).
*
* Counterpart to Solidity's `int176` operator.
*
* Requirements:
*
* - input must fit into 176 bits
*/
function toInt176(int256 value) internal pure returns (int176 downcasted) {
downcasted = int176(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(176, value);
}
}
/**
* @dev Returns the downcasted int168 from int256, reverting on
* overflow (when the input is less than smallest int168 or
* greater than largest int168).
*
* Counterpart to Solidity's `int168` operator.
*
* Requirements:
*
* - input must fit into 168 bits
*/
function toInt168(int256 value) internal pure returns (int168 downcasted) {
downcasted = int168(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(168, value);
}
}
/**
* @dev Returns the downcasted int160 from int256, reverting on
* overflow (when the input is less than smallest int160 or
* greater than largest int160).
*
* Counterpart to Solidity's `int160` operator.
*
* Requirements:
*
* - input must fit into 160 bits
*/
function toInt160(int256 value) internal pure returns (int160 downcasted) {
downcasted = int160(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(160, value);
}
}
/**
* @dev Returns the downcasted int152 from int256, reverting on
* overflow (when the input is less than smallest int152 or
* greater than largest int152).
*
* Counterpart to Solidity's `int152` operator.
*
* Requirements:
*
* - input must fit into 152 bits
*/
function toInt152(int256 value) internal pure returns (int152 downcasted) {
downcasted = int152(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(152, value);
}
}
/**
* @dev Returns the downcasted int144 from int256, reverting on
* overflow (when the input is less than smallest int144 or
* greater than largest int144).
*
* Counterpart to Solidity's `int144` operator.
*
* Requirements:
*
* - input must fit into 144 bits
*/
function toInt144(int256 value) internal pure returns (int144 downcasted) {
downcasted = int144(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(144, value);
}
}
/**
* @dev Returns the downcasted int136 from int256, reverting on
* overflow (when the input is less than smallest int136 or
* greater than largest int136).
*
* Counterpart to Solidity's `int136` operator.
*
* Requirements:
*
* - input must fit into 136 bits
*/
function toInt136(int256 value) internal pure returns (int136 downcasted) {
downcasted = int136(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(136, value);
}
}
/**
* @dev Returns the downcasted int128 from int256, reverting on
* overflow (when the input is less than smallest int128 or
* greater than largest int128).
*
* Counterpart to Solidity's `int128` operator.
*
* Requirements:
*
* - input must fit into 128 bits
*/
function toInt128(int256 value) internal pure returns (int128 downcasted) {
downcasted = int128(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(128, value);
}
}
/**
* @dev Returns the downcasted int120 from int256, reverting on
* overflow (when the input is less than smallest int120 or
* greater than largest int120).
*
* Counterpart to Solidity's `int120` operator.
*
* Requirements:
*
* - input must fit into 120 bits
*/
function toInt120(int256 value) internal pure returns (int120 downcasted) {
downcasted = int120(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(120, value);
}
}
/**
* @dev Returns the downcasted int112 from int256, reverting on
* overflow (when the input is less than smallest int112 or
* greater than largest int112).
*
* Counterpart to Solidity's `int112` operator.
*
* Requirements:
*
* - input must fit into 112 bits
*/
function toInt112(int256 value) internal pure returns (int112 downcasted) {
downcasted = int112(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(112, value);
}
}
/**
* @dev Returns the downcasted int104 from int256, reverting on
* overflow (when the input is less than smallest int104 or
* greater than largest int104).
*
* Counterpart to Solidity's `int104` operator.
*
* Requirements:
*
* - input must fit into 104 bits
*/
function toInt104(int256 value) internal pure returns (int104 downcasted) {
downcasted = int104(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(104, value);
}
}
/**
* @dev Returns the downcasted int96 from int256, reverting on
* overflow (when the input is less than smallest int96 or
* greater than largest int96).
*
* Counterpart to Solidity's `int96` operator.
*
* Requirements:
*
* - input must fit into 96 bits
*/
function toInt96(int256 value) internal pure returns (int96 downcasted) {
downcasted = int96(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(96, value);
}
}
/**
* @dev Returns the downcasted int88 from int256, reverting on
* overflow (when the input is less than smallest int88 or
* greater than largest int88).
*
* Counterpart to Solidity's `int88` operator.
*
* Requirements:
*
* - input must fit into 88 bits
*/
function toInt88(int256 value) internal pure returns (int88 downcasted) {
downcasted = int88(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(88, value);
}
}
/**
* @dev Returns the downcasted int80 from int256, reverting on
* overflow (when the input is less than smallest int80 or
* greater than largest int80).
*
* Counterpart to Solidity's `int80` operator.
*
* Requirements:
*
* - input must fit into 80 bits
*/
function toInt80(int256 value) internal pure returns (int80 downcasted) {
downcasted = int80(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(80, value);
}
}
/**
* @dev Returns the downcasted int72 from int256, reverting on
* overflow (when the input is less than smallest int72 or
* greater than largest int72).
*
* Counterpart to Solidity's `int72` operator.
*
* Requirements:
*
* - input must fit into 72 bits
*/
function toInt72(int256 value) internal pure returns (int72 downcasted) {
downcasted = int72(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(72, value);
}
}
/**
* @dev Returns the downcasted int64 from int256, reverting on
* overflow (when the input is less than smallest int64 or
* greater than largest int64).
*
* Counterpart to Solidity's `int64` operator.
*
* Requirements:
*
* - input must fit into 64 bits
*/
function toInt64(int256 value) internal pure returns (int64 downcasted) {
downcasted = int64(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(64, value);
}
}
/**
* @dev Returns the downcasted int56 from int256, reverting on
* overflow (when the input is less than smallest int56 or
* greater than largest int56).
*
* Counterpart to Solidity's `int56` operator.
*
* Requirements:
*
* - input must fit into 56 bits
*/
function toInt56(int256 value) internal pure returns (int56 downcasted) {
downcasted = int56(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(56, value);
}
}
/**
* @dev Returns the downcasted int48 from int256, reverting on
* overflow (when the input is less than smallest int48 or
* greater than largest int48).
*
* Counterpart to Solidity's `int48` operator.
*
* Requirements:
*
* - input must fit into 48 bits
*/
function toInt48(int256 value) internal pure returns (int48 downcasted) {
downcasted = int48(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(48, value);
}
}
/**
* @dev Returns the downcasted int40 from int256, reverting on
* overflow (when the input is less than smallest int40 or
* greater than largest int40).
*
* Counterpart to Solidity's `int40` operator.
*
* Requirements:
*
* - input must fit into 40 bits
*/
function toInt40(int256 value) internal pure returns (int40 downcasted) {
downcasted = int40(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(40, value);
}
}
/**
* @dev Returns the downcasted int32 from int256, reverting on
* overflow (when the input is less than smallest int32 or
* greater than largest int32).
*
* Counterpart to Solidity's `int32` operator.
*
* Requirements:
*
* - input must fit into 32 bits
*/
function toInt32(int256 value) internal pure returns (int32 downcasted) {
downcasted = int32(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(32, value);
}
}
/**
* @dev Returns the downcasted int24 from int256, reverting on
* overflow (when the input is less than smallest int24 or
* greater than largest int24).
*
* Counterpart to Solidity's `int24` operator.
*
* Requirements:
*
* - input must fit into 24 bits
*/
function toInt24(int256 value) internal pure returns (int24 downcasted) {
downcasted = int24(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(24, value);
}
}
/**
* @dev Returns the downcasted int16 from int256, reverting on
* overflow (when the input is less than smallest int16 or
* greater than largest int16).
*
* Counterpart to Solidity's `int16` operator.
*
* Requirements:
*
* - input must fit into 16 bits
*/
function toInt16(int256 value) internal pure returns (int16 downcasted) {
downcasted = int16(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(16, value);
}
}
/**
* @dev Returns the downcasted int8 from int256, reverting on
* overflow (when the input is less than smallest int8 or
* greater than largest int8).
*
* Counterpart to Solidity's `int8` operator.
*
* Requirements:
*
* - input must fit into 8 bits
*/
function toInt8(int256 value) internal pure returns (int8 downcasted) {
downcasted = int8(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(8, value);
}
}
/**
* @dev Converts an unsigned uint256 into a signed int256.
*
* Requirements:
*
* - input must be less than or equal to maxInt256.
*/
function toInt256(uint256 value) internal pure returns (int256) {
// Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive
if (value > uint256(type(int256).max)) {
revert SafeCastOverflowedUintToInt(value);
}
return int256(value);
}
/**
* @dev Cast a boolean (false or true) to a uint256 (0 or 1) with no jump.
*/
function toUint(bool b) internal pure returns (uint256 u) {
assembly ("memory-safe") {
u := iszero(iszero(b))
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/Errors.sol)
pragma solidity ^0.8.20;
/**
* @dev Collection of common custom errors used in multiple contracts
*
* IMPORTANT: Backwards compatibility is not guaranteed in future versions of the library.
* It is recommended to avoid relying on the error API for critical functionality.
*
* _Available since v5.1._
*/
library Errors {
/**
* @dev The ETH balance of the account is not enough to perform the operation.
*/
error InsufficientBalance(uint256 balance, uint256 needed);
/**
* @dev A call to an address target failed. The target may have reverted.
*/
error FailedCall();
/**
* @dev The deployment failed.
*/
error FailedDeployment();
/**
* @dev A necessary precompile is missing.
*/
error MissingPrecompile(address);
}{
"remappings": [
"@openzeppelin-foundry-upgradeable/=libs/@openzeppelin-foundry-upgradeable/",
"@openzeppelin-upgradeable/=libs/@openzeppelin-upgradeable/",
"@openzeppelin/=libs/@openzeppelin/",
"forge-std/=libs/forge-std/",
"solady/=libs/solady/",
"solidity-bytes-utils/=libs/solidity-bytes-utils/contracts/",
"solidity-stringutils/=libs/solidity-stringutils/src/"
],
"optimizer": {
"enabled": true,
"runs": 10000
},
"metadata": {
"useLiteralContent": false,
"bytecodeHash": "none",
"appendCBOR": false
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"evmVersion": "prague",
"viaIR": true
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_ibcHandler","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"authority","type":"address"}],"name":"AccessManagedInvalidAuthority","type":"error"},{"inputs":[{"internalType":"address","name":"caller","type":"address"},{"internalType":"uint32","name":"delay","type":"uint32"}],"name":"AccessManagedRequiredDelay","type":"error"},{"inputs":[{"internalType":"address","name":"caller","type":"address"}],"name":"AccessManagedUnauthorized","type":"error"},{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"AddressEmptyCode","type":"error"},{"inputs":[{"internalType":"address","name":"implementation","type":"address"}],"name":"ERC1967InvalidImplementation","type":"error"},{"inputs":[],"name":"ERC1967NonPayable","type":"error"},{"inputs":[],"name":"EnforcedPause","type":"error"},{"inputs":[],"name":"ErrClientFrozen","type":"error"},{"inputs":[],"name":"ErrHeaderExpired","type":"error"},{"inputs":[],"name":"ErrInvalidInitialConsensusState","type":"error"},{"inputs":[],"name":"ErrInvalidMisbehaviour","type":"error"},{"inputs":[],"name":"ErrInvalidMisbehaviourHeadersSequence","type":"error"},{"inputs":[],"name":"ErrInvalidUntrustedValidatorsHash","type":"error"},{"inputs":[],"name":"ErrInvalidZKP","type":"error"},{"inputs":[],"name":"ErrMaxClockDriftExceeded","type":"error"},{"inputs":[],"name":"ErrNotIBC","type":"error"},{"inputs":[],"name":"ErrTrustedConsensusStateNotFound","type":"error"},{"inputs":[],"name":"ErrUntrustedHeightLTETrustedHeight","type":"error"},{"inputs":[],"name":"ErrUntrustedTimestampLTETrustedTimestamp","type":"error"},{"inputs":[],"name":"ExpectedPause","type":"error"},{"inputs":[],"name":"FailedCall","type":"error"},{"inputs":[],"name":"InvalidInitialization","type":"error"},{"inputs":[],"name":"NotInitializing","type":"error"},{"inputs":[],"name":"UUPSUnauthorizedCallContext","type":"error"},{"inputs":[{"internalType":"bytes32","name":"slot","type":"bytes32"}],"name":"UUPSUnsupportedProxiableUUID","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"authority","type":"address"}],"name":"AuthorityUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"version","type":"uint64"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"implementation","type":"address"}],"name":"Upgraded","type":"event"},{"inputs":[],"name":"IBC_HANDLER","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"UPGRADE_INTERFACE_VERSION","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"authority","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint32","name":"clientId","type":"uint32"},{"internalType":"bytes","name":"clientStateBytes","type":"bytes"},{"internalType":"bytes","name":"consensusStateBytes","type":"bytes"},{"internalType":"address","name":"","type":"address"}],"name":"createClient","outputs":[{"components":[{"internalType":"bytes32","name":"clientStateCommitment","type":"bytes32"},{"internalType":"bytes32","name":"consensusStateCommitment","type":"bytes32"},{"internalType":"uint64","name":"height","type":"uint64"}],"internalType":"struct ConsensusStateUpdate","name":"update","type":"tuple"},{"internalType":"string","name":"counterpartyChainId","type":"string"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint32","name":"clientId","type":"uint32"},{"internalType":"bytes","name":"clientStateBytes","type":"bytes"},{"internalType":"bytes","name":"consensusStateBytes","type":"bytes"}],"name":"forceUpdateClient","outputs":[{"components":[{"internalType":"bytes32","name":"clientStateCommitment","type":"bytes32"},{"internalType":"bytes32","name":"consensusStateCommitment","type":"bytes32"},{"internalType":"uint64","name":"height","type":"uint64"}],"internalType":"struct ConsensusStateUpdate","name":"","type":"tuple"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"clientId","type":"uint32"}],"name":"getClientState","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"clientId","type":"uint32"},{"internalType":"uint64","name":"height","type":"uint64"}],"name":"getConsensusState","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"clientId","type":"uint32"}],"name":"getLatestHeight","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"clientId","type":"uint32"},{"internalType":"uint64","name":"height","type":"uint64"}],"name":"getTimestampAtHeight","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"gitRev","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"authority","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"isConsumingScheduledOp","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"clientId","type":"uint32"}],"name":"isFrozen","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint32","name":"clientId","type":"uint32"},{"internalType":"bytes","name":"clientMessageBytes","type":"bytes"},{"internalType":"address","name":"","type":"address"}],"name":"misbehaviour","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"proxiableUUID","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newAuthority","type":"address"}],"name":"setAuthority","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint32","name":"clientId","type":"uint32"},{"internalType":"bytes","name":"clientMessageBytes","type":"bytes"},{"internalType":"address","name":"","type":"address"}],"name":"updateClient","outputs":[{"components":[{"internalType":"bytes32","name":"clientStateCommitment","type":"bytes32"},{"internalType":"bytes32","name":"consensusStateCommitment","type":"bytes32"},{"internalType":"uint64","name":"height","type":"uint64"}],"internalType":"struct ConsensusStateUpdate","name":"","type":"tuple"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"upgradeToAndCall","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint32","name":"clientId","type":"uint32"},{"internalType":"uint64","name":"height","type":"uint64"},{"internalType":"bytes","name":"proof","type":"bytes"},{"internalType":"bytes","name":"path","type":"bytes"},{"internalType":"bytes","name":"value","type":"bytes"}],"name":"verifyMembership","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"clientId","type":"uint32"},{"internalType":"uint64","name":"height","type":"uint64"},{"internalType":"bytes","name":"proof","type":"bytes"},{"internalType":"bytes","name":"path","type":"bytes"}],"name":"verifyNonMembership","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"zkpBytes","type":"bytes"},{"internalType":"bytes31","name":"chainId","type":"bytes31"},{"internalType":"bytes32","name":"trustedValidatorsHash","type":"bytes32"},{"components":[{"internalType":"uint64","name":"height","type":"uint64"},{"internalType":"uint64","name":"secs","type":"uint64"},{"internalType":"uint64","name":"nanos","type":"uint64"},{"internalType":"bytes32","name":"validatorsHash","type":"bytes32"},{"internalType":"bytes32","name":"nextValidatorsHash","type":"bytes32"},{"internalType":"bytes32","name":"appHash","type":"bytes32"}],"internalType":"struct SignedHeader","name":"header","type":"tuple"}],"name":"verifyZKP","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
60c03461011e57601f614b9538819003918201601f19168301916001600160401b038311848410176101225780849260209460405283398101031261011e57516001600160a01b038116810361011e57306080525f516020614b755f395f51905f525460ff8160401c1661010f576002600160401b03196001600160401b038216016100b9575b5060a052604051614a3e90816101378239608051818181610b770152610d69015260a0518181816119cd0152611f6a0152f35b6001600160401b0319166001600160401b039081175f516020614b755f395f51905f52556040519081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d290602090a15f610086565b63f92ee8a960e01b5f5260045ffd5b5f80fd5b634e487b7160e01b5f52604160045260245ffdfe60806040526004361015610011575f80fd5b5f3560e01c80630d27062c146101945780632886a3a31461018f578063384a3c301461018a5780633f4ba83a146101855780633fd413de14610180578063446005b81461017b5780634f1ef2861461017657806352d1902d14610171578063553931741461016c5780635c975abb146101675780636659c7ac146101625780636d6f21201461015d5780637a9e5e4b146101585780638456cb59146101535780638f2a49301461014e5780638fb3603714610149578063a9f9396e14610144578063ad3cb1cc1461013f578063b4b525081461013a578063b6719c8914610135578063bf7e214f14610130578063c4d66de81461012b578063e079e299146101265763e9946fc314610121575f80fd5b6119f1565b6119a1565b61173e565b6116ec565b611696565b611632565b6115d3565b61153a565b6114a7565b611285565b6111ec565b611117565b6110c7565b610f4a565b610efd565b610e3b565b610d42565b610b1a565b61078b565b610608565b610537565b610368565b61027b565b6101cc565b5f9103126101a357565b5f80fd5b90601f19601f602080948051918291828752018686015e5f8582860101520116010190565b346101a3575f6003193601126101a3576102516040516101ed606082610a88565b602881527f373131336632363631303235383033303231663831396164643039393935666360208201527f653266353861626600000000000000000000000000000000000000000000000060408201526040519182916020835260208301906101a7565b0390f35b6004359063ffffffff821682036101a357565b6024359063ffffffff821682036101a357565b346101a35760206003193601126101a35763ffffffff610299610255565b165f525f6020526020600160405f20015460c01c604051908152f35b6004359073ffffffffffffffffffffffffffffffffffffffff821682036101a357565b6084359073ffffffffffffffffffffffffffffffffffffffff821682036101a357565b9181601f840112156101a35782359167ffffffffffffffff83116101a357602083818601950101116101a357565b80610358608092610365959467ffffffffffffffff604080928051855260208101516020860152015116910152565b81606082015201906101a7565b90565b346101a35760a06003193601126101a3576103816102b5565b5061038a610268565b60443567ffffffffffffffff81116101a3576103aa9036906004016102fb565b509060643567ffffffffffffffff81116101a3576103cc9036906004016102fb565b50916103d66102d8565b506103df611a56565b506103e8611f53565b6103f0611fba565b608081019067ffffffffffffffff8235610409816105f6565b16158015610515575b6104ed576104d36104d8926104838661047e61045f8861044b886104466104dd9c63ffffffff165f525f60205260405f2090565b611aac565b63ffffffff165f52600160205260405f2090565b61046885611a98565b67ffffffffffffffff165f5260205260405f2090565b611bbb565b6104b16104ab6104a661049e6104993688611c15565b61200d565b983690611c92565b612020565b91611a98565b906104ba610aab565b968752602087015267ffffffffffffffff166040860152565b611aa2565b612083565b9061025160405192839283610329565b7f920ed63f000000000000000000000000000000000000000000000000000000005f5260045ffd5b506105318435610524816105f6565b67ffffffffffffffff1690565b15610412565b346101a3575f6003193601126101a35761055136336121cf565b7fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f033005460ff8116156105ce5760ff19167fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f03300557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa6020604051338152a1005b7f8dfc202b000000000000000000000000000000000000000000000000000000005f5260045ffd5b67ffffffffffffffff8116036101a357565b346101a35760806003193601126101a357610621610255565b6024359061062e826105f6565b60443567ffffffffffffffff81116101a35761064e9036906004016102fb565b5060643567ffffffffffffffff81116101a35761066f9036906004016102fb565b9091610679611fba565b6106a38463ffffffff165f525f60205267ffffffffffffffff600160405f20015460801c16151590565b610732576102519461071b60016106ef63ffffffff610720981693845f525f602052600260405f200154945f528260205260405f209067ffffffffffffffff165f5260205260405f2090565b01549161070d6106fd611ccd565b9560405197889360208501611d15565b03601f198101865285610a88565b61249d565b60405190151581529081906020820190565b7fb3e34670000000000000000000000000000000000000000000000000000000005f5260045ffd5b61078990929192606081019367ffffffffffffffff604080928051855260208101516020860152015116910152565b565b346101a35760806003193601126101a3576107a46102b5565b506107ad610268565b60443567ffffffffffffffff81116101a3576107cd9036906004016102fb565b50906064359067ffffffffffffffff82116101a3576109726109f06104ab6104a66109e8610499610251986109e1610a129861047e6108136109d89c36906004016102fb565b509b8c9261081f611a56565b50610828611f53565b610830611fba565b63ffffffff81165f525f60205260405f20863561084c81610f3e565b60081c7fff000000000000000000000000000000000000000000000000000000000000008254161781556109ba600182016108c360208a013561088e816105f6565b829067ffffffffffffffff167fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000825416179055565b60408901356108d1816105f6565b7fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff6fffffffffffffffff000000000000000083549260401b16911617815561096761091e60608b01611a98565b82547fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff1660809190911b77ffffffffffffffff0000000000000000000000000000000016178255565b608089019e8f611a98565b77ffffffffffffffffffffffffffffffffffffffffffffffff7fffffffffffffffff00000000000000000000000000000000000000000000000083549260c01b169116179055565b600260a088013591015563ffffffff165f52600160205260405f2090565b6104688b611a98565b3690611c15565b953690611c92565b906109f9610aab565b938452602084015267ffffffffffffffff166040830152565b6040519182918261075a565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6060810190811067ffffffffffffffff821117610a6757604052565b610a1e565b60c0810190811067ffffffffffffffff821117610a6757604052565b90601f601f19910116810190811067ffffffffffffffff821117610a6757604052565b60405190610789606083610a88565b906107896040519283610a88565b67ffffffffffffffff8111610a6757601f01601f191660200190565b929192610af082610ac8565b91610afe6040519384610a88565b8294818452818301116101a3578281602093845f960137010152565b60406003193601126101a357610b2e6102b5565b60243567ffffffffffffffff81116101a357366023820112156101a357610b5f903690602481600401359101610ae4565b9073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016803014908115610d00575b50610cd857610bb136336121cf565b604051917f52d1902d00000000000000000000000000000000000000000000000000000000835260208360048173ffffffffffffffffffffffffffffffffffffffff86165afa5f9381610ca7575b50610c46577f4c9c8ce3000000000000000000000000000000000000000000000000000000005f5273ffffffffffffffffffffffffffffffffffffffff821660045260245ffd5b907f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc8303610c7a57610c7892506130a3565b005b7faa1d49a4000000000000000000000000000000000000000000000000000000005f52600483905260245ffd5b610cca91945060203d602011610cd1575b610cc28183610a88565b8101906124f9565b925f610bff565b503d610cb8565b7fe07c8dba000000000000000000000000000000000000000000000000000000005f5260045ffd5b905073ffffffffffffffffffffffffffffffffffffffff7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc541614155f610ba2565b346101a3575f6003193601126101a35773ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000163003610cd85760206040517f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc8152f35b60806003198201126101a35760043573ffffffffffffffffffffffffffffffffffffffff811681036101a3579160243563ffffffff811681036101a357916044359067ffffffffffffffff82116101a357610e16916004016102fb565b909160643573ffffffffffffffffffffffffffffffffffffffff811681036101a35790565b346101a357610e92610e4c36610db9565b5050929150610e59611f53565b610e61611fba565b63ffffffff81165f525f60205260405f209283610e8c610e818380611d56565b926020810190611d56565b9261257f565b15610ed55760010180547fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff16700100000000000000000000000000000000179055005b7fb1333bc8000000000000000000000000000000000000000000000000000000005f5260045ffd5b346101a3575f6003193601126101a357602060ff7fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f0330054166040519015158152f35b60ff198116036101a357565b346101a3576101206003193601126101a35760043567ffffffffffffffff81116101a357610f7c9036906004016102fb565b50602435610f8981610f3e565b6044359060c07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9c3601126101a35760205f61106e610100860194611062610fef604051610fea81610fdc8b8a83016126b7565b03601f198101835282610a88565b613253565b95610fdc610ffe610524611a74565b9361100a610524611a80565b611015610524611a8c565b60c43560e435916101043593604051998a9860081c8e8a019694929091610100989694928852602088015260408701526060860152608085015260a084015260c083015260e08201520190565b604051918280926126c1565b039060025afa156110c25761025192610720927effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff5f5116926110af6040610aba565b938452602084015261014082019161339d565b6121c4565b346101a35760206003193601126101a35763ffffffff6110e5610255565b165f525f6020526102516111036110fe60405f20611d89565b6127bb565b6040519182916020835260208301906101a7565b346101a35760206003193601126101a3576111306102b5565b73ffffffffffffffffffffffffffffffffffffffff7ff3177357ab46d8af007ab3fdb9af81da189e1068fefdc0073dca88a2cab40a00541633036111c057803b1561117e57610c7890612837565b73ffffffffffffffffffffffffffffffffffffffff907fc2f31e5e000000000000000000000000000000000000000000000000000000005f521660045260245ffd5b7f068ca9d8000000000000000000000000000000000000000000000000000000005f523360045260245ffd5b346101a3575f6003193601126101a35761120636336121cf565b61120e611fba565b600160ff197fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f033005416177fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f03300557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586020604051338152a1005b346101a35761129336610db9565b50509091506112a0611a56565b506112a9611f53565b6112b1611fba565b6112c88263ffffffff165f525f60205260405f2090565b600181018054939091608085901c67ffffffffffffffff16610732576104a66113bc61049983610524610a129761137f6102519b6113688a6113396113c29b8f6113336113449f6113279063ffffffff165f52600160205260405f2090565b61046860c08401611a98565b906129ca565b96819d919460c01c90565b67ffffffffffffffff84161161145c5763ffffffff165f52600160205260405f2090565b9067ffffffffffffffff165f5260205260405f2090565b809a611396610524835467ffffffffffffffff1690565b1561140957926113b19293608060a082013591013591612c27565b6113ca575b50611d89565b94611e0a565b6109f9610aab565b80547fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff167001000000000000000000000000000000001790555f6113b6565b9150608092611446919067ffffffffffffffff167fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000825416179055565b60a081013560018b015501356002890155611d89565b845477ffffffffffffffffffffffffffffffffffffffffffffffff1660c084901b7fffffffffffffffff0000000000000000000000000000000000000000000000001617855561044b565b346101a3575f6003193601126101a3577ff3177357ab46d8af007ab3fdb9af81da189e1068fefdc0073dca88a2cab40a005460a01c60ff16156115325760207f8fb36037000000000000000000000000000000000000000000000000000000005b7fffffffff0000000000000000000000000000000000000000000000000000000060405191168152f35b60205f611508565b346101a35760a06003193601126101a357611553610255565b60243561155f816105f6565b60443567ffffffffffffffff81116101a35761157f9036906004016102fb565b91909260643567ffffffffffffffff81116101a3576115a29036906004016102fb565b906084359467ffffffffffffffff86116101a357610251966115cb6107209736906004016102fb565b969095611e3c565b346101a3575f6003193601126101a3576102516040516115f4604082610a88565b600581527f352e302e3000000000000000000000000000000000000000000000000000000060208201526040519182916020835260208301906101a7565b346101a35760406003193601126101a35761025161110361169161168c611657610255565b63ffffffff60243591611669836105f6565b165f52600160205260405f209067ffffffffffffffff165f5260205260405f2090565b611e0a565b612c7c565b346101a35760206003193601126101a35760206116e26116b4610255565b6116bc611fba565b63ffffffff165f525f60205267ffffffffffffffff600160405f20015460801c16151590565b6040519015158152f35b346101a3575f6003193601126101a357602073ffffffffffffffffffffffffffffffffffffffff7ff3177357ab46d8af007ab3fdb9af81da189e1068fefdc0073dca88a2cab40a005416604051908152f35b346101a35760206003193601126101a3576117576102b5565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00549067ffffffffffffffff6117a660ff604085901c1615611798565b1590565b9367ffffffffffffffff1690565b1680159081611999575b600114908161198f575b159081611986575b5061195e57611843908261183a60017fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000007ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005416177ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0055565b6118e357611ed8565b61184957005b6118b47fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054167ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0055565b604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d290602090a1005b611959680100000000000000007fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005416177ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0055565b611ed8565b7ff92ee8a9000000000000000000000000000000000000000000000000000000005f5260045ffd5b9050155f6117c2565b303b1591506117ba565b8391506117b0565b346101a3575f6003193601126101a357602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b346101a35760406003193601126101a357602067ffffffffffffffff611a4c611a18610255565b63ffffffff60243591611a2a836105f6565b165f526001845260405f209067ffffffffffffffff165f5260205260405f2090565b5416604051908152f35b60405190611a6382610a4b565b5f6040838281528260208201520152565b606435610365816105f6565b608435610365816105f6565b60a435610365816105f6565b35610365816105f6565b3561036581610f3e565b9060a06002918035611abd81610f3e565b60081c7fff00000000000000000000000000000000000000000000000000000000000000855416178455611bb460018501611aff602084013561088e816105f6565b6040830135611b0d816105f6565b7fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff6fffffffffffffffff000000000000000083549260401b169116178155611b5c606084013561091e816105f6565b608083013590611b6b826105f6565b9077ffffffffffffffffffffffffffffffffffffffffffffffff7fffffffffffffffff00000000000000000000000000000000000000000000000083549260c01b169116179055565b0135910155565b906040600291611c048135611bcf816105f6565b859067ffffffffffffffff167fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000825416179055565b602081013560018501550135910155565b91908260c09103126101a357604051611c2d81610a6c565b60a08082948035611c3d81610f3e565b84526020810135611c4d816105f6565b60208501526040810135611c60816105f6565b60408501526060810135611c73816105f6565b60608501526080810135611c86816105f6565b60808501520135910152565b91908260609103126101a357604051611caa81610a4b565b60408082948035611cba816105f6565b8452602081013560208501520135910152565b60405190611cdc604083610a88565b600482527f7761736d000000000000000000000000000000000000000000000000000000006020830152565b908092918237015f815290565b909280926022947f0300000000000000000000000000000000000000000000000000000000000000845260018401525f60218401528483013701015f815290565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01813603018212156101a3570190565b90604051611d9681610a6c565b60a06002829460ff19815460081b168452611e03611df2600183015467ffffffffffffffff8116602088015267ffffffffffffffff808260401c1616604088015267ffffffffffffffff808260801c1616606088015260c01c90565b67ffffffffffffffff166080860152565b0154910152565b90604051611e1781610a4b565b60406002829467ffffffffffffffff8154168452600181015460208501520154910152565b969594925090611e4a611fba565b611e748763ffffffff165f525f60205267ffffffffffffffff600160405f20015460801c16151590565b61073257611eca6001611ebc63ffffffff611ecf9a1694855f525f602052600260405f200154955f528260205260405f209067ffffffffffffffff165f5260205260405f2090565b01549261070d6106fd611ccd565b613643565b61179481612c72565b611ef190611ee461371f565b611eec61371f565b612837565b611ef961371f565b611f0161371f565b611f0961371f565b60ff197fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f0330054167fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f0330055565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000163303611f9257565b7fe54f8f9d000000000000000000000000000000000000000000000000000000005f5260045ffd5b60ff7fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f033005416611fe557565b7fd93c0665000000000000000000000000000000000000000000000000000000005f5260045ffd5b612016906127bb565b6020815191012090565b61201690612c7c565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b905f5b60ff811690601f82108015612108577fff0000000000000000000000000000000000000000000000000000000000000085841a60f81b16159081612100575b50156120e1575060ff81146120dc57600101612086565b612056565b929050604051926040840160405280601f03845260031b1b6020830152565b90505f6120c5565b612029565b906004116101a35790600490565b919091357fffffffff000000000000000000000000000000000000000000000000000000008116926004811061214f575050565b7fffffffff00000000000000000000000000000000000000000000000000000000929350829060040360031b1b161690565b9183606094601f9273ffffffffffffffffffffffffffffffffffffffff601f199516865260406020870152816040870152868601375f8582860101520116010190565b6040513d5f823e3d90fd5b61222c6122107ff3177357ab46d8af007ab3fdb9af81da189e1068fefdc0073dca88a2cab40a005473ffffffffffffffffffffffffffffffffffffffff1690565b61222361221d855f61210d565b9061211b565b90833091612cb6565b901561223757505050565b63ffffffff16156123fc576122c4740100000000000000000000000000000000000000007fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff7ff3177357ab46d8af007ab3fdb9af81da189e1068fefdc0073dca88a2cab40a005416177ff3177357ab46d8af007ab3fdb9af81da189e1068fefdc0073dca88a2cab40a0055565b6123216123086123087ff3177357ab46d8af007ab3fdb9af81da189e1068fefdc0073dca88a2cab40a005473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff1690565b91823b156101a357612367925f808094604051968795869485937f94c7d7ee00000000000000000000000000000000000000000000000000000000855260048501612181565b03925af180156110c2576123e2575b506107897fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff7ff3177357ab46d8af007ab3fdb9af81da189e1068fefdc0073dca88a2cab40a0054167ff3177357ab46d8af007ab3fdb9af81da189e1068fefdc0073dca88a2cab40a0055565b806123f05f6123f693610a88565b80610199565b5f612376565b7f068ca9d8000000000000000000000000000000000000000000000000000000005f5273ffffffffffffffffffffffffffffffffffffffff1660045260245ffd5b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81813603018212156101a3570190565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b8135939291368190037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa1018512156101a3576124e7946124e0602083018361243d565b9101612d7c565b60128110156124f4571590565b612470565b908160209103126101a3575190565b91909160a08060c083019467ffffffffffffffff8135612527816105f6565b16845267ffffffffffffffff6020820135612541816105f6565b16602085015267ffffffffffffffff604082013561255e816105f6565b16604085015260608101356060850152608081013560808501520135910152565b9061258983611a98565b67ffffffffffffffff61259e61052487611a98565b91161061268f578061260261260b926125fb6125ef6125da6125ce8863ffffffff165f52600160205260405f2090565b61046860c08b01611a98565b9663ffffffff165f52600160205260405f2090565b61046860c08a01611a98565b94866129ca565b939050856129ca565b905061261683611a98565b67ffffffffffffffff61262b61052487611a98565b91160361267357505060405161264981610fdc602082019485612508565b5190209060405161266281610fdc602082019485612508565b5190200361266e575f90565b600190565b67ffffffffffffffff925082919350169116111561266e575f90565b7f63520534000000000000000000000000000000000000000000000000000000005f5260045ffd5b6040809282370190565b805191908290602001825e015f815290565b90925f61277e602092611062610100860197610fdc612700610fdc610fea8c6040519283918c83016126b7565b9861270d61052486611a98565b9461271c6105248a8301611a98565b9061272c61052460408301611a98565b60608201359060a0608084013593013593604051998a9860081c8e8a019694929091610100989694928852602088015260408701526060860152608085015260a084015260c083015260e08201520190565b039060025afa156110c257610365927effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff5f5116926110af6040610aba565b60ff198151169067ffffffffffffffff6020820151169067ffffffffffffffff60408201511667ffffffffffffffff6060830151169060a067ffffffffffffffff6080850151169301519360405195602087015260408601526060850152608084015260a083015260c082015260c0815261036560e082610a88565b602073ffffffffffffffffffffffffffffffffffffffff7f2f658b440c35314f52658ea8a740e05b284cdc84dc9ae01e891f21b8933e7cad9216807fffffffffffffffffffffffff00000000000000000000000000000000000000007ff3177357ab46d8af007ab3fdb9af81da189e1068fefdc0073dca88a2cab40a005416177ff3177357ab46d8af007ab3fdb9af81da189e1068fefdc0073dca88a2cab40a0055604051908152a1565b67ffffffffffffffff633b9aca009116029067ffffffffffffffff82169182036120dc57565b67ffffffffffffffff60019116019067ffffffffffffffff82116120dc57565b9067ffffffffffffffff8091169116019067ffffffffffffffff82116120dc57565b90633b9aca00820291808304633b9aca0014901517156120dc57565b818102929181159184041417156120dc57565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1813603018212156101a3570180359067ffffffffffffffff82116101a3576020019181360383136101a357565b9291906129df815467ffffffffffffffff1690565b9367ffffffffffffffff8516928315612bff576129fb82611a98565b93612a0860c08401611a98565b9367ffffffffffffffff86169167ffffffffffffffff8616831115612bd757612a50612a3e612a3960208801611a98565b6128e2565b612a4a60408801611a98565b90612928565b9867ffffffffffffffff8a1691821115612baf57612a706105244261294a565b90612a9282600188015492612a8c8467ffffffffffffffff1690565b9061361b565b612b8757612ab0916105249160401c67ffffffffffffffff16612a4a565b1115612b5f576105246002612ac792015495612908565b14612b25575b90612af59261179492612aef612ae660e0850185612979565b50915460081b90565b906126d3565b612afd579190565b7f396df4ec000000000000000000000000000000000000000000000000000000005f5260045ffd5b9082606082013503612b375790612acd565b7f895cf0ce000000000000000000000000000000000000000000000000000000005f5260045ffd5b7f4ccc303c000000000000000000000000000000000000000000000000000000005f5260045ffd5b7f6c4c87b6000000000000000000000000000000000000000000000000000000005f5260045ffd5b7f14a286e4000000000000000000000000000000000000000000000000000000005f5260045ffd5b7ff97b0922000000000000000000000000000000000000000000000000000000005f5260045ffd5b7f09128dc8000000000000000000000000000000000000000000000000000000005f5260045ffd5b835467ffffffffffffffff9182169116148015939190612c63575b508215612c54575b505061266e575f90565b60020154141590505f80612c4a565b6001820154141592505f612c42565b600911156124f457565b67ffffffffffffffff8151169060406020820151910151906040519260208401526040830152606082015260608152610365608082610a88565b5f9060409295939582967fffffffff00000000000000000000000000000000000000000000000000000000849773ffffffffffffffffffffffffffffffffffffffff8751938160208601967fb700961300000000000000000000000000000000000000000000000000000000885216602486015216604484015216606482015260648152612d45608482610a88565b8380528360205251915afa612d5657565b9150505f51906020518060201c150290565b600511156124f457565b600611156124f457565b93919293612d8981613776565b612d9581959295612d68565b6130985783612dac92612da66137d0565b9061384e565b612db581612c72565b80612f485750612dc481613afb565b612dd081969296612d68565b612f3e57612e009261070d92612dfb612de7613bcc565b926040519586916020830160209181520190565b613bf6565b612e0981612d72565b80612e1d575003612e18575f90565b600990565b809250612e2a9150612d72565b60018103612e385750600490565b612e4181612d72565b60028103612e4f5750600590565b612e5881612d72565b60038103612e665750600690565b612e6f81612d72565b60048103612e7d5750600790565b80612e89600592612d72565b14612f39576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152605660248201527f766572696679436861696e65644e6f6e4d656d626572736869703a206e6f6e2060448201527f65786861757374697665207061747465726e206d61746368696e67206f6e205660648201527f65726966794e6f6e4578697374656e63654572726f7200000000000000000000608482015260a490fd5b600890565b5050505050600390565b9350505050612f5681612c72565b60018103612f645750600a90565b612f6d81612c72565b60038103612f7b5750600c90565b612f8481612c72565b60048103612f925750600d90565b612f9b81612c72565b60058103612fa95750600e90565b612fb281612c72565b60068103612fc05750600f90565b612fc981612c72565b60078103612fd75750601090565b80612fe3600892612c72565b14613093576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152605660248201527f766572696679436861696e65644e6f6e4d656d626572736869703a206e6f6e2060448201527f65786861757374697665207061747465726e206d61746368696e67206f6e205660648201527f65726966794e6f6e4578697374656e63654572726f7200000000000000000000608482015260a490fd5b601190565b505050505050600390565b90813b156131925773ffffffffffffffffffffffffffffffffffffffff8216807fffffffffffffffffffffffff00000000000000000000000000000000000000007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5416177f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc557fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b5f80a28051156131615761315e91613c73565b50565b50503461316a57565b7fb398979f000000000000000000000000000000000000000000000000000000005f5260045ffd5b73ffffffffffffffffffffffffffffffffffffffff827f4c9c8ce3000000000000000000000000000000000000000000000000000000005f521660045260245ffd5b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82019182116120dc57565b811561320b570690565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b90600182018092116120dc57565b919082018092116120dc57565b61339861036591610fdc61336e6040519261326f60c085610a88565b608884527f1f333139281e100f5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c60208501527f5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c60408501527f5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c60608501527f5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c60808501527f5c5c5c5c5c5c5c5c00000000000000000000000000000000000000000000000060a0850152610fdc61335a61333f613cb7565b926040519283916133546020840180976126c1565b906126c1565b519020604051928391602083019586613d8a565b5190207f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000090613201565b613238565b926133a89082613d9e565b939192909215613612576133bf9161179491613eff565b61360b576101006040519384377f07b8dbefa90bde075a26318e5066db729155514e3c06b888d4e03c56d82c97e66101008401527f02aca5d2a73f8d34e4b26eee3932365e6526c8d5e2f3347d679c2cb1867104dc6101208401527f2edb19cbb2b6ad0c98fdd7d1845500c26e497dc35e4cdc1cb02cc65dc4ba1bf26101408401527f1696ccafaefe49a5d8bad8e79630e19b25e5392a203aff0042d0216f254806f56101608401527f245229d9b076b3c0e8a4d70bde8c1cccffa08a9fae7557b165b3b0dbd653e2c76101808401527f253ec85988dbb84e46e94b5efa3373b47a000b4ac6c86b2d4b798d274a1823026101a08401527f07090a82e8fabbd39299be24705b92cf208ee8b3487f6f2b39ff27978a29a1db6101c08401527f2424bcc1f60a5472685fd50705b2809626e170120acaf441e133a2bd5e61d2446101e08401527f25833b15e156ae01f2741f4f4120ddb466c52eb83a959f79eb99b23caa7fbf1d6102008401527f04ddc8d30d5c438ca34091c5d2c6ded571382cba2b3c4fdc4222df2938b4e51e6102208401526102408301526102608201527f198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c26102808201527f1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed6102a08201527f275dc4a288d1afb3cbb1ac09187524c7db36395df7be3b99e673b13a075a65ec6102c08201527f1d9befcd05a5323e6da4d435f3b617cdb3af83285c2df711ef39c01571827f9d6102e08201526020816103008160085afa90511690565b5050505f90565b50505050505f90565b67ffffffffffffffff809193929316921682018092116120dc5767ffffffffffffffff161190565b91949093613659613654848061243d565b613afb565b61366581969296612d68565b613713576136919261368b61367a868061243d565b936136836137d0565b923691610ae4565b92613bf6565b61369a81612d72565b806137055750916136e993916136b76136d694602081019061243d565b6136e46136c2613bcc565b926040519687916020830160209181520190565b03601f198101875286610a88565b61416a565b6136f281612d72565b806136fc57505f90565b61036590614052565b925050506103659150614052565b50505050505050600290565b60ff7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005460401c161561374e57565b7fd7e6bcf8000000000000000000000000000000000000000000000000000000005f5260045ffd5b6020810161378c613787828461243d565b61420e565b156137c3575060408101906137a4613787838361243d565b156137b25750505f90600490565b6137bf916136549161243d565b9091565b613654906137bf9261243d565b6137d8611a56565b506040516137e581610a4b565b6021815260046020820152600c604082015290565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1813603018212156101a3570180359067ffffffffffffffff82116101a357602001918160051b360383136101a357565b9092916020820190613869613863838561243d565b80612979565b919094604085019561387e613863888861243d565b949093613891611794613787898b61243d565b613a6a575b6138a66117946137878b8b61243d565b6139f4575b5080159384806139ec575b6139dd57851595861591826139c6575b50506139b857831591826139a2575b50509050613997571561392857505091818361391261390061390a6139006117949761391a9961243d565b60608101906137fa565b94909361243d565b939050614551565b613923575b5f90565b600690565b90929015613962575091818361394d61390061390a613900611794976139559961243d565b9390506144e6565b61395d575f90565b600790565b9261398d9361398561390061397d613900611794978761243d565b93909561243d565b9390926143e1565b1561391f57600890565b505050505050600590565b6139ae92505f93614288565b1315805f806138d5565b505050505050505050600490565b5f9250906139d49186614288565b12155f806138c6565b50505050505050505050600390565b5085156138b6565b613a499088613a038b8261243d565b918c613a438d613a3b613a31613a27613a1f613863858a61243d565b94909861243d565b6020810190612979565b9690923691610ae4565b943691610ae4565b9361416a565b613a5281612d72565b613a5c575f6138ab565b505050505050505050600290565b613a94613a77888a61243d565b89838d613a438c613a3b613a31613a27613a1f613863858a61243d565b613a9d81612d72565b156138965750505050505050505050600190565b600311156124f457565b91908110156121085760051b810135907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc1813603018212156101a3570190565b60408101613b098183612979565b905015613bc357613b1d613b3e9183612979565b90613b288480612979565b90613b366020870187612979565b9490936145fb565b919091613b4a81613ab1565b613bba5760608101613b5c81836137fa565b9190505f925b828410613b725750505050905f90565b90919293613b9390613b8e86613b8886866137fa565b90613abb565b6146aa565b949094613b9f81613ab1565b613bae57600101929190613b62565b50505050505f90600390565b50505f90600290565b50505f90600190565b613bd4611a56565b50604051613be181610a4b565b60208152600160208201526001604082015290565b929091613c0d613c068580612979565b3691610ae4565b60208151910120906020815191012003613c6b57613c31613c066020850185612979565b60208151910120906020815191012003613c6457613c4e91614700565b613c5781612d68565b613c5f575f90565b600390565b5050600290565b505050600190565b5f8061036593602081519101845af43d15613caf573d91613c9383610ac8565b92613ca16040519485610a88565b83523d5f602085013e614802565b606091614802565b60405190613cc660c083610a88565b608882527f363636363636363600000000000000000000000000000000000000000000000060a0837f75595b5342747a6536363636363636363636363636363636363636363636363660208201527f363636363636363636363636363636363636363636363636363636363636363660408201527f363636363636363636363636363636363636363636363636363636363636363660608201527f363636363636363636363636363636363636363636363636363636363636363660808201520152565b613d9790602093926126c1565b9081520190565b90916040519260408401907f2f5d8a3817f21d3e453573c90c3cc47b7ff235fad7bdfbd59bbd6ae5d153273e8552604060208601947f147fa22142b1fd86ce75fc87230a0feac8765d02938784dcfc828d17d7e7c432865283377f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000016040808760808160065afa937f2a81b98e1c997bd01a20893a08a46c6804493e838c1a0ff6c8c069ef5ab66b9a8152602060608901947f276938ada8075cec20d4d6a1f157ec94cc7ba6207c98576e98c1ad9d6378fb6f86527f0326e7d44688ce5903676b7d646e46a5938c8e5fd8cd54e4d5aa3300649f3cfc6001825160808d0199818b5288888860608160075afa92101616868d60808160065afa1616967f179496ce140df89ce35c5ee7fb496efdffda5e5d3b95ff9116e2e5df96b36ab7855252015180955260608160075afa9210161660408460808160065afa169251915190565b906040908180519384377f198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c2828401527f1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed60608401527f090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b60808401527f12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa60a084015260c08301377f07b8dbefa90bde075a26318e5066db729155514e3c06b888d4e03c56d82c97e66101008201527f02aca5d2a73f8d34e4b26eee3932365e6526c8d5e2f3347d679c2cb1867104dc6101208201527f2edb19cbb2b6ad0c98fdd7d1845500c26e497dc35e4cdc1cb02cc65dc4ba1bf26101408201527f1696ccafaefe49a5d8bad8e79630e19b25e5392a203aff0042d0216f254806f56101608201526020816101808160085afa90511690565b61405b81612d72565b600181036140695750600390565b61407281612d72565b600281036140805750600490565b61408981612d72565b600381036140975750600590565b6140a081612d72565b600481036140ae5750600690565b806140ba600592612d72565b1461395d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152605060248201527f766572696679436861696e65644d656d626572736869703a206e6f6e2065786860448201527f61757374697665207061747465726e206d61746368696e67206f6e205665726960648201527f66794578697374656e63654572726f7200000000000000000000000000000000608482015260a490fd5b929390919361417c613c068580612979565b60208151910120906020815191012003614205576141a0613c066020850185612979565b602081519101209060208151910120036141fd576141be9082614700565b6141c781612d68565b6141f6576141d490613afb565b6141dd81612d68565b6141ef57036141ea575f90565b600590565b5050600490565b5050600390565b505050600290565b50505050600190565b6142188180612979565b905061425d5761422b6020820182612979565b905061425d5761423e6040820182612979565b905061425d578060606142529201906137fa565b905061391f57600190565b505f90565b908151811015612108570160200190565b90156121085790565b90821015612108570190565b805180841190841802831892918391905f5b8381106142dd57505051116142d657116142b2575f90565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90565b5050600190565b909192506143146142ee8285614262565b517fff000000000000000000000000000000000000000000000000000000000000001690565b7fff0000000000000000000000000000000000000000000000000000000000000061439161436c61434685898861427c565b357fff000000000000000000000000000000000000000000000000000000000000001690565b7fff000000000000000000000000000000000000000000000000000000000000001690565b9116818110156143c657505050505050507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90565b116143d7576001019084929161429a565b5050505050600190565b929390916143ee816131d4565b926143f8836131d4565b935b61440b613c06613863838686613abb565b60208151910120614423613c0661386388888c613abb565b6020815191012014806144af575b61449757614458611794614446838686613abb565b61445188888c613abb565b90896148a5565b61448c5761446a9261179492876144e6565b6144845761447b9361179493614551565b61391f57600190565b505050505f90565b505050505050505f90565b6144a36144a9916131d4565b946131d4565b936143fa565b506144c1613c06613a27838686613abb565b602081519101206144d9613c06613a2788888c613abb565b6020815191012014614431565b80519060208101518201908183116120dc57604081015183018093116120dc575115600117156120dc575f5b85811061452457505050505050600190565b61453a5f8484614535858a8a613abb565b6148f6565b1561454757600101614512565b5050505050505f90565b919091805115600117156120dc57602081015160408201519151925f5b8681106145815750505050505050600190565b61459285858561453585878c613abb565b1561448c5760010161456e565b906145a982610ac8565b6145b66040519182610a88565b828152601f196145c68294610ac8565b0190602036910137565b8593836145ee9260209a999795613d979995823701905f82526126c1565b91823701905f82526126c1565b949390919293841561469d578015614690575f60209161462261461d88614957565b61459f565b9361462d8589614976565b5061463d60405180938193611d08565b039060025afa156110c257602094610fdc61467f94611062935f9788519261466661461d61493b565b92614670846149b6565b506040519889978d89016145d0565b039060025afa156110c2575f805191565b5050505050505f90600290565b5050505050505f90600190565b61467f6146d061106260205f948180976146c48380612979565b96909383810190612979565b80929188604051998a9787890137860192858401526040830137010186838201520301601f198101835282610a88565b906040820161470f8184612979565b905015613c6b5761474d6143466147477fff000000000000000000000000000000000000000000000000000000000000009386612979565b90614273565b16613c64576147626040820151825190613246565b606083019261477184826137fa565b9490505f5b858110614787575050505050505f90565b61479581613b8884866137fa565b846147a08280612979565b90506020880151119182156147e6575b82156147d0575b50506147c557600101614776565b505050505050600290565b6147dc91925080612979565b905011845f6147b7565b91506147fb61436c6143466147478580612979565b15916147b0565b9061483f575080511561481757805190602001fd5b7fd6bda275000000000000000000000000000000000000000000000000000000005f5260045ffd5b81511580614892575b614850575090565b73ffffffffffffffffffffffffffffffffffffffff907f9996b315000000000000000000000000000000000000000000000000000000005f521660045260245ffd5b50803b15614848565b600211156124f457565b906148b090826149c6565b92909160028410156124f45783614484576148d6916148ce916149c6565b91909361489b565b6148df8161489b565b6148f0576148ec90613238565b1490565b50505f90565b91906149028380612979565b905010908115614926575b506148f057806020614920920190612979565b90501490565b90506149328280612979565b9050115f61490d565b60015f805b614948575090565b60019091019060071c80614940565b60019060071c805b614967575090565b60019091019060071c8061495f565b91909160205f9301607f8216915b60071c9182156149aa576001918291608017815301930190607f81169093909193614984565b90600193949250530190565b5f919082906020908101906149aa565b5f5b600281106149da575050505f90600190565b6149e5825182612966565b602083015181018082116120dc57604084015182018092116120dc578260010390600182116120dc57600192614a20614a2793875190612966565b91876148f6565b151514614a36576001016149c8565b915050905f9056f0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00000000000000000000000000ee4ea8d358473f0fcebf0329feed95d56e8c04d7
Deployed Bytecode
0x60806040526004361015610011575f80fd5b5f3560e01c80630d27062c146101945780632886a3a31461018f578063384a3c301461018a5780633f4ba83a146101855780633fd413de14610180578063446005b81461017b5780634f1ef2861461017657806352d1902d14610171578063553931741461016c5780635c975abb146101675780636659c7ac146101625780636d6f21201461015d5780637a9e5e4b146101585780638456cb59146101535780638f2a49301461014e5780638fb3603714610149578063a9f9396e14610144578063ad3cb1cc1461013f578063b4b525081461013a578063b6719c8914610135578063bf7e214f14610130578063c4d66de81461012b578063e079e299146101265763e9946fc314610121575f80fd5b6119f1565b6119a1565b61173e565b6116ec565b611696565b611632565b6115d3565b61153a565b6114a7565b611285565b6111ec565b611117565b6110c7565b610f4a565b610efd565b610e3b565b610d42565b610b1a565b61078b565b610608565b610537565b610368565b61027b565b6101cc565b5f9103126101a357565b5f80fd5b90601f19601f602080948051918291828752018686015e5f8582860101520116010190565b346101a3575f6003193601126101a3576102516040516101ed606082610a88565b602881527f373131336632363631303235383033303231663831396164643039393935666360208201527f653266353861626600000000000000000000000000000000000000000000000060408201526040519182916020835260208301906101a7565b0390f35b6004359063ffffffff821682036101a357565b6024359063ffffffff821682036101a357565b346101a35760206003193601126101a35763ffffffff610299610255565b165f525f6020526020600160405f20015460c01c604051908152f35b6004359073ffffffffffffffffffffffffffffffffffffffff821682036101a357565b6084359073ffffffffffffffffffffffffffffffffffffffff821682036101a357565b9181601f840112156101a35782359167ffffffffffffffff83116101a357602083818601950101116101a357565b80610358608092610365959467ffffffffffffffff604080928051855260208101516020860152015116910152565b81606082015201906101a7565b90565b346101a35760a06003193601126101a3576103816102b5565b5061038a610268565b60443567ffffffffffffffff81116101a3576103aa9036906004016102fb565b509060643567ffffffffffffffff81116101a3576103cc9036906004016102fb565b50916103d66102d8565b506103df611a56565b506103e8611f53565b6103f0611fba565b608081019067ffffffffffffffff8235610409816105f6565b16158015610515575b6104ed576104d36104d8926104838661047e61045f8861044b886104466104dd9c63ffffffff165f525f60205260405f2090565b611aac565b63ffffffff165f52600160205260405f2090565b61046885611a98565b67ffffffffffffffff165f5260205260405f2090565b611bbb565b6104b16104ab6104a661049e6104993688611c15565b61200d565b983690611c92565b612020565b91611a98565b906104ba610aab565b968752602087015267ffffffffffffffff166040860152565b611aa2565b612083565b9061025160405192839283610329565b7f920ed63f000000000000000000000000000000000000000000000000000000005f5260045ffd5b506105318435610524816105f6565b67ffffffffffffffff1690565b15610412565b346101a3575f6003193601126101a35761055136336121cf565b7fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f033005460ff8116156105ce5760ff19167fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f03300557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa6020604051338152a1005b7f8dfc202b000000000000000000000000000000000000000000000000000000005f5260045ffd5b67ffffffffffffffff8116036101a357565b346101a35760806003193601126101a357610621610255565b6024359061062e826105f6565b60443567ffffffffffffffff81116101a35761064e9036906004016102fb565b5060643567ffffffffffffffff81116101a35761066f9036906004016102fb565b9091610679611fba565b6106a38463ffffffff165f525f60205267ffffffffffffffff600160405f20015460801c16151590565b610732576102519461071b60016106ef63ffffffff610720981693845f525f602052600260405f200154945f528260205260405f209067ffffffffffffffff165f5260205260405f2090565b01549161070d6106fd611ccd565b9560405197889360208501611d15565b03601f198101865285610a88565b61249d565b60405190151581529081906020820190565b7fb3e34670000000000000000000000000000000000000000000000000000000005f5260045ffd5b61078990929192606081019367ffffffffffffffff604080928051855260208101516020860152015116910152565b565b346101a35760806003193601126101a3576107a46102b5565b506107ad610268565b60443567ffffffffffffffff81116101a3576107cd9036906004016102fb565b50906064359067ffffffffffffffff82116101a3576109726109f06104ab6104a66109e8610499610251986109e1610a129861047e6108136109d89c36906004016102fb565b509b8c9261081f611a56565b50610828611f53565b610830611fba565b63ffffffff81165f525f60205260405f20863561084c81610f3e565b60081c7fff000000000000000000000000000000000000000000000000000000000000008254161781556109ba600182016108c360208a013561088e816105f6565b829067ffffffffffffffff167fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000825416179055565b60408901356108d1816105f6565b7fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff6fffffffffffffffff000000000000000083549260401b16911617815561096761091e60608b01611a98565b82547fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff1660809190911b77ffffffffffffffff0000000000000000000000000000000016178255565b608089019e8f611a98565b77ffffffffffffffffffffffffffffffffffffffffffffffff7fffffffffffffffff00000000000000000000000000000000000000000000000083549260c01b169116179055565b600260a088013591015563ffffffff165f52600160205260405f2090565b6104688b611a98565b3690611c15565b953690611c92565b906109f9610aab565b938452602084015267ffffffffffffffff166040830152565b6040519182918261075a565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6060810190811067ffffffffffffffff821117610a6757604052565b610a1e565b60c0810190811067ffffffffffffffff821117610a6757604052565b90601f601f19910116810190811067ffffffffffffffff821117610a6757604052565b60405190610789606083610a88565b906107896040519283610a88565b67ffffffffffffffff8111610a6757601f01601f191660200190565b929192610af082610ac8565b91610afe6040519384610a88565b8294818452818301116101a3578281602093845f960137010152565b60406003193601126101a357610b2e6102b5565b60243567ffffffffffffffff81116101a357366023820112156101a357610b5f903690602481600401359101610ae4565b9073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000f2b24b085080cef91f7bffdc6358fe054999e15f16803014908115610d00575b50610cd857610bb136336121cf565b604051917f52d1902d00000000000000000000000000000000000000000000000000000000835260208360048173ffffffffffffffffffffffffffffffffffffffff86165afa5f9381610ca7575b50610c46577f4c9c8ce3000000000000000000000000000000000000000000000000000000005f5273ffffffffffffffffffffffffffffffffffffffff821660045260245ffd5b907f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc8303610c7a57610c7892506130a3565b005b7faa1d49a4000000000000000000000000000000000000000000000000000000005f52600483905260245ffd5b610cca91945060203d602011610cd1575b610cc28183610a88565b8101906124f9565b925f610bff565b503d610cb8565b7fe07c8dba000000000000000000000000000000000000000000000000000000005f5260045ffd5b905073ffffffffffffffffffffffffffffffffffffffff7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc541614155f610ba2565b346101a3575f6003193601126101a35773ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000f2b24b085080cef91f7bffdc6358fe054999e15f163003610cd85760206040517f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc8152f35b60806003198201126101a35760043573ffffffffffffffffffffffffffffffffffffffff811681036101a3579160243563ffffffff811681036101a357916044359067ffffffffffffffff82116101a357610e16916004016102fb565b909160643573ffffffffffffffffffffffffffffffffffffffff811681036101a35790565b346101a357610e92610e4c36610db9565b5050929150610e59611f53565b610e61611fba565b63ffffffff81165f525f60205260405f209283610e8c610e818380611d56565b926020810190611d56565b9261257f565b15610ed55760010180547fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff16700100000000000000000000000000000000179055005b7fb1333bc8000000000000000000000000000000000000000000000000000000005f5260045ffd5b346101a3575f6003193601126101a357602060ff7fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f0330054166040519015158152f35b60ff198116036101a357565b346101a3576101206003193601126101a35760043567ffffffffffffffff81116101a357610f7c9036906004016102fb565b50602435610f8981610f3e565b6044359060c07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9c3601126101a35760205f61106e610100860194611062610fef604051610fea81610fdc8b8a83016126b7565b03601f198101835282610a88565b613253565b95610fdc610ffe610524611a74565b9361100a610524611a80565b611015610524611a8c565b60c43560e435916101043593604051998a9860081c8e8a019694929091610100989694928852602088015260408701526060860152608085015260a084015260c083015260e08201520190565b604051918280926126c1565b039060025afa156110c25761025192610720927effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff5f5116926110af6040610aba565b938452602084015261014082019161339d565b6121c4565b346101a35760206003193601126101a35763ffffffff6110e5610255565b165f525f6020526102516111036110fe60405f20611d89565b6127bb565b6040519182916020835260208301906101a7565b346101a35760206003193601126101a3576111306102b5565b73ffffffffffffffffffffffffffffffffffffffff7ff3177357ab46d8af007ab3fdb9af81da189e1068fefdc0073dca88a2cab40a00541633036111c057803b1561117e57610c7890612837565b73ffffffffffffffffffffffffffffffffffffffff907fc2f31e5e000000000000000000000000000000000000000000000000000000005f521660045260245ffd5b7f068ca9d8000000000000000000000000000000000000000000000000000000005f523360045260245ffd5b346101a3575f6003193601126101a35761120636336121cf565b61120e611fba565b600160ff197fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f033005416177fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f03300557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586020604051338152a1005b346101a35761129336610db9565b50509091506112a0611a56565b506112a9611f53565b6112b1611fba565b6112c88263ffffffff165f525f60205260405f2090565b600181018054939091608085901c67ffffffffffffffff16610732576104a66113bc61049983610524610a129761137f6102519b6113688a6113396113c29b8f6113336113449f6113279063ffffffff165f52600160205260405f2090565b61046860c08401611a98565b906129ca565b96819d919460c01c90565b67ffffffffffffffff84161161145c5763ffffffff165f52600160205260405f2090565b9067ffffffffffffffff165f5260205260405f2090565b809a611396610524835467ffffffffffffffff1690565b1561140957926113b19293608060a082013591013591612c27565b6113ca575b50611d89565b94611e0a565b6109f9610aab565b80547fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff167001000000000000000000000000000000001790555f6113b6565b9150608092611446919067ffffffffffffffff167fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000825416179055565b60a081013560018b015501356002890155611d89565b845477ffffffffffffffffffffffffffffffffffffffffffffffff1660c084901b7fffffffffffffffff0000000000000000000000000000000000000000000000001617855561044b565b346101a3575f6003193601126101a3577ff3177357ab46d8af007ab3fdb9af81da189e1068fefdc0073dca88a2cab40a005460a01c60ff16156115325760207f8fb36037000000000000000000000000000000000000000000000000000000005b7fffffffff0000000000000000000000000000000000000000000000000000000060405191168152f35b60205f611508565b346101a35760a06003193601126101a357611553610255565b60243561155f816105f6565b60443567ffffffffffffffff81116101a35761157f9036906004016102fb565b91909260643567ffffffffffffffff81116101a3576115a29036906004016102fb565b906084359467ffffffffffffffff86116101a357610251966115cb6107209736906004016102fb565b969095611e3c565b346101a3575f6003193601126101a3576102516040516115f4604082610a88565b600581527f352e302e3000000000000000000000000000000000000000000000000000000060208201526040519182916020835260208301906101a7565b346101a35760406003193601126101a35761025161110361169161168c611657610255565b63ffffffff60243591611669836105f6565b165f52600160205260405f209067ffffffffffffffff165f5260205260405f2090565b611e0a565b612c7c565b346101a35760206003193601126101a35760206116e26116b4610255565b6116bc611fba565b63ffffffff165f525f60205267ffffffffffffffff600160405f20015460801c16151590565b6040519015158152f35b346101a3575f6003193601126101a357602073ffffffffffffffffffffffffffffffffffffffff7ff3177357ab46d8af007ab3fdb9af81da189e1068fefdc0073dca88a2cab40a005416604051908152f35b346101a35760206003193601126101a3576117576102b5565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00549067ffffffffffffffff6117a660ff604085901c1615611798565b1590565b9367ffffffffffffffff1690565b1680159081611999575b600114908161198f575b159081611986575b5061195e57611843908261183a60017fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000007ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005416177ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0055565b6118e357611ed8565b61184957005b6118b47fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054167ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0055565b604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d290602090a1005b611959680100000000000000007fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005416177ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0055565b611ed8565b7ff92ee8a9000000000000000000000000000000000000000000000000000000005f5260045ffd5b9050155f6117c2565b303b1591506117ba565b8391506117b0565b346101a3575f6003193601126101a357602060405173ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000ee4ea8d358473f0fcebf0329feed95d56e8c04d7168152f35b346101a35760406003193601126101a357602067ffffffffffffffff611a4c611a18610255565b63ffffffff60243591611a2a836105f6565b165f526001845260405f209067ffffffffffffffff165f5260205260405f2090565b5416604051908152f35b60405190611a6382610a4b565b5f6040838281528260208201520152565b606435610365816105f6565b608435610365816105f6565b60a435610365816105f6565b35610365816105f6565b3561036581610f3e565b9060a06002918035611abd81610f3e565b60081c7fff00000000000000000000000000000000000000000000000000000000000000855416178455611bb460018501611aff602084013561088e816105f6565b6040830135611b0d816105f6565b7fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff6fffffffffffffffff000000000000000083549260401b169116178155611b5c606084013561091e816105f6565b608083013590611b6b826105f6565b9077ffffffffffffffffffffffffffffffffffffffffffffffff7fffffffffffffffff00000000000000000000000000000000000000000000000083549260c01b169116179055565b0135910155565b906040600291611c048135611bcf816105f6565b859067ffffffffffffffff167fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000825416179055565b602081013560018501550135910155565b91908260c09103126101a357604051611c2d81610a6c565b60a08082948035611c3d81610f3e565b84526020810135611c4d816105f6565b60208501526040810135611c60816105f6565b60408501526060810135611c73816105f6565b60608501526080810135611c86816105f6565b60808501520135910152565b91908260609103126101a357604051611caa81610a4b565b60408082948035611cba816105f6565b8452602081013560208501520135910152565b60405190611cdc604083610a88565b600482527f7761736d000000000000000000000000000000000000000000000000000000006020830152565b908092918237015f815290565b909280926022947f0300000000000000000000000000000000000000000000000000000000000000845260018401525f60218401528483013701015f815290565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01813603018212156101a3570190565b90604051611d9681610a6c565b60a06002829460ff19815460081b168452611e03611df2600183015467ffffffffffffffff8116602088015267ffffffffffffffff808260401c1616604088015267ffffffffffffffff808260801c1616606088015260c01c90565b67ffffffffffffffff166080860152565b0154910152565b90604051611e1781610a4b565b60406002829467ffffffffffffffff8154168452600181015460208501520154910152565b969594925090611e4a611fba565b611e748763ffffffff165f525f60205267ffffffffffffffff600160405f20015460801c16151590565b61073257611eca6001611ebc63ffffffff611ecf9a1694855f525f602052600260405f200154955f528260205260405f209067ffffffffffffffff165f5260205260405f2090565b01549261070d6106fd611ccd565b613643565b61179481612c72565b611ef190611ee461371f565b611eec61371f565b612837565b611ef961371f565b611f0161371f565b611f0961371f565b60ff197fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f0330054167fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f0330055565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000ee4ea8d358473f0fcebf0329feed95d56e8c04d7163303611f9257565b7fe54f8f9d000000000000000000000000000000000000000000000000000000005f5260045ffd5b60ff7fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f033005416611fe557565b7fd93c0665000000000000000000000000000000000000000000000000000000005f5260045ffd5b612016906127bb565b6020815191012090565b61201690612c7c565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b905f5b60ff811690601f82108015612108577fff0000000000000000000000000000000000000000000000000000000000000085841a60f81b16159081612100575b50156120e1575060ff81146120dc57600101612086565b612056565b929050604051926040840160405280601f03845260031b1b6020830152565b90505f6120c5565b612029565b906004116101a35790600490565b919091357fffffffff000000000000000000000000000000000000000000000000000000008116926004811061214f575050565b7fffffffff00000000000000000000000000000000000000000000000000000000929350829060040360031b1b161690565b9183606094601f9273ffffffffffffffffffffffffffffffffffffffff601f199516865260406020870152816040870152868601375f8582860101520116010190565b6040513d5f823e3d90fd5b61222c6122107ff3177357ab46d8af007ab3fdb9af81da189e1068fefdc0073dca88a2cab40a005473ffffffffffffffffffffffffffffffffffffffff1690565b61222361221d855f61210d565b9061211b565b90833091612cb6565b901561223757505050565b63ffffffff16156123fc576122c4740100000000000000000000000000000000000000007fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff7ff3177357ab46d8af007ab3fdb9af81da189e1068fefdc0073dca88a2cab40a005416177ff3177357ab46d8af007ab3fdb9af81da189e1068fefdc0073dca88a2cab40a0055565b6123216123086123087ff3177357ab46d8af007ab3fdb9af81da189e1068fefdc0073dca88a2cab40a005473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff1690565b91823b156101a357612367925f808094604051968795869485937f94c7d7ee00000000000000000000000000000000000000000000000000000000855260048501612181565b03925af180156110c2576123e2575b506107897fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff7ff3177357ab46d8af007ab3fdb9af81da189e1068fefdc0073dca88a2cab40a0054167ff3177357ab46d8af007ab3fdb9af81da189e1068fefdc0073dca88a2cab40a0055565b806123f05f6123f693610a88565b80610199565b5f612376565b7f068ca9d8000000000000000000000000000000000000000000000000000000005f5273ffffffffffffffffffffffffffffffffffffffff1660045260245ffd5b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81813603018212156101a3570190565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b8135939291368190037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa1018512156101a3576124e7946124e0602083018361243d565b9101612d7c565b60128110156124f4571590565b612470565b908160209103126101a3575190565b91909160a08060c083019467ffffffffffffffff8135612527816105f6565b16845267ffffffffffffffff6020820135612541816105f6565b16602085015267ffffffffffffffff604082013561255e816105f6565b16604085015260608101356060850152608081013560808501520135910152565b9061258983611a98565b67ffffffffffffffff61259e61052487611a98565b91161061268f578061260261260b926125fb6125ef6125da6125ce8863ffffffff165f52600160205260405f2090565b61046860c08b01611a98565b9663ffffffff165f52600160205260405f2090565b61046860c08a01611a98565b94866129ca565b939050856129ca565b905061261683611a98565b67ffffffffffffffff61262b61052487611a98565b91160361267357505060405161264981610fdc602082019485612508565b5190209060405161266281610fdc602082019485612508565b5190200361266e575f90565b600190565b67ffffffffffffffff925082919350169116111561266e575f90565b7f63520534000000000000000000000000000000000000000000000000000000005f5260045ffd5b6040809282370190565b805191908290602001825e015f815290565b90925f61277e602092611062610100860197610fdc612700610fdc610fea8c6040519283918c83016126b7565b9861270d61052486611a98565b9461271c6105248a8301611a98565b9061272c61052460408301611a98565b60608201359060a0608084013593013593604051998a9860081c8e8a019694929091610100989694928852602088015260408701526060860152608085015260a084015260c083015260e08201520190565b039060025afa156110c257610365927effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff5f5116926110af6040610aba565b60ff198151169067ffffffffffffffff6020820151169067ffffffffffffffff60408201511667ffffffffffffffff6060830151169060a067ffffffffffffffff6080850151169301519360405195602087015260408601526060850152608084015260a083015260c082015260c0815261036560e082610a88565b602073ffffffffffffffffffffffffffffffffffffffff7f2f658b440c35314f52658ea8a740e05b284cdc84dc9ae01e891f21b8933e7cad9216807fffffffffffffffffffffffff00000000000000000000000000000000000000007ff3177357ab46d8af007ab3fdb9af81da189e1068fefdc0073dca88a2cab40a005416177ff3177357ab46d8af007ab3fdb9af81da189e1068fefdc0073dca88a2cab40a0055604051908152a1565b67ffffffffffffffff633b9aca009116029067ffffffffffffffff82169182036120dc57565b67ffffffffffffffff60019116019067ffffffffffffffff82116120dc57565b9067ffffffffffffffff8091169116019067ffffffffffffffff82116120dc57565b90633b9aca00820291808304633b9aca0014901517156120dc57565b818102929181159184041417156120dc57565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1813603018212156101a3570180359067ffffffffffffffff82116101a3576020019181360383136101a357565b9291906129df815467ffffffffffffffff1690565b9367ffffffffffffffff8516928315612bff576129fb82611a98565b93612a0860c08401611a98565b9367ffffffffffffffff86169167ffffffffffffffff8616831115612bd757612a50612a3e612a3960208801611a98565b6128e2565b612a4a60408801611a98565b90612928565b9867ffffffffffffffff8a1691821115612baf57612a706105244261294a565b90612a9282600188015492612a8c8467ffffffffffffffff1690565b9061361b565b612b8757612ab0916105249160401c67ffffffffffffffff16612a4a565b1115612b5f576105246002612ac792015495612908565b14612b25575b90612af59261179492612aef612ae660e0850185612979565b50915460081b90565b906126d3565b612afd579190565b7f396df4ec000000000000000000000000000000000000000000000000000000005f5260045ffd5b9082606082013503612b375790612acd565b7f895cf0ce000000000000000000000000000000000000000000000000000000005f5260045ffd5b7f4ccc303c000000000000000000000000000000000000000000000000000000005f5260045ffd5b7f6c4c87b6000000000000000000000000000000000000000000000000000000005f5260045ffd5b7f14a286e4000000000000000000000000000000000000000000000000000000005f5260045ffd5b7ff97b0922000000000000000000000000000000000000000000000000000000005f5260045ffd5b7f09128dc8000000000000000000000000000000000000000000000000000000005f5260045ffd5b835467ffffffffffffffff9182169116148015939190612c63575b508215612c54575b505061266e575f90565b60020154141590505f80612c4a565b6001820154141592505f612c42565b600911156124f457565b67ffffffffffffffff8151169060406020820151910151906040519260208401526040830152606082015260608152610365608082610a88565b5f9060409295939582967fffffffff00000000000000000000000000000000000000000000000000000000849773ffffffffffffffffffffffffffffffffffffffff8751938160208601967fb700961300000000000000000000000000000000000000000000000000000000885216602486015216604484015216606482015260648152612d45608482610a88565b8380528360205251915afa612d5657565b9150505f51906020518060201c150290565b600511156124f457565b600611156124f457565b93919293612d8981613776565b612d9581959295612d68565b6130985783612dac92612da66137d0565b9061384e565b612db581612c72565b80612f485750612dc481613afb565b612dd081969296612d68565b612f3e57612e009261070d92612dfb612de7613bcc565b926040519586916020830160209181520190565b613bf6565b612e0981612d72565b80612e1d575003612e18575f90565b600990565b809250612e2a9150612d72565b60018103612e385750600490565b612e4181612d72565b60028103612e4f5750600590565b612e5881612d72565b60038103612e665750600690565b612e6f81612d72565b60048103612e7d5750600790565b80612e89600592612d72565b14612f39576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152605660248201527f766572696679436861696e65644e6f6e4d656d626572736869703a206e6f6e2060448201527f65786861757374697665207061747465726e206d61746368696e67206f6e205660648201527f65726966794e6f6e4578697374656e63654572726f7200000000000000000000608482015260a490fd5b600890565b5050505050600390565b9350505050612f5681612c72565b60018103612f645750600a90565b612f6d81612c72565b60038103612f7b5750600c90565b612f8481612c72565b60048103612f925750600d90565b612f9b81612c72565b60058103612fa95750600e90565b612fb281612c72565b60068103612fc05750600f90565b612fc981612c72565b60078103612fd75750601090565b80612fe3600892612c72565b14613093576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152605660248201527f766572696679436861696e65644e6f6e4d656d626572736869703a206e6f6e2060448201527f65786861757374697665207061747465726e206d61746368696e67206f6e205660648201527f65726966794e6f6e4578697374656e63654572726f7200000000000000000000608482015260a490fd5b601190565b505050505050600390565b90813b156131925773ffffffffffffffffffffffffffffffffffffffff8216807fffffffffffffffffffffffff00000000000000000000000000000000000000007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5416177f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc557fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b5f80a28051156131615761315e91613c73565b50565b50503461316a57565b7fb398979f000000000000000000000000000000000000000000000000000000005f5260045ffd5b73ffffffffffffffffffffffffffffffffffffffff827f4c9c8ce3000000000000000000000000000000000000000000000000000000005f521660045260245ffd5b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82019182116120dc57565b811561320b570690565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b90600182018092116120dc57565b919082018092116120dc57565b61339861036591610fdc61336e6040519261326f60c085610a88565b608884527f1f333139281e100f5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c60208501527f5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c60408501527f5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c60608501527f5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c60808501527f5c5c5c5c5c5c5c5c00000000000000000000000000000000000000000000000060a0850152610fdc61335a61333f613cb7565b926040519283916133546020840180976126c1565b906126c1565b519020604051928391602083019586613d8a565b5190207f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000090613201565b613238565b926133a89082613d9e565b939192909215613612576133bf9161179491613eff565b61360b576101006040519384377f07b8dbefa90bde075a26318e5066db729155514e3c06b888d4e03c56d82c97e66101008401527f02aca5d2a73f8d34e4b26eee3932365e6526c8d5e2f3347d679c2cb1867104dc6101208401527f2edb19cbb2b6ad0c98fdd7d1845500c26e497dc35e4cdc1cb02cc65dc4ba1bf26101408401527f1696ccafaefe49a5d8bad8e79630e19b25e5392a203aff0042d0216f254806f56101608401527f245229d9b076b3c0e8a4d70bde8c1cccffa08a9fae7557b165b3b0dbd653e2c76101808401527f253ec85988dbb84e46e94b5efa3373b47a000b4ac6c86b2d4b798d274a1823026101a08401527f07090a82e8fabbd39299be24705b92cf208ee8b3487f6f2b39ff27978a29a1db6101c08401527f2424bcc1f60a5472685fd50705b2809626e170120acaf441e133a2bd5e61d2446101e08401527f25833b15e156ae01f2741f4f4120ddb466c52eb83a959f79eb99b23caa7fbf1d6102008401527f04ddc8d30d5c438ca34091c5d2c6ded571382cba2b3c4fdc4222df2938b4e51e6102208401526102408301526102608201527f198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c26102808201527f1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed6102a08201527f275dc4a288d1afb3cbb1ac09187524c7db36395df7be3b99e673b13a075a65ec6102c08201527f1d9befcd05a5323e6da4d435f3b617cdb3af83285c2df711ef39c01571827f9d6102e08201526020816103008160085afa90511690565b5050505f90565b50505050505f90565b67ffffffffffffffff809193929316921682018092116120dc5767ffffffffffffffff161190565b91949093613659613654848061243d565b613afb565b61366581969296612d68565b613713576136919261368b61367a868061243d565b936136836137d0565b923691610ae4565b92613bf6565b61369a81612d72565b806137055750916136e993916136b76136d694602081019061243d565b6136e46136c2613bcc565b926040519687916020830160209181520190565b03601f198101875286610a88565b61416a565b6136f281612d72565b806136fc57505f90565b61036590614052565b925050506103659150614052565b50505050505050600290565b60ff7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005460401c161561374e57565b7fd7e6bcf8000000000000000000000000000000000000000000000000000000005f5260045ffd5b6020810161378c613787828461243d565b61420e565b156137c3575060408101906137a4613787838361243d565b156137b25750505f90600490565b6137bf916136549161243d565b9091565b613654906137bf9261243d565b6137d8611a56565b506040516137e581610a4b565b6021815260046020820152600c604082015290565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1813603018212156101a3570180359067ffffffffffffffff82116101a357602001918160051b360383136101a357565b9092916020820190613869613863838561243d565b80612979565b919094604085019561387e613863888861243d565b949093613891611794613787898b61243d565b613a6a575b6138a66117946137878b8b61243d565b6139f4575b5080159384806139ec575b6139dd57851595861591826139c6575b50506139b857831591826139a2575b50509050613997571561392857505091818361391261390061390a6139006117949761391a9961243d565b60608101906137fa565b94909361243d565b939050614551565b613923575b5f90565b600690565b90929015613962575091818361394d61390061390a613900611794976139559961243d565b9390506144e6565b61395d575f90565b600790565b9261398d9361398561390061397d613900611794978761243d565b93909561243d565b9390926143e1565b1561391f57600890565b505050505050600590565b6139ae92505f93614288565b1315805f806138d5565b505050505050505050600490565b5f9250906139d49186614288565b12155f806138c6565b50505050505050505050600390565b5085156138b6565b613a499088613a038b8261243d565b918c613a438d613a3b613a31613a27613a1f613863858a61243d565b94909861243d565b6020810190612979565b9690923691610ae4565b943691610ae4565b9361416a565b613a5281612d72565b613a5c575f6138ab565b505050505050505050600290565b613a94613a77888a61243d565b89838d613a438c613a3b613a31613a27613a1f613863858a61243d565b613a9d81612d72565b156138965750505050505050505050600190565b600311156124f457565b91908110156121085760051b810135907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc1813603018212156101a3570190565b60408101613b098183612979565b905015613bc357613b1d613b3e9183612979565b90613b288480612979565b90613b366020870187612979565b9490936145fb565b919091613b4a81613ab1565b613bba5760608101613b5c81836137fa565b9190505f925b828410613b725750505050905f90565b90919293613b9390613b8e86613b8886866137fa565b90613abb565b6146aa565b949094613b9f81613ab1565b613bae57600101929190613b62565b50505050505f90600390565b50505f90600290565b50505f90600190565b613bd4611a56565b50604051613be181610a4b565b60208152600160208201526001604082015290565b929091613c0d613c068580612979565b3691610ae4565b60208151910120906020815191012003613c6b57613c31613c066020850185612979565b60208151910120906020815191012003613c6457613c4e91614700565b613c5781612d68565b613c5f575f90565b600390565b5050600290565b505050600190565b5f8061036593602081519101845af43d15613caf573d91613c9383610ac8565b92613ca16040519485610a88565b83523d5f602085013e614802565b606091614802565b60405190613cc660c083610a88565b608882527f363636363636363600000000000000000000000000000000000000000000000060a0837f75595b5342747a6536363636363636363636363636363636363636363636363660208201527f363636363636363636363636363636363636363636363636363636363636363660408201527f363636363636363636363636363636363636363636363636363636363636363660608201527f363636363636363636363636363636363636363636363636363636363636363660808201520152565b613d9790602093926126c1565b9081520190565b90916040519260408401907f2f5d8a3817f21d3e453573c90c3cc47b7ff235fad7bdfbd59bbd6ae5d153273e8552604060208601947f147fa22142b1fd86ce75fc87230a0feac8765d02938784dcfc828d17d7e7c432865283377f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000016040808760808160065afa937f2a81b98e1c997bd01a20893a08a46c6804493e838c1a0ff6c8c069ef5ab66b9a8152602060608901947f276938ada8075cec20d4d6a1f157ec94cc7ba6207c98576e98c1ad9d6378fb6f86527f0326e7d44688ce5903676b7d646e46a5938c8e5fd8cd54e4d5aa3300649f3cfc6001825160808d0199818b5288888860608160075afa92101616868d60808160065afa1616967f179496ce140df89ce35c5ee7fb496efdffda5e5d3b95ff9116e2e5df96b36ab7855252015180955260608160075afa9210161660408460808160065afa169251915190565b906040908180519384377f198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c2828401527f1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed60608401527f090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b60808401527f12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa60a084015260c08301377f07b8dbefa90bde075a26318e5066db729155514e3c06b888d4e03c56d82c97e66101008201527f02aca5d2a73f8d34e4b26eee3932365e6526c8d5e2f3347d679c2cb1867104dc6101208201527f2edb19cbb2b6ad0c98fdd7d1845500c26e497dc35e4cdc1cb02cc65dc4ba1bf26101408201527f1696ccafaefe49a5d8bad8e79630e19b25e5392a203aff0042d0216f254806f56101608201526020816101808160085afa90511690565b61405b81612d72565b600181036140695750600390565b61407281612d72565b600281036140805750600490565b61408981612d72565b600381036140975750600590565b6140a081612d72565b600481036140ae5750600690565b806140ba600592612d72565b1461395d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152605060248201527f766572696679436861696e65644d656d626572736869703a206e6f6e2065786860448201527f61757374697665207061747465726e206d61746368696e67206f6e205665726960648201527f66794578697374656e63654572726f7200000000000000000000000000000000608482015260a490fd5b929390919361417c613c068580612979565b60208151910120906020815191012003614205576141a0613c066020850185612979565b602081519101209060208151910120036141fd576141be9082614700565b6141c781612d68565b6141f6576141d490613afb565b6141dd81612d68565b6141ef57036141ea575f90565b600590565b5050600490565b5050600390565b505050600290565b50505050600190565b6142188180612979565b905061425d5761422b6020820182612979565b905061425d5761423e6040820182612979565b905061425d578060606142529201906137fa565b905061391f57600190565b505f90565b908151811015612108570160200190565b90156121085790565b90821015612108570190565b805180841190841802831892918391905f5b8381106142dd57505051116142d657116142b2575f90565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90565b5050600190565b909192506143146142ee8285614262565b517fff000000000000000000000000000000000000000000000000000000000000001690565b7fff0000000000000000000000000000000000000000000000000000000000000061439161436c61434685898861427c565b357fff000000000000000000000000000000000000000000000000000000000000001690565b7fff000000000000000000000000000000000000000000000000000000000000001690565b9116818110156143c657505050505050507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90565b116143d7576001019084929161429a565b5050505050600190565b929390916143ee816131d4565b926143f8836131d4565b935b61440b613c06613863838686613abb565b60208151910120614423613c0661386388888c613abb565b6020815191012014806144af575b61449757614458611794614446838686613abb565b61445188888c613abb565b90896148a5565b61448c5761446a9261179492876144e6565b6144845761447b9361179493614551565b61391f57600190565b505050505f90565b505050505050505f90565b6144a36144a9916131d4565b946131d4565b936143fa565b506144c1613c06613a27838686613abb565b602081519101206144d9613c06613a2788888c613abb565b6020815191012014614431565b80519060208101518201908183116120dc57604081015183018093116120dc575115600117156120dc575f5b85811061452457505050505050600190565b61453a5f8484614535858a8a613abb565b6148f6565b1561454757600101614512565b5050505050505f90565b919091805115600117156120dc57602081015160408201519151925f5b8681106145815750505050505050600190565b61459285858561453585878c613abb565b1561448c5760010161456e565b906145a982610ac8565b6145b66040519182610a88565b828152601f196145c68294610ac8565b0190602036910137565b8593836145ee9260209a999795613d979995823701905f82526126c1565b91823701905f82526126c1565b949390919293841561469d578015614690575f60209161462261461d88614957565b61459f565b9361462d8589614976565b5061463d60405180938193611d08565b039060025afa156110c257602094610fdc61467f94611062935f9788519261466661461d61493b565b92614670846149b6565b506040519889978d89016145d0565b039060025afa156110c2575f805191565b5050505050505f90600290565b5050505050505f90600190565b61467f6146d061106260205f948180976146c48380612979565b96909383810190612979565b80929188604051998a9787890137860192858401526040830137010186838201520301601f198101835282610a88565b906040820161470f8184612979565b905015613c6b5761474d6143466147477fff000000000000000000000000000000000000000000000000000000000000009386612979565b90614273565b16613c64576147626040820151825190613246565b606083019261477184826137fa565b9490505f5b858110614787575050505050505f90565b61479581613b8884866137fa565b846147a08280612979565b90506020880151119182156147e6575b82156147d0575b50506147c557600101614776565b505050505050600290565b6147dc91925080612979565b905011845f6147b7565b91506147fb61436c6143466147478580612979565b15916147b0565b9061483f575080511561481757805190602001fd5b7fd6bda275000000000000000000000000000000000000000000000000000000005f5260045ffd5b81511580614892575b614850575090565b73ffffffffffffffffffffffffffffffffffffffff907f9996b315000000000000000000000000000000000000000000000000000000005f521660045260245ffd5b50803b15614848565b600211156124f457565b906148b090826149c6565b92909160028410156124f45783614484576148d6916148ce916149c6565b91909361489b565b6148df8161489b565b6148f0576148ec90613238565b1490565b50505f90565b91906149028380612979565b905010908115614926575b506148f057806020614920920190612979565b90501490565b90506149328280612979565b9050115f61490d565b60015f805b614948575090565b60019091019060071c80614940565b60019060071c805b614967575090565b60019091019060071c8061495f565b91909160205f9301607f8216915b60071c9182156149aa576001918291608017815301930190607f81169093909193614984565b90600193949250530190565b5f919082906020908101906149aa565b5f5b600281106149da575050505f90600190565b6149e5825182612966565b602083015181018082116120dc57604084015182018092116120dc578260010390600182116120dc57600192614a20614a2793875190612966565b91876148f6565b151514614a36576001016149c8565b915050905f9056
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000ee4ea8d358473f0fcebf0329feed95d56e8c04d7
-----Decoded View---------------
Arg [0] : _ibcHandler (address): 0xEe4eA8d358473f0FCEbf0329fEed95D56E8C04D7
-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 000000000000000000000000ee4ea8d358473f0fcebf0329feed95d56e8c04d7
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 34 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
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.