Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
- Contract name:
- SignalService
- Optimization enabled
- true
- Compiler version
- v0.8.24+commit.e11b9ed9
- Optimization runs
- 200
- EVM Version
- cancun
- Verified at
- 2024-05-27T09:04:02.960268Z
contracts/signal/SignalService.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.24;
import "../common/EssentialContract.sol";
import "../common/LibStrings.sol";
import "../libs/LibTrieProof.sol";
import "./ISignalService.sol";
/// @title SignalService
/// @notice See the documentation in {ISignalService} for more details.
/// @dev Labeled in AddressResolver as "signal_service".
/// @custom:security-contact security@taiko.xyz
contract SignalService is EssentialContract, ISignalService {
/// @notice Mapping to store the top blockId.
/// @dev Slot 1.
mapping(uint64 chainId => mapping(bytes32 kind => uint64 blockId)) public topBlockId;
/// @notice Mapping to store the authorized addresses.
/// @dev Slot 2.
mapping(address addr => bool authorized) public isAuthorized;
uint256[48] private __gap;
struct CacheAction {
bytes32 rootHash;
bytes32 signalRoot;
uint64 chainId;
uint64 blockId;
bool isFullProof;
bool isLastHop;
CacheOption option;
}
error SS_EMPTY_PROOF();
error SS_INVALID_HOPS_WITH_LOOP();
error SS_INVALID_LAST_HOP_CHAINID();
error SS_INVALID_MID_HOP_CHAINID();
error SS_INVALID_STATE();
error SS_SIGNAL_NOT_FOUND();
error SS_UNAUTHORIZED();
/// @notice Initializes the contract.
/// @param _owner The owner of this contract. msg.sender will be used if this value is zero.
/// @param _addressManager The address of the {AddressManager} contract.
function init(address _owner, address _addressManager) external initializer {
__Essential_init(_owner, _addressManager);
}
/// @dev Authorize or deauthorize an address for calling syncChainData.
/// @dev Note that addr is supposed to be TaikoL1 and TaikoL1 contracts deployed locally.
/// @param _addr The address to be authorized or deauthorized.
/// @param _authorize True if authorize, false otherwise.
function authorize(address _addr, bool _authorize) external onlyOwner {
if (isAuthorized[_addr] == _authorize) revert SS_INVALID_STATE();
isAuthorized[_addr] = _authorize;
emit Authorized(_addr, _authorize);
}
/// @inheritdoc ISignalService
function sendSignal(bytes32 _signal) external returns (bytes32) {
return _sendSignal(msg.sender, _signal, _signal);
}
/// @inheritdoc ISignalService
function syncChainData(
uint64 _chainId,
bytes32 _kind,
uint64 _blockId,
bytes32 _chainData
)
external
returns (bytes32)
{
if (!isAuthorized[msg.sender]) revert SS_UNAUTHORIZED();
return _syncChainData(_chainId, _kind, _blockId, _chainData);
}
/// @inheritdoc ISignalService
/// @dev This function may revert.
function proveSignalReceived(
uint64 _chainId,
address _app,
bytes32 _signal,
bytes calldata _proof
)
external
virtual
whenNotPaused
nonReentrant
returns (uint256 numCacheOps_)
{
CacheAction[] memory actions = // actions for caching
_verifySignalReceived(_chainId, _app, _signal, _proof, true);
for (uint256 i; i < actions.length; ++i) {
numCacheOps_ += _cache(actions[i]);
}
}
/// @inheritdoc ISignalService
/// @dev This function may revert.
function verifySignalReceived(
uint64 _chainId,
address _app,
bytes32 _signal,
bytes calldata _proof
)
external
view
{
_verifySignalReceived(_chainId, _app, _signal, _proof, false);
}
/// @inheritdoc ISignalService
function isChainDataSynced(
uint64 _chainId,
bytes32 _kind,
uint64 _blockId,
bytes32 _chainData
)
public
view
nonZeroValue(_chainData)
returns (bool)
{
bytes32 signal = signalForChainData(_chainId, _kind, _blockId);
return _loadSignalValue(address(this), signal) == _chainData;
}
/// @inheritdoc ISignalService
function isSignalSent(address _app, bytes32 _signal) public view returns (bool) {
return _loadSignalValue(_app, _signal) != 0;
}
/// @inheritdoc ISignalService
function getSyncedChainData(
uint64 _chainId,
bytes32 _kind,
uint64 _blockId
)
public
view
returns (uint64 blockId_, bytes32 chainData_)
{
blockId_ = _blockId != 0 ? _blockId : topBlockId[_chainId][_kind];
if (blockId_ != 0) {
bytes32 signal = signalForChainData(_chainId, _kind, blockId_);
chainData_ = _loadSignalValue(address(this), signal);
if (chainData_ == 0) revert SS_SIGNAL_NOT_FOUND();
}
}
/// @inheritdoc ISignalService
function signalForChainData(
uint64 _chainId,
bytes32 _kind,
uint64 _blockId
)
public
pure
returns (bytes32)
{
return keccak256(abi.encode(_chainId, _kind, _blockId));
}
/// @notice Returns the slot for a signal.
/// @param _chainId The chainId of the signal.
/// @param _app The address that initiated the signal.
/// @param _signal The signal (message) that was sent.
/// @return The slot for the signal.
function getSignalSlot(
uint64 _chainId,
address _app,
bytes32 _signal
)
public
pure
returns (bytes32)
{
return keccak256(abi.encodePacked("SIGNAL", _chainId, _app, _signal));
}
function _verifyHopProof(
uint64 _chainId,
address _app,
bytes32 _signal,
bytes32 _value,
HopProof memory _hop,
address _signalService
)
internal
view
virtual
nonZeroAddr(_app)
nonZeroValue(_signal)
nonZeroValue(_value)
returns (bytes32)
{
return LibTrieProof.verifyMerkleProof(
_hop.rootHash,
_signalService,
getSignalSlot(_chainId, _app, _signal),
_value,
_hop.accountProof,
_hop.storageProof
);
}
function _authorizePause(address, bool) internal pure override notImplemented { }
function _syncChainData(
uint64 _chainId,
bytes32 _kind,
uint64 _blockId,
bytes32 _chainData
)
private
returns (bytes32 signal_)
{
signal_ = signalForChainData(_chainId, _kind, _blockId);
_sendSignal(address(this), signal_, _chainData);
if (topBlockId[_chainId][_kind] < _blockId) {
topBlockId[_chainId][_kind] = _blockId;
}
emit ChainDataSynced(_chainId, _blockId, _kind, _chainData, signal_);
}
function _sendSignal(
address _app,
bytes32 _signal,
bytes32 _value
)
private
nonZeroAddr(_app)
nonZeroValue(_signal)
nonZeroValue(_value)
returns (bytes32 slot_)
{
slot_ = getSignalSlot(uint64(block.chainid), _app, _signal);
assembly {
sstore(slot_, _value)
}
emit SignalSent(_app, _signal, slot_, _value);
}
function _cache(CacheAction memory _action) private returns (uint256 numCacheOps_) {
// cache state root
bool cacheStateRoot = _action.option == CacheOption.CACHE_BOTH
|| _action.option == CacheOption.CACHE_STATE_ROOT;
if (cacheStateRoot && _action.isFullProof && !_action.isLastHop) {
numCacheOps_ = 1;
_syncChainData(
_action.chainId, LibStrings.H_STATE_ROOT, _action.blockId, _action.rootHash
);
}
// cache signal root
bool cacheSignalRoot = _action.option == CacheOption.CACHE_BOTH
|| _action.option == CacheOption.CACHE_SIGNAL_ROOT;
if (cacheSignalRoot && (_action.isFullProof || !_action.isLastHop)) {
numCacheOps_ += 1;
_syncChainData(
_action.chainId, LibStrings.H_SIGNAL_ROOT, _action.blockId, _action.signalRoot
);
}
}
function _loadSignalValue(
address _app,
bytes32 _signal
)
private
view
nonZeroAddr(_app)
nonZeroValue(_signal)
returns (bytes32 value_)
{
bytes32 slot = getSignalSlot(uint64(block.chainid), _app, _signal);
assembly {
value_ := sload(slot)
}
}
function _verifySignalReceived(
uint64 _chainId,
address _app,
bytes32 _signal,
bytes calldata _proof,
bool _prepareCaching
)
private
view
nonZeroAddr(_app)
nonZeroValue(_signal)
returns (CacheAction[] memory actions)
{
HopProof[] memory hopProofs = abi.decode(_proof, (HopProof[]));
if (hopProofs.length == 0) revert SS_EMPTY_PROOF();
uint64[] memory trace = new uint64[](hopProofs.length - 1);
if (_prepareCaching) {
actions = new CacheAction[](hopProofs.length);
}
uint64 chainId = _chainId;
address app = _app;
bytes32 signal = _signal;
bytes32 value = _signal;
address signalService = resolve(chainId, LibStrings.B_SIGNAL_SERVICE, false);
if (signalService == address(this)) revert SS_INVALID_MID_HOP_CHAINID();
HopProof memory hop;
bytes32 signalRoot;
bool isFullProof;
bool isLastHop;
for (uint256 i; i < hopProofs.length; ++i) {
hop = hopProofs[i];
for (uint256 j; j < i; ++j) {
if (trace[j] == hop.chainId) revert SS_INVALID_HOPS_WITH_LOOP();
}
signalRoot = _verifyHopProof(chainId, app, signal, value, hop, signalService);
isLastHop = i == trace.length;
if (isLastHop) {
if (hop.chainId != block.chainid) revert SS_INVALID_LAST_HOP_CHAINID();
signalService = address(this);
} else {
trace[i] = hop.chainId;
if (hop.chainId == 0 || hop.chainId == block.chainid) {
revert SS_INVALID_MID_HOP_CHAINID();
}
signalService = resolve(hop.chainId, LibStrings.B_SIGNAL_SERVICE, false);
if (signalService == address(this)) revert SS_INVALID_MID_HOP_CHAINID();
}
isFullProof = hop.accountProof.length != 0;
if (_prepareCaching) {
actions[i] = CacheAction(
hop.rootHash,
signalRoot,
chainId,
hop.blockId,
isFullProof,
isLastHop,
hop.cacheOption
);
}
signal = signalForChainData(
chainId,
isFullProof ? LibStrings.H_STATE_ROOT : LibStrings.H_SIGNAL_ROOT,
hop.blockId
);
value = hop.rootHash;
chainId = hop.chainId;
app = signalService;
}
if (value == 0 || value != _loadSignalValue(address(this), signal)) {
revert SS_SIGNAL_NOT_FOUND();
}
}
}
contracts/common/AddressResolver.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.24;
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import "./IAddressManager.sol";
import "./IAddressResolver.sol";
/// @title AddressResolver
/// @notice See the documentation in {IAddressResolver}.
/// @custom:security-contact security@taiko.xyz
abstract contract AddressResolver is IAddressResolver, Initializable {
/// @notice Address of the AddressManager.
address public addressManager;
uint256[49] private __gap;
error RESOLVER_DENIED();
error RESOLVER_INVALID_MANAGER();
error RESOLVER_UNEXPECTED_CHAINID();
error RESOLVER_ZERO_ADDR(uint64 chainId, bytes32 name);
/// @dev Modifier that ensures the caller is the resolved address of a given
/// name.
/// @param _name The name to check against.
modifier onlyFromNamed(bytes32 _name) {
if (msg.sender != resolve(_name, true)) revert RESOLVER_DENIED();
_;
}
/// @dev Modifier that ensures the caller is a resolved address to either _name1 or _name2
/// name.
/// @param _name1 The first name to check against.
/// @param _name2 The second name to check against.
modifier onlyFromNamedEither(bytes32 _name1, bytes32 _name2) {
if (msg.sender != resolve(_name1, true) && msg.sender != resolve(_name2, true)) {
revert RESOLVER_DENIED();
}
_;
}
/// @custom:oz-upgrades-unsafe-allow constructor
constructor() {
_disableInitializers();
}
/// @inheritdoc IAddressResolver
function resolve(
bytes32 _name,
bool _allowZeroAddress
)
public
view
virtual
returns (address payable)
{
return _resolve(uint64(block.chainid), _name, _allowZeroAddress);
}
/// @inheritdoc IAddressResolver
function resolve(
uint64 _chainId,
bytes32 _name,
bool _allowZeroAddress
)
public
view
virtual
returns (address payable)
{
return _resolve(_chainId, _name, _allowZeroAddress);
}
/// @dev Initialization method for setting up AddressManager reference.
/// @param _addressManager Address of the AddressManager.
function __AddressResolver_init(address _addressManager) internal virtual onlyInitializing {
if (block.chainid > type(uint64).max) {
revert RESOLVER_UNEXPECTED_CHAINID();
}
addressManager = _addressManager;
}
/// @dev Helper method to resolve name-to-address.
/// @param _chainId The chainId of interest.
/// @param _name Name whose address is to be resolved.
/// @param _allowZeroAddress If set to true, does not throw if the resolved
/// address is `address(0)`.
/// @return addr_ Address associated with the given name on the specified
/// chain.
function _resolve(
uint64 _chainId,
bytes32 _name,
bool _allowZeroAddress
)
private
view
returns (address payable addr_)
{
address _addressManager = addressManager;
if (_addressManager == address(0)) revert RESOLVER_INVALID_MANAGER();
addr_ = payable(IAddressManager(_addressManager).getAddress(_chainId, _name));
if (!_allowZeroAddress && addr_ == address(0)) {
revert RESOLVER_ZERO_ADDR(_chainId, _name);
}
}
}
contracts/common/EssentialContract.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.24;
import "@openzeppelin/contracts/proxy/utils/UUPSUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol";
import "./AddressResolver.sol";
import "../libs/LibNetwork.sol";
/// @title EssentialContract
/// @custom:security-contact security@taiko.xyz
abstract contract EssentialContract is UUPSUpgradeable, Ownable2StepUpgradeable, AddressResolver {
uint8 private constant _FALSE = 1;
uint8 private constant _TRUE = 2;
/// @dev The slot in transient storage of the reentry lock.
/// This is the result of keccak256("ownerUUPS.reentry_slot") plus 1. The addition aims to
/// prevent hash collisions with slots defined in EIP-1967, where slots are derived by
/// keccak256("something") - 1, and with slots in SignalService, calculated directly with
/// keccak256("something").
bytes32 private constant _REENTRY_SLOT =
0xa5054f728453d3dbe953bdc43e4d0cb97e662ea32d7958190f3dc2da31d9721b;
/// @dev Slot 1.
uint8 private __reentry;
uint8 private __paused;
uint64 public lastUnpausedAt;
uint256[49] private __gap;
/// @notice Emitted when the contract is paused.
/// @param account The account that paused the contract.
event Paused(address account);
/// @notice Emitted when the contract is unpaused.
/// @param account The account that unpaused the contract.
event Unpaused(address account);
error INVALID_PAUSE_STATUS();
error FUNC_NOT_IMPLEMENTED();
error REENTRANT_CALL();
error ZERO_ADDRESS();
error ZERO_VALUE();
/// @dev Modifier that ensures the caller is the owner or resolved address of a given name.
/// @param _name The name to check against.
modifier onlyFromOwnerOrNamed(bytes32 _name) {
if (msg.sender != owner() && msg.sender != resolve(_name, true)) revert RESOLVER_DENIED();
_;
}
modifier notImplemented() {
revert FUNC_NOT_IMPLEMENTED();
_;
}
modifier nonReentrant() {
if (_loadReentryLock() == _TRUE) revert REENTRANT_CALL();
_storeReentryLock(_TRUE);
_;
_storeReentryLock(_FALSE);
}
modifier whenPaused() {
if (!paused()) revert INVALID_PAUSE_STATUS();
_;
}
modifier whenNotPaused() {
if (paused()) revert INVALID_PAUSE_STATUS();
_;
}
modifier nonZeroAddr(address _addr) {
if (_addr == address(0)) revert ZERO_ADDRESS();
_;
}
modifier nonZeroValue(bytes32 _value) {
if (_value == 0) revert ZERO_VALUE();
_;
}
/// @custom:oz-upgrades-unsafe-allow constructor
constructor() {
_disableInitializers();
}
/// @notice Pauses the contract.
function pause() public virtual {
_pause();
// We call the authorize function here to avoid:
// Warning (5740): Unreachable code.
_authorizePause(msg.sender, true);
}
/// @notice Unpauses the contract.
function unpause() public virtual {
_unpause();
// We call the authorize function here to avoid:
// Warning (5740): Unreachable code.
_authorizePause(msg.sender, false);
}
function impl() public view returns (address) {
return _getImplementation();
}
/// @notice Returns true if the contract is paused, and false otherwise.
/// @return true if paused, false otherwise.
function paused() public view returns (bool) {
return __paused == _TRUE;
}
function inNonReentrant() public view returns (bool) {
return _loadReentryLock() == _TRUE;
}
/// @notice Initializes the contract.
/// @param _owner The owner of this contract. msg.sender will be used if this value is zero.
/// @param _addressManager The address of the {AddressManager} contract.
function __Essential_init(
address _owner,
address _addressManager
)
internal
nonZeroAddr(_addressManager)
{
__Essential_init(_owner);
__AddressResolver_init(_addressManager);
}
function __Essential_init(address _owner) internal virtual onlyInitializing {
__Context_init();
_transferOwnership(_owner == address(0) ? msg.sender : _owner);
__paused = _FALSE;
}
function _pause() internal whenNotPaused {
__paused = _TRUE;
emit Paused(msg.sender);
}
function _unpause() internal whenPaused {
__paused = _FALSE;
lastUnpausedAt = uint64(block.timestamp);
emit Unpaused(msg.sender);
}
function _authorizeUpgrade(address) internal virtual override onlyOwner { }
function _authorizePause(address, bool) internal virtual onlyOwner { }
// Stores the reentry lock
function _storeReentryLock(uint8 _reentry) internal virtual {
if (LibNetwork.isDencunSupported(block.chainid)) {
assembly {
tstore(_REENTRY_SLOT, _reentry)
}
} else {
__reentry = _reentry;
}
}
// Loads the reentry lock
function _loadReentryLock() internal view virtual returns (uint8 reentry_) {
if (LibNetwork.isDencunSupported(block.chainid)) {
assembly {
reentry_ := tload(_REENTRY_SLOT)
}
} else {
reentry_ = __reentry;
}
}
}
contracts/common/IAddressManager.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.24;
/// @title IAddressManager
/// @notice Manages a mapping of (chainId, name) pairs to Ethereum addresses.
/// @custom:security-contact security@taiko.xyz
interface IAddressManager {
/// @notice Gets the address mapped to a specific chainId-name pair.
/// @dev Note that in production, this method shall be a pure function
/// without any storage access.
/// @param _chainId The chainId for which the address needs to be fetched.
/// @param _name The name for which the address needs to be fetched.
/// @return Address associated with the chainId-name pair.
function getAddress(uint64 _chainId, bytes32 _name) external view returns (address);
}
contracts/common/IAddressResolver.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.24;
/// @title IAddressResolver
/// @notice This contract acts as a bridge for name-to-address resolution.
/// It delegates the resolution to the AddressManager. By separating the logic,
/// we can maintain flexibility in address management without affecting the
/// resolving process.
/// @dev Note that the address manager should be changed using upgradability, there
/// is no setAddressManager() function to guarantee atomicity across all
/// contracts that are resolvers.
/// @custom:security-contact security@taiko.xyz
interface IAddressResolver {
/// @notice Resolves a name to its address deployed on this chain.
/// @param _name Name whose address is to be resolved.
/// @param _allowZeroAddress If set to true, does not throw if the resolved
/// address is `address(0)`.
/// @return Address associated with the given name.
function resolve(
bytes32 _name,
bool _allowZeroAddress
)
external
view
returns (address payable);
/// @notice Resolves a name to its address deployed on a specified chain.
/// @param _chainId The chainId of interest.
/// @param _name Name whose address is to be resolved.
/// @param _allowZeroAddress If set to true, does not throw if the resolved
/// address is `address(0)`.
/// @return Address associated with the given name on the specified
/// chain.
function resolve(
uint64 _chainId,
bytes32 _name,
bool _allowZeroAddress
)
external
view
returns (address payable);
}
contracts/common/LibStrings.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.24;
/// @title LibStrings
/// @custom:security-contact security@taiko.xyz
library LibStrings {
bytes32 internal constant B_ASSIGNMENT_HOOK = bytes32("assignment_hook");
bytes32 internal constant B_AUTOMATA_DCAP_ATTESTATION = bytes32("automata_dcap_attestation");
bytes32 internal constant B_BRIDGE = bytes32("bridge");
bytes32 internal constant B_BRIDGE_WATCHDOG = bytes32("bridge_watchdog");
bytes32 internal constant B_BRIDGED_ERC1155 = bytes32("bridged_erc1155");
bytes32 internal constant B_BRIDGED_ERC20 = bytes32("bridged_erc20");
bytes32 internal constant B_BRIDGED_ERC721 = bytes32("bridged_erc721");
bytes32 internal constant B_CHAIN_WATCHDOG = bytes32("chain_watchdog");
bytes32 internal constant B_ERC1155_VAULT = bytes32("erc1155_vault");
bytes32 internal constant B_ERC20_VAULT = bytes32("erc20_vault");
bytes32 internal constant B_ERC721_VAULT = bytes32("erc721_vault");
bytes32 internal constant B_PROPOSER = bytes32("proposer");
bytes32 internal constant B_PROPOSER_ONE = bytes32("proposer_one");
bytes32 internal constant B_PROVER_ASSIGNMENT = bytes32("PROVER_ASSIGNMENT");
bytes32 internal constant B_PROVER_SET = bytes32("prover_set");
bytes32 internal constant B_QUOTA_MANAGER = bytes32("quota_manager");
bytes32 internal constant B_SGX_WATCHDOG = bytes32("sgx_watchdog");
bytes32 internal constant B_SIGNAL_SERVICE = bytes32("signal_service");
bytes32 internal constant B_TAIKO = bytes32("taiko");
bytes32 internal constant B_TAIKO_TOKEN = bytes32("taiko_token");
bytes32 internal constant B_TIER_GUARDIAN = bytes32("tier_guardian");
bytes32 internal constant B_TIER_GUARDIAN_MINORITY = bytes32("tier_guardian_minority");
bytes32 internal constant B_TIER_PROVIDER = bytes32("tier_provider");
bytes32 internal constant B_TIER_SGX = bytes32("tier_sgx");
bytes32 internal constant B_TIER_SGX_ZKVM = bytes32("tier_sgx_zkvm");
bytes32 internal constant B_WITHDRAWER = bytes32("withdrawer");
bytes32 internal constant H_RETURN_LIVENESS_BOND = keccak256("RETURN_LIVENESS_BOND");
bytes32 internal constant H_SIGNAL_ROOT = keccak256("SIGNAL_ROOT");
bytes32 internal constant H_STATE_ROOT = keccak256("STATE_ROOT");
}
contracts/libs/LibNetwork.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.24;
/// @title LibNetwork
library LibNetwork {
uint256 internal constant MAINNET = 1;
uint256 internal constant ROPSTEN = 2;
uint256 internal constant RINKEBY = 4;
uint256 internal constant GOERLI = 5;
uint256 internal constant KOVAN = 42;
uint256 internal constant HOLESKY = 17_000;
uint256 internal constant SEPOLIA = 11_155_111;
uint64 internal constant TAIKO = 167_000;
/// @dev Checks if the chain ID represents an Ethereum testnet.
/// @param _chainId The chain ID.
/// @return true if the chain ID represents an Ethereum testnet, false otherwise.
function isEthereumTestnet(uint256 _chainId) internal pure returns (bool) {
return _chainId == LibNetwork.ROPSTEN || _chainId == LibNetwork.RINKEBY
|| _chainId == LibNetwork.GOERLI || _chainId == LibNetwork.KOVAN
|| _chainId == LibNetwork.HOLESKY || _chainId == LibNetwork.SEPOLIA;
}
/// @dev Checks if the chain ID represents an Ethereum testnet or the Etheruem mainnet.
/// @param _chainId The chain ID.
/// @return true if the chain ID represents an Ethereum testnet or the Etheruem mainnet, false
/// otherwise.
function isEthereumMainnetOrTestnet(uint256 _chainId) internal pure returns (bool) {
return _chainId == LibNetwork.MAINNET || isEthereumTestnet(_chainId);
}
/// @dev Checks if the chain ID represents the Taiko L2 mainnet.
/// @param _chainId The chain ID.
/// @return true if the chain ID represents the Taiko L2 mainnet.
function isTaikoMainnet(uint256 _chainId) internal pure returns (bool) {
return _chainId == TAIKO;
}
/// @dev Checks if the chain ID represents an internal Taiko devnet's base layer.
/// @param _chainId The chain ID.
/// @return true if the chain ID represents an internal Taiko devnet's base layer, false
/// otherwise.
function isTaikoDevnet(uint256 _chainId) internal pure returns (bool) {
return _chainId >= 32_300 && _chainId <= 32_400;
}
/// @dev Checks if the chain supports Dencun hardfork. Note that this check doesn't need to be
/// exhaustive.
/// @param _chainId The chain ID.
/// @return true if the chain supports Dencun hardfork, false otherwise.
function isDencunSupported(uint256 _chainId) internal pure returns (bool) {
return _chainId == LibNetwork.MAINNET || _chainId == LibNetwork.HOLESKY
|| _chainId == LibNetwork.SEPOLIA || isTaikoDevnet(_chainId);
}
}
contracts/libs/LibTrieProof.sol
// SPDX-License-Identifier: MIT
// _____ _ _ _ _
// |_ _|_ _(_) |_____ | | __ _| |__ ___
// | |/ _` | | / / _ \ | |__/ _` | '_ (_-<
// |_|\__,_|_|_\_\___/ |____\__,_|_.__/__/
pragma solidity 0.8.24;
import "../thirdparty/optimism/rlp/RLPReader.sol";
import "../thirdparty/optimism/rlp/RLPWriter.sol";
import "../thirdparty/optimism/trie/SecureMerkleTrie.sol";
/// @title LibTrieProof
/// @custom:security-contact security@taiko.xyz
library LibTrieProof {
// The consensus format representing account is RLP encoded in the
// following order: nonce, balance, storageHash, codeHash.
uint256 private constant _ACCOUNT_FIELD_INDEX_STORAGE_HASH = 2;
error LTP_INVALID_ACCOUNT_PROOF();
error LTP_INVALID_INCLUSION_PROOF();
/// @notice Verifies that the value of a slot in the storage of an account is value.
///
/// @param _rootHash The merkle root of state tree or the account tree. If accountProof's length
/// is zero, it is used as the account's storage root, otherwise it will be used as the state
/// root.
/// @param _addr The address of contract.
/// @param _slot The slot in the contract.
/// @param _value The value to be verified.
/// @param _accountProof The account proof
/// @param _storageProof The storage proof
/// @return storageRoot_ The account's storage root
function verifyMerkleProof(
bytes32 _rootHash,
address _addr,
bytes32 _slot,
bytes32 _value,
bytes[] memory _accountProof,
bytes[] memory _storageProof
)
internal
pure
returns (bytes32 storageRoot_)
{
if (_accountProof.length != 0) {
bytes memory rlpAccount =
SecureMerkleTrie.get(abi.encodePacked(_addr), _accountProof, _rootHash);
if (rlpAccount.length == 0) revert LTP_INVALID_ACCOUNT_PROOF();
RLPReader.RLPItem[] memory accountState = RLPReader.readList(rlpAccount);
storageRoot_ =
bytes32(RLPReader.readBytes(accountState[_ACCOUNT_FIELD_INDEX_STORAGE_HASH]));
} else {
storageRoot_ = _rootHash;
}
bool verified = SecureMerkleTrie.verifyInclusionProof(
bytes.concat(_slot), RLPWriter.writeUint(uint256(_value)), _storageProof, storageRoot_
);
if (!verified) revert LTP_INVALID_INCLUSION_PROOF();
}
}
contracts/signal/ISignalService.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.24;
/// @title ISignalService
/// @notice The SignalService contract serves as a secure cross-chain message
/// passing system. It defines methods for sending and verifying signals with
/// merkle proofs. The trust assumption is that the target chain has secure
/// access to the merkle root (such as Taiko injects it in the anchor
/// transaction). With this, verifying a signal is reduced to simply verifying
/// a merkle proof.
/// @custom:security-contact security@taiko.xyz
interface ISignalService {
enum CacheOption {
CACHE_NOTHING,
CACHE_SIGNAL_ROOT,
CACHE_STATE_ROOT,
CACHE_BOTH
}
struct HopProof {
/// @notice This hop's destination chain ID. If there is a next hop, this ID is the next
/// hop's source chain ID.
uint64 chainId;
/// @notice The ID of a source chain block whose state root has been synced to the hop's
/// destination chain.
/// Note that this block ID must be greater than or equal to the block ID where the signal
/// was sent on the source chain.
uint64 blockId;
/// @notice The state root or signal root of the source chain at the above blockId. This
/// value has been synced to the destination chain.
/// @dev To get both the blockId and the rootHash, apps should subscribe to the
/// ChainDataSynced event or query `topBlockId` first using the source chain's ID and
/// LibStrings.H_STATE_ROOT to get the most recent block ID synced, then call
/// `getSyncedChainData` to read the synchronized data.
bytes32 rootHash;
/// @notice Options to cache either the state roots or signal roots of middle-hops to the
/// current chain.
CacheOption cacheOption;
/// @notice The signal service's account proof. If this value is empty, then `rootHash` will
/// be used as the signal root, otherwise, `rootHash` will be used as the state root.
bytes[] accountProof;
/// @notice The signal service's storage proof.
bytes[] storageProof;
}
/// @notice Emitted when a remote chain's state root or signal root is
/// synced locally as a signal.
/// @param chainId The remote chainId.
/// @param blockId The chain data's corresponding blockId.
/// @param kind A value to mark the data type.
/// @param data The remote data.
/// @param signal The signal for this chain data.
event ChainDataSynced(
uint64 indexed chainId,
uint64 indexed blockId,
bytes32 indexed kind,
bytes32 data,
bytes32 signal
);
/// @notice Emitted when a signal is sent.
/// @param app The address that initiated the signal.
/// @param signal The signal (message) that was sent.
/// @param slot The location in storage where this signal is stored.
/// @param value The value of the signal.
event SignalSent(address app, bytes32 signal, bytes32 slot, bytes32 value);
/// @notice Emitted when an address is authorized or deauthorized.
/// @param addr The address to be authorized or deauthorized.
/// @param authorized True if authorized, false otherwise.
event Authorized(address indexed addr, bool authorized);
/// @notice Send a signal (message) by setting the storage slot to a value of 1.
/// @param _signal The signal (message) to send.
/// @return slot_ The location in storage where this signal is stored.
function sendSignal(bytes32 _signal) external returns (bytes32 slot_);
/// @notice Sync a data from a remote chain locally as a signal. The signal is calculated
/// uniquely from chainId, kind, and data.
/// @param _chainId The remote chainId.
/// @param _kind A value to mark the data type.
/// @param _blockId The chain data's corresponding blockId
/// @param _chainData The remote data.
/// @return signal_ The signal for this chain data.
function syncChainData(
uint64 _chainId,
bytes32 _kind,
uint64 _blockId,
bytes32 _chainData
)
external
returns (bytes32 signal_);
/// @notice Verifies if a signal has been received on the target chain.
/// @param _chainId The identifier for the source chain from which the
/// signal originated.
/// @param _app The address that initiated the signal.
/// @param _signal The signal (message) to send.
/// @param _proof Merkle proof that the signal was persisted on the
/// source chain.
/// @return numCacheOps_ The number of newly cached items.
function proveSignalReceived(
uint64 _chainId,
address _app,
bytes32 _signal,
bytes calldata _proof
)
external
returns (uint256 numCacheOps_);
/// @notice Verifies if a signal has been received on the target chain.
/// This is the "readonly" version of proveSignalReceived.
/// @param _chainId The identifier for the source chain from which the
/// signal originated.
/// @param _app The address that initiated the signal.
/// @param _signal The signal (message) to send.
/// @param _proof Merkle proof that the signal was persisted on the
/// source chain.
function verifySignalReceived(
uint64 _chainId,
address _app,
bytes32 _signal,
bytes calldata _proof
)
external
view;
/// @notice Verifies if a particular signal has already been sent.
/// @param _app The address that initiated the signal.
/// @param _signal The signal (message) that was sent.
/// @return true if the signal has been sent, otherwise false.
function isSignalSent(address _app, bytes32 _signal) external view returns (bool);
/// @notice Checks if a chain data has been synced.
/// uniquely from chainId, kind, and data.
/// @param _chainId The remote chainId.
/// @param _kind A value to mark the data type.
/// @param _blockId The chain data's corresponding blockId
/// @param _chainData The remote data.
/// @return true if the data has been synced, otherwise false.
function isChainDataSynced(
uint64 _chainId,
bytes32 _kind,
uint64 _blockId,
bytes32 _chainData
)
external
view
returns (bool);
/// @notice Returns the given block's chain data.
/// @param _chainId Identifier of the chainId.
/// @param _kind A value to mark the data type.
/// @param _blockId The chain data's corresponding block id. If this value is 0, use the top
/// block id.
/// @return blockId_ The actual block id.
/// @return chainData_ The synced chain data.
function getSyncedChainData(
uint64 _chainId,
bytes32 _kind,
uint64 _blockId
)
external
view
returns (uint64 blockId_, bytes32 chainData_);
/// @notice Returns the data to be used for caching slot generation.
/// @param _chainId Identifier of the chainId.
/// @param _kind A value to mark the data type.
/// @param _blockId The chain data's corresponding block id. If this value is 0, use the top
/// block id.
/// @return signal_ The signal used for caching slot creation.
function signalForChainData(
uint64 _chainId,
bytes32 _kind,
uint64 _blockId
)
external
pure
returns (bytes32 signal_);
}
contracts/thirdparty/optimism/Bytes.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.24;
/// @title Bytes
/// @notice Bytes is a library for manipulating byte arrays.
library Bytes {
/// @custom:attribution https://github.com/GNSPS/solidity-bytes-utils
/// @notice Slices a byte array with a given starting index and length. Returns a new byte array
/// as opposed to a pointer to the original array. Will throw if trying to slice more
/// bytes than exist in the array.
/// @param _bytes Byte array to slice.
/// @param _start Starting index of the slice.
/// @param _length Length of the slice.
/// @return Slice of the input byte array.
function slice(
bytes memory _bytes,
uint256 _start,
uint256 _length
)
internal
pure
returns (bytes memory)
{
unchecked {
require(_length + 31 >= _length, "slice_overflow");
require(_start + _length >= _start, "slice_overflow");
require(_bytes.length >= _start + _length, "slice_outOfBounds");
}
bytes memory tempBytes;
assembly {
switch iszero(_length)
case 0 {
// Get a location of some free memory and store it in tempBytes as
// Solidity does for memory variables.
tempBytes := mload(0x40)
// The first word of the slice result is potentially a partial
// word read from the original array. To read it, we calculate
// the length of that partial word and start copying that many
// bytes into the array. The first word we copy will start with
// data we don't care about, but the last `lengthmod` bytes will
// land at the beginning of the contents of the new array. When
// we're done copying, we overwrite the full first word with
// the actual length of the slice.
let lengthmod := and(_length, 31)
// The multiplication in the next line is necessary
// because when slicing multiples of 32 bytes (lengthmod == 0)
// the following copy loop was copying the origin's length
// and then ending prematurely not copying everything it should.
let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod)))
let end := add(mc, _length)
for {
// The multiplication in the next line has the same exact purpose
// as the one above.
let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), _start)
} lt(mc, end) {
mc := add(mc, 0x20)
cc := add(cc, 0x20)
} { mstore(mc, mload(cc)) }
mstore(tempBytes, _length)
//update free-memory pointer
//allocating the array padded to 32 bytes like the compiler does now
mstore(0x40, and(add(mc, 31), not(31)))
}
//if we want a zero-length slice let's just return a zero-length array
default {
tempBytes := mload(0x40)
//zero out the 32 bytes slice we are about to return
//we need to do it because Solidity does not garbage collect
mstore(tempBytes, 0)
mstore(0x40, add(tempBytes, 0x20))
}
}
return tempBytes;
}
/// @notice Slices a byte array with a given starting index up to the end of the original byte
/// array. Returns a new array rather than a pointer to the original.
/// @param _bytes Byte array to slice.
/// @param _start Starting index of the slice.
/// @return Slice of the input byte array.
function slice(bytes memory _bytes, uint256 _start) internal pure returns (bytes memory) {
if (_start >= _bytes.length) {
return bytes("");
}
return slice(_bytes, _start, _bytes.length - _start);
}
/// @notice Converts a byte array into a nibble array by splitting each byte into two nibbles.
/// Resulting nibble array will be exactly twice as long as the input byte array.
/// @param _bytes Input byte array to convert.
/// @return Resulting nibble array.
function toNibbles(bytes memory _bytes) internal pure returns (bytes memory) {
bytes memory _nibbles;
assembly {
// Grab a free memory offset for the new array
_nibbles := mload(0x40)
// Load the length of the passed bytes array from memory
let bytesLength := mload(_bytes)
// Calculate the length of the new nibble array
// This is the length of the input array times 2
let nibblesLength := shl(0x01, bytesLength)
// Update the free memory pointer to allocate memory for the new array.
// To do this, we add the length of the new array + 32 bytes for the array length
// rounded up to the nearest 32 byte boundary to the current free memory pointer.
mstore(0x40, add(_nibbles, and(not(0x1F), add(nibblesLength, 0x3F))))
// Store the length of the new array in memory
mstore(_nibbles, nibblesLength)
// Store the memory offset of the _bytes array's contents on the stack
let bytesStart := add(_bytes, 0x20)
// Store the memory offset of the nibbles array's contents on the stack
let nibblesStart := add(_nibbles, 0x20)
// Loop through each byte in the input array
for { let i := 0x00 } lt(i, bytesLength) { i := add(i, 0x01) } {
// Get the starting offset of the next 2 bytes in the nibbles array
let offset := add(nibblesStart, shl(0x01, i))
// Load the byte at the current index within the `_bytes` array
let b := byte(0x00, mload(add(bytesStart, i)))
// Pull out the first nibble and store it in the new array
mstore8(offset, shr(0x04, b))
// Pull out the second nibble and store it in the new array
mstore8(add(offset, 0x01), and(b, 0x0F))
}
}
return _nibbles;
}
/// @notice Compares two byte arrays by comparing their keccak256 hashes.
/// @param _bytes First byte array to compare.
/// @param _other Second byte array to compare.
/// @return true if the two byte arrays are equal, false otherwise.
function equal(bytes memory _bytes, bytes memory _other) internal pure returns (bool) {
return keccak256(_bytes) == keccak256(_other);
}
}
contracts/thirdparty/optimism/rlp/RLPReader.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.24;
/// @custom:attribution https://github.com/hamdiallam/Solidity-RLP
/// @title RLPReader
/// @notice RLPReader is a library for parsing RLP-encoded byte arrays into Solidity types. Adapted
/// from Solidity-RLP (https://github.com/hamdiallam/Solidity-RLP) by Hamdi Allam with
/// various tweaks to improve readability. (A shout-out to Optimism !)
library RLPReader {
/// @notice Custom pointer type to avoid confusion between pointers and uint256s.
type MemoryPointer is uint256;
/// @notice RLP item types.
/// @custom:value DATA_ITEM Represents an RLP data item (NOT a list).
/// @custom:value LIST_ITEM Represents an RLP list item.
enum RLPItemType {
DATA_ITEM,
LIST_ITEM
}
/// @notice Struct representing an RLP item.
/// @custom:field length Length of the RLP item.
/// @custom:field ptr Pointer to the RLP item in memory.
struct RLPItem {
uint256 length;
MemoryPointer ptr;
}
/// @notice Max list length that this library will accept.
uint256 internal constant MAX_LIST_LENGTH = 32;
/// @notice Converts bytes to a reference to memory position and length.
/// @param _in Input bytes to convert.
/// @return out_ Output memory reference.
function toRLPItem(bytes memory _in) internal pure returns (RLPItem memory out_) {
// Empty arrays are not RLP items.
require(
_in.length > 0,
"RLPReader: length of an RLP item must be greater than zero to be decodable"
);
MemoryPointer ptr;
assembly {
ptr := add(_in, 32)
}
out_ = RLPItem({ length: _in.length, ptr: ptr });
}
/// @notice Reads an RLP list value into a list of RLP items.
/// @param _in RLP list value.
/// @return out_ Decoded RLP list items.
function readList(RLPItem memory _in) internal pure returns (RLPItem[] memory out_) {
(uint256 listOffset, uint256 listLength, RLPItemType itemType) = _decodeLength(_in);
require(
itemType == RLPItemType.LIST_ITEM,
"RLPReader: decoded item type for list is not a list item"
);
require(
listOffset + listLength == _in.length,
"RLPReader: list item has an invalid data remainder"
);
// Solidity in-memory arrays can't be increased in size, but *can* be decreased in size by
// writing to the length. Since we can't know the number of RLP items without looping over
// the entire input, we'd have to loop twice to accurately size this array. It's easier to
// simply set a reasonable maximum list length and decrease the size before we finish.
out_ = new RLPItem[](MAX_LIST_LENGTH);
uint256 itemCount = 0;
uint256 offset = listOffset;
while (offset < _in.length) {
(uint256 itemOffset, uint256 itemLength,) = _decodeLength(
RLPItem({
length: _in.length - offset,
ptr: MemoryPointer.wrap(MemoryPointer.unwrap(_in.ptr) + offset)
})
);
// We don't need to check itemCount < out.length explicitly because Solidity already
// handles this check on our behalf, we'd just be wasting gas.
out_[itemCount] = RLPItem({
length: itemLength + itemOffset,
ptr: MemoryPointer.wrap(MemoryPointer.unwrap(_in.ptr) + offset)
});
itemCount += 1;
offset += itemOffset + itemLength;
}
// Decrease the array size to match the actual item count.
assembly {
mstore(out_, itemCount)
}
}
/// @notice Reads an RLP list value into a list of RLP items.
/// @param _in RLP list value.
/// @return out_ Decoded RLP list items.
function readList(bytes memory _in) internal pure returns (RLPItem[] memory out_) {
out_ = readList(toRLPItem(_in));
}
/// @notice Reads an RLP bytes value into bytes.
/// @param _in RLP bytes value.
/// @return out_ Decoded bytes.
function readBytes(RLPItem memory _in) internal pure returns (bytes memory out_) {
(uint256 itemOffset, uint256 itemLength, RLPItemType itemType) = _decodeLength(_in);
require(
itemType == RLPItemType.DATA_ITEM,
"RLPReader: decoded item type for bytes is not a data item"
);
require(
_in.length == itemOffset + itemLength,
"RLPReader: bytes value contains an invalid remainder"
);
out_ = _copy(_in.ptr, itemOffset, itemLength);
}
/// @notice Reads an RLP bytes value into bytes.
/// @param _in RLP bytes value.
/// @return out_ Decoded bytes.
function readBytes(bytes memory _in) internal pure returns (bytes memory out_) {
out_ = readBytes(toRLPItem(_in));
}
/// @notice Reads the raw bytes of an RLP item.
/// @param _in RLP item to read.
/// @return out_ Raw RLP bytes.
function readRawBytes(RLPItem memory _in) internal pure returns (bytes memory out_) {
out_ = _copy(_in.ptr, 0, _in.length);
}
/// @notice Decodes the length of an RLP item.
/// @param _in RLP item to decode.
/// @return offset_ Offset of the encoded data.
/// @return length_ Length of the encoded data.
/// @return type_ RLP item type (LIST_ITEM or DATA_ITEM).
function _decodeLength(RLPItem memory _in)
private
pure
returns (uint256 offset_, uint256 length_, RLPItemType type_)
{
// Short-circuit if there's nothing to decode, note that we perform this check when
// the user creates an RLP item via toRLPItem, but it's always possible for them to bypass
// that function and create an RLP item directly. So we need to check this anyway.
require(
_in.length > 0,
"RLPReader: length of an RLP item must be greater than zero to be decodable"
);
MemoryPointer ptr = _in.ptr;
uint256 prefix;
assembly {
prefix := byte(0, mload(ptr))
}
if (prefix <= 0x7f) {
// Single byte.
return (0, 1, RLPItemType.DATA_ITEM);
} else if (prefix <= 0xb7) {
// Short string.
// slither-disable-next-line variable-scope
uint256 strLen = prefix - 0x80;
require(
_in.length > strLen,
"RLPReader: length of content must be greater than string length (short string)"
);
bytes1 firstByteOfContent;
assembly {
firstByteOfContent := and(mload(add(ptr, 1)), shl(248, 0xff))
}
require(
strLen != 1 || firstByteOfContent >= 0x80,
"RLPReader: invalid prefix, single byte < 0x80 are not prefixed (short string)"
);
return (1, strLen, RLPItemType.DATA_ITEM);
} else if (prefix <= 0xbf) {
// Long string.
uint256 lenOfStrLen = prefix - 0xb7;
require(
_in.length > lenOfStrLen,
"RLPReader: length of content must be > than length of string length (long string)"
);
bytes1 firstByteOfContent;
assembly {
firstByteOfContent := and(mload(add(ptr, 1)), shl(248, 0xff))
}
require(
firstByteOfContent != 0x00,
"RLPReader: length of content must not have any leading zeros (long string)"
);
uint256 strLen;
assembly {
strLen := shr(sub(256, mul(8, lenOfStrLen)), mload(add(ptr, 1)))
}
require(
strLen > 55,
"RLPReader: length of content must be greater than 55 bytes (long string)"
);
require(
_in.length > lenOfStrLen + strLen,
"RLPReader: length of content must be greater than total length (long string)"
);
return (1 + lenOfStrLen, strLen, RLPItemType.DATA_ITEM);
} else if (prefix <= 0xf7) {
// Short list.
// slither-disable-next-line variable-scope
uint256 listLen = prefix - 0xc0;
require(
_in.length > listLen,
"RLPReader: length of content must be greater than list length (short list)"
);
return (1, listLen, RLPItemType.LIST_ITEM);
} else {
// Long list.
uint256 lenOfListLen = prefix - 0xf7;
require(
_in.length > lenOfListLen,
"RLPReader: length of content must be > than length of list length (long list)"
);
bytes1 firstByteOfContent;
assembly {
firstByteOfContent := and(mload(add(ptr, 1)), shl(248, 0xff))
}
require(
firstByteOfContent != 0x00,
"RLPReader: length of content must not have any leading zeros (long list)"
);
uint256 listLen;
assembly {
listLen := shr(sub(256, mul(8, lenOfListLen)), mload(add(ptr, 1)))
}
require(
listLen > 55,
"RLPReader: length of content must be greater than 55 bytes (long list)"
);
require(
_in.length > lenOfListLen + listLen,
"RLPReader: length of content must be greater than total length (long list)"
);
return (1 + lenOfListLen, listLen, RLPItemType.LIST_ITEM);
}
}
/// @notice Copies the bytes from a memory location.
/// @param _src Pointer to the location to read from.
/// @param _offset Offset to start reading from.
/// @param _length Number of bytes to read.
/// @return out_ Copied bytes.
function _copy(
MemoryPointer _src,
uint256 _offset,
uint256 _length
)
private
pure
returns (bytes memory out_)
{
out_ = new bytes(_length);
if (_length == 0) {
return out_;
}
// Mostly based on Solidity's copy_memory_to_memory:
// solhint-disable max-line-length
// https://github.com/ethereum/solidity/blob/34dd30d71b4da730488be72ff6af7083cf2a91f6/libsolidity/codegen/YulUtilFunctions.cpp#L102-L114
uint256 src = MemoryPointer.unwrap(_src) + _offset;
assembly {
let dest := add(out_, 32)
let i := 0
for { } lt(i, _length) { i := add(i, 32) } { mstore(add(dest, i), mload(add(src, i))) }
if gt(i, _length) { mstore(add(dest, _length), 0) }
}
}
}
contracts/thirdparty/optimism/rlp/RLPWriter.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.24;
/// @custom:attribution https://github.com/bakaoh/solidity-rlp-encode
/// @title RLPWriter
/// @author RLPWriter is a library for encoding Solidity types to RLP bytes. Adapted from Bakaoh's
/// RLPEncode library (https://github.com/bakaoh/solidity-rlp-encode) with minor
/// modifications to improve legibility. (A shout-out to Optimism !)
library RLPWriter {
/// @notice RLP encodes a byte string.
/// @param _in The byte string to encode.
/// @return out_ The RLP encoded string in bytes.
function writeBytes(bytes memory _in) internal pure returns (bytes memory out_) {
if (_in.length == 1 && uint8(_in[0]) < 128) {
out_ = _in;
} else {
out_ = abi.encodePacked(_writeLength(_in.length, 128), _in);
}
}
/// @notice RLP encodes a uint.
/// @param _in The uint256 to encode.
/// @return out_ The RLP encoded uint256 in bytes.
function writeUint(uint256 _in) internal pure returns (bytes memory out_) {
out_ = writeBytes(_toBinary(_in));
}
/// @notice Encode the first byte and then the `len` in binary form if `length` is more than 55.
/// @param _len The length of the string or the payload.
/// @param _offset 128 if item is string, 192 if item is list.
/// @return out_ RLP encoded bytes.
function _writeLength(uint256 _len, uint256 _offset) private pure returns (bytes memory out_) {
if (_len < 56) {
out_ = new bytes(1);
out_[0] = bytes1(uint8(_len) + uint8(_offset));
} else {
uint256 lenLen;
uint256 i = 1;
while (_len / i != 0) {
lenLen++;
i *= 256;
}
out_ = new bytes(lenLen + 1);
out_[0] = bytes1(uint8(lenLen) + uint8(_offset) + 55);
for (i = 1; i <= lenLen; i++) {
out_[i] = bytes1(uint8((_len / (256 ** (lenLen - i))) % 256));
}
}
}
/// @notice Encode integer in big endian binary form with no leading zeroes.
/// @param _x The integer to encode.
/// @return out_ RLP encoded bytes.
function _toBinary(uint256 _x) private pure returns (bytes memory out_) {
bytes memory b = abi.encodePacked(_x);
uint256 i = 0;
for (; i < 32; i++) {
if (b[i] != 0) {
break;
}
}
out_ = new bytes(32 - i);
for (uint256 j = 0; j < out_.length; j++) {
out_[j] = b[i++];
}
}
}
contracts/thirdparty/optimism/trie/MerkleTrie.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.24;
import { Bytes } from "../Bytes.sol";
import { RLPReader } from "../rlp/RLPReader.sol";
/// @title MerkleTrie
/// @notice MerkleTrie is a small library for verifying standard Ethereum Merkle-Patricia trie
/// inclusion proofs. By default, this library assumes a hexary trie. One can change the
/// trie radix constant to support other trie radixes.
library MerkleTrie {
/// @notice Struct representing a node in the trie.
/// @custom:field encoded The RLP-encoded node.
/// @custom:field decoded The RLP-decoded node.
struct TrieNode {
bytes encoded;
RLPReader.RLPItem[] decoded;
}
/// @notice Determines the number of elements per branch node.
uint256 internal constant TREE_RADIX = 16;
/// @notice Branch nodes have TREE_RADIX elements and one value element.
uint256 internal constant BRANCH_NODE_LENGTH = TREE_RADIX + 1;
/// @notice Leaf nodes and extension nodes have two elements, a `path` and a `value`.
uint256 internal constant LEAF_OR_EXTENSION_NODE_LENGTH = 2;
/// @notice Prefix for even-nibbled extension node paths.
uint8 internal constant PREFIX_EXTENSION_EVEN = 0;
/// @notice Prefix for odd-nibbled extension node paths.
uint8 internal constant PREFIX_EXTENSION_ODD = 1;
/// @notice Prefix for even-nibbled leaf node paths.
uint8 internal constant PREFIX_LEAF_EVEN = 2;
/// @notice Prefix for odd-nibbled leaf node paths.
uint8 internal constant PREFIX_LEAF_ODD = 3;
/// @notice Verifies a proof that a given key/value pair is present in the trie.
/// @param _key Key of the node to search for, as a hex string.
/// @param _value Value of the node to search for, as a hex string.
/// @param _proof Merkle trie inclusion proof for the desired node. Unlike traditional Merkle
/// trees, this proof is executed top-down and consists of a list of RLP-encoded
/// nodes that make a path down to the target node.
/// @param _root Known root of the Merkle trie. Used to verify that the included proof is
/// correctly constructed.
/// @return valid_ Whether or not the proof is valid.
function verifyInclusionProof(
bytes memory _key,
bytes memory _value,
bytes[] memory _proof,
bytes32 _root
)
internal
pure
returns (bool valid_)
{
valid_ = Bytes.equal(_value, get(_key, _proof, _root));
}
/// @notice Retrieves the value associated with a given key.
/// @param _key Key to search for, as hex bytes.
/// @param _proof Merkle trie inclusion proof for the key.
/// @param _root Known root of the Merkle trie.
/// @return value_ Value of the key if it exists.
function get(
bytes memory _key,
bytes[] memory _proof,
bytes32 _root
)
internal
pure
returns (bytes memory value_)
{
require(_key.length > 0, "MerkleTrie: empty key");
TrieNode[] memory proof = _parseProof(_proof);
bytes memory key = Bytes.toNibbles(_key);
bytes memory currentNodeID = abi.encodePacked(_root);
uint256 currentKeyIndex = 0;
// Proof is top-down, so we start at the first element (root).
for (uint256 i = 0; i < proof.length; i++) {
TrieNode memory currentNode = proof[i];
// Key index should never exceed total key length or we'll be out of bounds.
require(currentKeyIndex <= key.length, "MerkleTrie: key index exceeds total key length");
if (currentKeyIndex == 0) {
// First proof element is always the root node.
require(
Bytes.equal(abi.encodePacked(keccak256(currentNode.encoded)), currentNodeID),
"MerkleTrie: invalid root hash"
);
} else if (currentNode.encoded.length >= 32) {
// Nodes 32 bytes or larger are hashed inside branch nodes.
require(
Bytes.equal(abi.encodePacked(keccak256(currentNode.encoded)), currentNodeID),
"MerkleTrie: invalid large internal hash"
);
} else {
// Nodes smaller than 32 bytes aren't hashed.
require(
Bytes.equal(currentNode.encoded, currentNodeID),
"MerkleTrie: invalid internal node hash"
);
}
if (currentNode.decoded.length == BRANCH_NODE_LENGTH) {
if (currentKeyIndex == key.length) {
// Value is the last element of the decoded list (for branch nodes). There's
// some ambiguity in the Merkle trie specification because bytes(0) is a
// valid value to place into the trie, but for branch nodes bytes(0) can exist
// even when the value wasn't explicitly placed there. Geth treats a value of
// bytes(0) as "key does not exist" and so we do the same.
value_ = RLPReader.readBytes(currentNode.decoded[TREE_RADIX]);
require(
value_.length > 0,
"MerkleTrie: value length must be greater than zero (branch)"
);
// Extra proof elements are not allowed.
require(
i == proof.length - 1,
"MerkleTrie: value node must be last node in proof (branch)"
);
return value_;
} else {
// We're not at the end of the key yet.
// Figure out what the next node ID should be and continue.
uint8 branchKey = uint8(key[currentKeyIndex]);
RLPReader.RLPItem memory nextNode = currentNode.decoded[branchKey];
currentNodeID = _getNodeID(nextNode);
currentKeyIndex += 1;
}
} else if (currentNode.decoded.length == LEAF_OR_EXTENSION_NODE_LENGTH) {
bytes memory path = _getNodePath(currentNode);
uint8 prefix = uint8(path[0]);
uint8 offset = 2 - (prefix % 2);
bytes memory pathRemainder = Bytes.slice(path, offset);
bytes memory keyRemainder = Bytes.slice(key, currentKeyIndex);
uint256 sharedNibbleLength = _getSharedNibbleLength(pathRemainder, keyRemainder);
// Whether this is a leaf node or an extension node, the path remainder MUST be a
// prefix of the key remainder (or be equal to the key remainder) or the proof is
// considered invalid.
require(
pathRemainder.length == sharedNibbleLength,
"MerkleTrie: path remainder must share all nibbles with key"
);
if (prefix == PREFIX_LEAF_EVEN || prefix == PREFIX_LEAF_ODD) {
// Prefix of 2 or 3 means this is a leaf node. For the leaf node to be valid,
// the key remainder must be exactly equal to the path remainder. We already
// did the necessary byte comparison, so it's more efficient here to check that
// the key remainder length equals the shared nibble length, which implies
// equality with the path remainder (since we already did the same check with
// the path remainder and the shared nibble length).
require(
keyRemainder.length == sharedNibbleLength,
"MerkleTrie: key remainder must be identical to path remainder"
);
// Our Merkle Trie is designed specifically for the purposes of the Ethereum
// state trie. Empty values are not allowed in the state trie, so we can safely
// say that if the value is empty, the key should not exist and the proof is
// invalid.
value_ = RLPReader.readBytes(currentNode.decoded[1]);
require(
value_.length > 0,
"MerkleTrie: value length must be greater than zero (leaf)"
);
// Extra proof elements are not allowed.
require(
i == proof.length - 1,
"MerkleTrie: value node must be last node in proof (leaf)"
);
return value_;
} else if (prefix == PREFIX_EXTENSION_EVEN || prefix == PREFIX_EXTENSION_ODD) {
// Prefix of 0 or 1 means this is an extension node. We move onto the next node
// in the proof and increment the key index by the length of the path remainder
// which is equal to the shared nibble length.
currentNodeID = _getNodeID(currentNode.decoded[1]);
currentKeyIndex += sharedNibbleLength;
} else {
revert("MerkleTrie: received a node with an unknown prefix");
}
} else {
revert("MerkleTrie: received an unparseable node");
}
}
revert("MerkleTrie: ran out of proof elements");
}
/// @notice Parses an array of proof elements into a new array that contains both the original
/// encoded element and the RLP-decoded element.
/// @param _proof Array of proof elements to parse.
/// @return proof_ Proof parsed into easily accessible structs.
function _parseProof(bytes[] memory _proof) private pure returns (TrieNode[] memory proof_) {
uint256 length = _proof.length;
proof_ = new TrieNode[](length);
for (uint256 i = 0; i < length; ++i) {
proof_[i] = TrieNode({ encoded: _proof[i], decoded: RLPReader.readList(_proof[i]) });
}
}
/// @notice Picks out the ID for a node. Node ID is referred to as the "hash" within the
/// specification, but nodes < 32 bytes are not actually hashed.
/// @param _node Node to pull an ID for.
/// @return id_ ID for the node, depending on the size of its contents.
function _getNodeID(RLPReader.RLPItem memory _node) private pure returns (bytes memory id_) {
id_ = _node.length < 32 ? RLPReader.readRawBytes(_node) : RLPReader.readBytes(_node);
}
/// @notice Gets the path for a leaf or extension node.
/// @param _node Node to get a path for.
/// @return nibbles_ Node path, converted to an array of nibbles.
function _getNodePath(TrieNode memory _node) private pure returns (bytes memory nibbles_) {
nibbles_ = Bytes.toNibbles(RLPReader.readBytes(_node.decoded[0]));
}
/// @notice Utility; determines the number of nibbles shared between two nibble arrays.
/// @param _a First nibble array.
/// @param _b Second nibble array.
/// @return shared_ Number of shared nibbles.
function _getSharedNibbleLength(
bytes memory _a,
bytes memory _b
)
private
pure
returns (uint256 shared_)
{
uint256 max = (_a.length < _b.length) ? _a.length : _b.length;
for (; shared_ < max && _a[shared_] == _b[shared_];) {
unchecked {
++shared_;
}
}
}
}
contracts/thirdparty/optimism/trie/SecureMerkleTrie.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.24;
import { MerkleTrie } from "./MerkleTrie.sol";
/// @title SecureMerkleTrie
/// @notice SecureMerkleTrie is a thin wrapper around the MerkleTrie library that hashes the input
/// keys. Ethereum's state trie hashes input keys before storing them.
library SecureMerkleTrie {
/// @notice Verifies a proof that a given key/value pair is present in the Merkle trie.
/// @param _key Key of the node to search for, as a hex string.
/// @param _value Value of the node to search for, as a hex string.
/// @param _proof Merkle trie inclusion proof for the desired node. Unlike traditional Merkle
/// trees, this proof is executed top-down and consists of a list of RLP-encoded
/// nodes that make a path down to the target node.
/// @param _root Known root of the Merkle trie. Used to verify that the included proof is
/// correctly constructed.
/// @return valid_ Whether or not the proof is valid.
function verifyInclusionProof(
bytes memory _key,
bytes memory _value,
bytes[] memory _proof,
bytes32 _root
)
internal
pure
returns (bool valid_)
{
bytes memory key = _getSecureKey(_key);
valid_ = MerkleTrie.verifyInclusionProof(key, _value, _proof, _root);
}
/// @notice Retrieves the value associated with a given key.
/// @param _key Key to search for, as hex bytes.
/// @param _proof Merkle trie inclusion proof for the key.
/// @param _root Known root of the Merkle trie.
/// @return value_ Value of the key if it exists.
function get(
bytes memory _key,
bytes[] memory _proof,
bytes32 _root
)
internal
pure
returns (bytes memory value_)
{
bytes memory key = _getSecureKey(_key);
value_ = MerkleTrie.get(key, _proof, _root);
}
/// @notice Computes the hashed version of the input key.
/// @param _key Key to hash.
/// @return hash_ Hashed version of the key.
function _getSecureKey(bytes memory _key) private pure returns (bytes memory hash_) {
hash_ = abi.encodePacked(keccak256(_key));
}
}
node_modules/@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable2Step.sol)
pragma solidity ^0.8.0;
import "./OwnableUpgradeable.sol";
import {Initializable} from "../proxy/utils/Initializable.sol";
/**
* @dev Contract module which provides access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* By default, the owner account will be the one that deploys the contract. This
* can later be changed with {transferOwnership} and {acceptOwnership}.
*
* This module is used through inheritance. It will make available all functions
* from parent (Ownable).
*/
abstract contract Ownable2StepUpgradeable is Initializable, OwnableUpgradeable {
address private _pendingOwner;
event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);
function __Ownable2Step_init() internal onlyInitializing {
__Ownable_init_unchained();
}
function __Ownable2Step_init_unchained() internal onlyInitializing {
}
/**
* @dev Returns the address of the pending owner.
*/
function pendingOwner() public view virtual returns (address) {
return _pendingOwner;
}
/**
* @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual override onlyOwner {
_pendingOwner = newOwner;
emit OwnershipTransferStarted(owner(), newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual override {
delete _pendingOwner;
super._transferOwnership(newOwner);
}
/**
* @dev The new owner accepts the ownership transfer.
*/
function acceptOwnership() public virtual {
address sender = _msgSender();
require(pendingOwner() == sender, "Ownable2Step: caller is not the new owner");
_transferOwnership(sender);
}
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[49] private __gap;
}
node_modules/@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)
pragma solidity ^0.8.0;
import "../utils/ContextUpgradeable.sol";
import {Initializable} from "../proxy/utils/Initializable.sol";
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* By default, the owner account will be the one that deploys the contract. This
* can later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
function __Ownable_init() internal onlyInitializing {
__Ownable_init_unchained();
}
function __Ownable_init_unchained() internal onlyInitializing {
_transferOwnership(_msgSender());
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
_checkOwner();
_;
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if the sender is not the owner.
*/
function _checkOwner() internal view virtual {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby disabling any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[49] private __gap;
}
node_modules/@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)
pragma solidity ^0.8.2;
import "../../utils/AddressUpgradeable.sol";
/**
* @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 Indicates that the contract has been initialized.
* @custom:oz-retyped-from bool
*/
uint8 private _initialized;
/**
* @dev Indicates that the contract is in the process of being initialized.
*/
bool private _initializing;
/**
* @dev Triggered when the contract has been initialized or reinitialized.
*/
event Initialized(uint8 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 functions marked with `initializer` can be nested in the context of a
* constructor.
*
* Emits an {Initialized} event.
*/
modifier initializer() {
bool isTopLevelCall = !_initializing;
require(
(isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),
"Initializable: contract is already initialized"
);
_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 255 will prevent any future reinitialization.
*
* Emits an {Initialized} event.
*/
modifier reinitializer(uint8 version) {
require(!_initializing && _initialized < version, "Initializable: contract is already initialized");
_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() {
require(_initializing, "Initializable: contract is not initializing");
_;
}
/**
* @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 {
require(!_initializing, "Initializable: contract is initializing");
if (_initialized != type(uint8).max) {
_initialized = type(uint8).max;
emit Initialized(type(uint8).max);
}
}
/**
* @dev Returns the highest version that has been initialized. See {reinitializer}.
*/
function _getInitializedVersion() internal view returns (uint8) {
return _initialized;
}
/**
* @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.
*/
function _isInitializing() internal view returns (bool) {
return _initializing;
}
}
node_modules/@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)
pragma solidity ^0.8.1;
/**
* @dev Collection of functions related to the address type
*/
library AddressUpgradeable {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
*
* Furthermore, `isContract` will also return true if the target contract within
* the same transaction is already scheduled for destruction by `SELFDESTRUCT`,
* which only has an effect at the end of a transaction.
* ====
*
* [IMPORTANT]
* ====
* You shouldn't rely on `isContract` to protect against flash loan attacks!
*
* Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
* like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
* constructor.
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize/address.code.length, which returns 0
// for contracts in construction, since the code is only stored at the end
// of the constructor execution.
return account.code.length > 0;
}
/**
* @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.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @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, it is bubbled up by this
* function (like regular Solidity function calls).
*
* 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.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @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`.
*
* _Available since v3.1._
*/
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
* the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
*
* _Available since v4.8._
*/
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata,
string memory errorMessage
) internal view returns (bytes memory) {
if (success) {
if (returndata.length == 0) {
// only check isContract if the call was successful and the return data is empty
// otherwise we already know that it was a contract
require(isContract(target), "Address: call to non-contract");
}
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
/**
* @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason or using the provided one.
*
* _Available since v4.3._
*/
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
function _revert(bytes memory returndata, string memory errorMessage) 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
/// @solidity memory-safe-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
node_modules/@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.4) (utils/Context.sol)
pragma solidity ^0.8.0;
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;
}
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[50] private __gap;
}
node_modules/@openzeppelin/contracts/interfaces/IERC1967.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (interfaces/IERC1967.sol)
pragma solidity ^0.8.0;
/**
* @dev ERC-1967: Proxy Storage Slots. This interface contains the events defined in the ERC.
*
* _Available since v4.8.3._
*/
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);
}
node_modules/@openzeppelin/contracts/interfaces/draft-IERC1822.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (interfaces/draft-IERC1822.sol)
pragma solidity ^0.8.0;
/**
* @dev ERC1822: 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);
}
node_modules/@openzeppelin/contracts/proxy/ERC1967/ERC1967Upgrade.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (proxy/ERC1967/ERC1967Upgrade.sol)
pragma solidity ^0.8.2;
import "../beacon/IBeacon.sol";
import "../../interfaces/IERC1967.sol";
import "../../interfaces/draft-IERC1822.sol";
import "../../utils/Address.sol";
import "../../utils/StorageSlot.sol";
/**
* @dev This abstract contract provides getters and event emitting update functions for
* https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots.
*
* _Available since v4.1._
*/
abstract contract ERC1967Upgrade is IERC1967 {
// This is the keccak-256 hash of "eip1967.proxy.rollback" subtracted by 1
bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143;
/**
* @dev Storage slot with the address of the current implementation.
* This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1, and is
* validated in the constructor.
*/
bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
/**
* @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 EIP1967 implementation slot.
*/
function _setImplementation(address newImplementation) private {
require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract");
StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
}
/**
* @dev Perform implementation upgrade
*
* Emits an {Upgraded} event.
*/
function _upgradeTo(address newImplementation) internal {
_setImplementation(newImplementation);
emit Upgraded(newImplementation);
}
/**
* @dev Perform implementation upgrade with additional setup call.
*
* Emits an {Upgraded} event.
*/
function _upgradeToAndCall(address newImplementation, bytes memory data, bool forceCall) internal {
_upgradeTo(newImplementation);
if (data.length > 0 || forceCall) {
Address.functionDelegateCall(newImplementation, data);
}
}
/**
* @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call.
*
* Emits an {Upgraded} event.
*/
function _upgradeToAndCallUUPS(address newImplementation, bytes memory data, bool forceCall) internal {
// Upgrades from old implementations will perform a rollback test. This test requires the new
// implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing
// this special case will break upgrade paths from old UUPS implementation to new ones.
if (StorageSlot.getBooleanSlot(_ROLLBACK_SLOT).value) {
_setImplementation(newImplementation);
} else {
try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) {
require(slot == _IMPLEMENTATION_SLOT, "ERC1967Upgrade: unsupported proxiableUUID");
} catch {
revert("ERC1967Upgrade: new implementation is not UUPS");
}
_upgradeToAndCall(newImplementation, data, forceCall);
}
}
/**
* @dev Storage slot with the admin of the contract.
* This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1, and is
* validated in the constructor.
*/
bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;
/**
* @dev Returns the current admin.
*/
function _getAdmin() internal view returns (address) {
return StorageSlot.getAddressSlot(_ADMIN_SLOT).value;
}
/**
* @dev Stores a new address in the EIP1967 admin slot.
*/
function _setAdmin(address newAdmin) private {
require(newAdmin != address(0), "ERC1967: new admin is the zero address");
StorageSlot.getAddressSlot(_ADMIN_SLOT).value = newAdmin;
}
/**
* @dev Changes the admin of the proxy.
*
* Emits an {AdminChanged} event.
*/
function _changeAdmin(address newAdmin) internal {
emit AdminChanged(_getAdmin(), newAdmin);
_setAdmin(newAdmin);
}
/**
* @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.
* This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor.
*/
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 EIP1967 beacon slot.
*/
function _setBeacon(address newBeacon) private {
require(Address.isContract(newBeacon), "ERC1967: new beacon is not a contract");
require(
Address.isContract(IBeacon(newBeacon).implementation()),
"ERC1967: beacon implementation is not a contract"
);
StorageSlot.getAddressSlot(_BEACON_SLOT).value = newBeacon;
}
/**
* @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does
* not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that).
*
* Emits a {BeaconUpgraded} event.
*/
function _upgradeBeaconToAndCall(address newBeacon, bytes memory data, bool forceCall) internal {
_setBeacon(newBeacon);
emit BeaconUpgraded(newBeacon);
if (data.length > 0 || forceCall) {
Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data);
}
}
}
node_modules/@openzeppelin/contracts/proxy/beacon/IBeacon.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol)
pragma solidity ^0.8.0;
/**
* @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.
*
* {BeaconProxy} will check that this address is a contract.
*/
function implementation() external view returns (address);
}
node_modules/@openzeppelin/contracts/proxy/utils/UUPSUpgradeable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/UUPSUpgradeable.sol)
pragma solidity ^0.8.0;
import "../../interfaces/draft-IERC1822.sol";
import "../ERC1967/ERC1967Upgrade.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.
*
* _Available since v4.1._
*/
abstract contract UUPSUpgradeable is IERC1822Proxiable, ERC1967Upgrade {
/// @custom:oz-upgrades-unsafe-allow state-variable-immutable state-variable-assignment
address private immutable __self = address(this);
/**
* @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 ERC1967) 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 ERC1167 minimal proxies (clones) would not normally pass this test, but is not guaranteed to
* fail.
*/
modifier onlyProxy() {
require(address(this) != __self, "Function must be called through delegatecall");
require(_getImplementation() == __self, "Function must be called through active proxy");
_;
}
/**
* @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() {
require(address(this) == __self, "UUPSUpgradeable: must not be called through delegatecall");
_;
}
/**
* @dev Implementation of the ERC1822 {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 override notDelegated returns (bytes32) {
return _IMPLEMENTATION_SLOT;
}
/**
* @dev Upgrade the implementation of the proxy to `newImplementation`.
*
* Calls {_authorizeUpgrade}.
*
* Emits an {Upgraded} event.
*
* @custom:oz-upgrades-unsafe-allow-reachable delegatecall
*/
function upgradeTo(address newImplementation) public virtual onlyProxy {
_authorizeUpgrade(newImplementation);
_upgradeToAndCallUUPS(newImplementation, new bytes(0), false);
}
/**
* @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, true);
}
/**
* @dev Function that should revert when `msg.sender` is not authorized to upgrade the contract. Called by
* {upgradeTo} and {upgradeToAndCall}.
*
* Normally, this function will use an xref:access.adoc[access control] modifier such as {Ownable-onlyOwner}.
*
* ```solidity
* function _authorizeUpgrade(address) internal override onlyOwner {}
* ```
*/
function _authorizeUpgrade(address newImplementation) internal virtual;
}
node_modules/@openzeppelin/contracts/utils/Address.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)
pragma solidity ^0.8.1;
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
*
* Furthermore, `isContract` will also return true if the target contract within
* the same transaction is already scheduled for destruction by `SELFDESTRUCT`,
* which only has an effect at the end of a transaction.
* ====
*
* [IMPORTANT]
* ====
* You shouldn't rely on `isContract` to protect against flash loan attacks!
*
* Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
* like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
* constructor.
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize/address.code.length, which returns 0
// for contracts in construction, since the code is only stored at the end
// of the constructor execution.
return account.code.length > 0;
}
/**
* @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.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @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, it is bubbled up by this
* function (like regular Solidity function calls).
*
* 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.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @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`.
*
* _Available since v3.1._
*/
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
* the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
*
* _Available since v4.8._
*/
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata,
string memory errorMessage
) internal view returns (bytes memory) {
if (success) {
if (returndata.length == 0) {
// only check isContract if the call was successful and the return data is empty
// otherwise we already know that it was a contract
require(isContract(target), "Address: call to non-contract");
}
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
/**
* @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason or using the provided one.
*
* _Available since v4.3._
*/
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
function _revert(bytes memory returndata, string memory errorMessage) 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
/// @solidity memory-safe-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
node_modules/@openzeppelin/contracts/utils/StorageSlot.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/StorageSlot.sol)
// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.
pragma solidity ^0.8.0;
/**
* @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 ERC1967 implementation slot:
* ```solidity
* contract ERC1967 {
* bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
*
* function _getImplementation() internal view returns (address) {
* return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;
* }
*
* function _setImplementation(address newImplementation) internal {
* require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract");
* StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
* }
* }
* ```
*
* _Available since v4.1 for `address`, `bool`, `bytes32`, `uint256`._
* _Available since v4.9 for `string`, `bytes`._
*/
library StorageSlot {
struct AddressSlot {
address value;
}
struct BooleanSlot {
bool value;
}
struct Bytes32Slot {
bytes32 value;
}
struct Uint256Slot {
uint256 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) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `BooleanSlot` with member `value` located at `slot`.
*/
function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `Bytes32Slot` with member `value` located at `slot`.
*/
function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `Uint256Slot` with member `value` located at `slot`.
*/
function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `StringSlot` with member `value` located at `slot`.
*/
function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
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) {
/// @solidity memory-safe-assembly
assembly {
r.slot := store.slot
}
}
/**
* @dev Returns an `BytesSlot` with member `value` located at `slot`.
*/
function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
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) {
/// @solidity memory-safe-assembly
assembly {
r.slot := store.slot
}
}
}
Compiler Settings
{"viaIR":false,"remappings":["@openzeppelin/contracts-upgradeable/=node_modules/@openzeppelin/contracts-upgradeable/","@openzeppelin/contracts/=node_modules/@openzeppelin/contracts/","solady/=node_modules/solady/","forge-std/=node_modules/forge-std/","ds-test/=node_modules/ds-test/src/","p256-verifier/=node_modules/p256-verifier/","forge-safe/=node_modules/forge-safe/"],"outputSelection":{"*":{"*":["*"],"":["*"]}},"optimizer":{"runs":200,"enabled":true},"metadata":{"useLiteralContent":false,"bytecodeHash":"ipfs","appendCBOR":true},"libraries":{},"evmVersion":"cancun"}
Contract ABI
[{"type":"error","name":"FUNC_NOT_IMPLEMENTED","inputs":[]},{"type":"error","name":"INVALID_PAUSE_STATUS","inputs":[]},{"type":"error","name":"LTP_INVALID_ACCOUNT_PROOF","inputs":[]},{"type":"error","name":"LTP_INVALID_INCLUSION_PROOF","inputs":[]},{"type":"error","name":"REENTRANT_CALL","inputs":[]},{"type":"error","name":"RESOLVER_DENIED","inputs":[]},{"type":"error","name":"RESOLVER_INVALID_MANAGER","inputs":[]},{"type":"error","name":"RESOLVER_UNEXPECTED_CHAINID","inputs":[]},{"type":"error","name":"RESOLVER_ZERO_ADDR","inputs":[{"type":"uint64","name":"chainId","internalType":"uint64"},{"type":"bytes32","name":"name","internalType":"bytes32"}]},{"type":"error","name":"SS_EMPTY_PROOF","inputs":[]},{"type":"error","name":"SS_INVALID_HOPS_WITH_LOOP","inputs":[]},{"type":"error","name":"SS_INVALID_LAST_HOP_CHAINID","inputs":[]},{"type":"error","name":"SS_INVALID_MID_HOP_CHAINID","inputs":[]},{"type":"error","name":"SS_INVALID_STATE","inputs":[]},{"type":"error","name":"SS_SIGNAL_NOT_FOUND","inputs":[]},{"type":"error","name":"SS_UNAUTHORIZED","inputs":[]},{"type":"error","name":"ZERO_ADDRESS","inputs":[]},{"type":"error","name":"ZERO_VALUE","inputs":[]},{"type":"event","name":"AdminChanged","inputs":[{"type":"address","name":"previousAdmin","internalType":"address","indexed":false},{"type":"address","name":"newAdmin","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"Authorized","inputs":[{"type":"address","name":"addr","internalType":"address","indexed":true},{"type":"bool","name":"authorized","internalType":"bool","indexed":false}],"anonymous":false},{"type":"event","name":"BeaconUpgraded","inputs":[{"type":"address","name":"beacon","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"ChainDataSynced","inputs":[{"type":"uint64","name":"chainId","internalType":"uint64","indexed":true},{"type":"uint64","name":"blockId","internalType":"uint64","indexed":true},{"type":"bytes32","name":"kind","internalType":"bytes32","indexed":true},{"type":"bytes32","name":"data","internalType":"bytes32","indexed":false},{"type":"bytes32","name":"signal","internalType":"bytes32","indexed":false}],"anonymous":false},{"type":"event","name":"Initialized","inputs":[{"type":"uint8","name":"version","internalType":"uint8","indexed":false}],"anonymous":false},{"type":"event","name":"OwnershipTransferStarted","inputs":[{"type":"address","name":"previousOwner","internalType":"address","indexed":true},{"type":"address","name":"newOwner","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"OwnershipTransferred","inputs":[{"type":"address","name":"previousOwner","internalType":"address","indexed":true},{"type":"address","name":"newOwner","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"Paused","inputs":[{"type":"address","name":"account","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"SignalSent","inputs":[{"type":"address","name":"app","internalType":"address","indexed":false},{"type":"bytes32","name":"signal","internalType":"bytes32","indexed":false},{"type":"bytes32","name":"slot","internalType":"bytes32","indexed":false},{"type":"bytes32","name":"value","internalType":"bytes32","indexed":false}],"anonymous":false},{"type":"event","name":"Unpaused","inputs":[{"type":"address","name":"account","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"Upgraded","inputs":[{"type":"address","name":"implementation","internalType":"address","indexed":true}],"anonymous":false},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"acceptOwnership","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"addressManager","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"authorize","inputs":[{"type":"address","name":"_addr","internalType":"address"},{"type":"bool","name":"_authorize","internalType":"bool"}]},{"type":"function","stateMutability":"pure","outputs":[{"type":"bytes32","name":"","internalType":"bytes32"}],"name":"getSignalSlot","inputs":[{"type":"uint64","name":"_chainId","internalType":"uint64"},{"type":"address","name":"_app","internalType":"address"},{"type":"bytes32","name":"_signal","internalType":"bytes32"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint64","name":"blockId_","internalType":"uint64"},{"type":"bytes32","name":"chainData_","internalType":"bytes32"}],"name":"getSyncedChainData","inputs":[{"type":"uint64","name":"_chainId","internalType":"uint64"},{"type":"bytes32","name":"_kind","internalType":"bytes32"},{"type":"uint64","name":"_blockId","internalType":"uint64"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"impl","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"inNonReentrant","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"init","inputs":[{"type":"address","name":"_owner","internalType":"address"},{"type":"address","name":"_addressManager","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"authorized","internalType":"bool"}],"name":"isAuthorized","inputs":[{"type":"address","name":"addr","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"isChainDataSynced","inputs":[{"type":"uint64","name":"_chainId","internalType":"uint64"},{"type":"bytes32","name":"_kind","internalType":"bytes32"},{"type":"uint64","name":"_blockId","internalType":"uint64"},{"type":"bytes32","name":"_chainData","internalType":"bytes32"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"isSignalSent","inputs":[{"type":"address","name":"_app","internalType":"address"},{"type":"bytes32","name":"_signal","internalType":"bytes32"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint64","name":"","internalType":"uint64"}],"name":"lastUnpausedAt","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"owner","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"pause","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"paused","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"pendingOwner","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"uint256","name":"numCacheOps_","internalType":"uint256"}],"name":"proveSignalReceived","inputs":[{"type":"uint64","name":"_chainId","internalType":"uint64"},{"type":"address","name":"_app","internalType":"address"},{"type":"bytes32","name":"_signal","internalType":"bytes32"},{"type":"bytes","name":"_proof","internalType":"bytes"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes32","name":"","internalType":"bytes32"}],"name":"proxiableUUID","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"renounceOwnership","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address payable"}],"name":"resolve","inputs":[{"type":"uint64","name":"_chainId","internalType":"uint64"},{"type":"bytes32","name":"_name","internalType":"bytes32"},{"type":"bool","name":"_allowZeroAddress","internalType":"bool"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address payable"}],"name":"resolve","inputs":[{"type":"bytes32","name":"_name","internalType":"bytes32"},{"type":"bool","name":"_allowZeroAddress","internalType":"bool"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bytes32","name":"","internalType":"bytes32"}],"name":"sendSignal","inputs":[{"type":"bytes32","name":"_signal","internalType":"bytes32"}]},{"type":"function","stateMutability":"pure","outputs":[{"type":"bytes32","name":"","internalType":"bytes32"}],"name":"signalForChainData","inputs":[{"type":"uint64","name":"_chainId","internalType":"uint64"},{"type":"bytes32","name":"_kind","internalType":"bytes32"},{"type":"uint64","name":"_blockId","internalType":"uint64"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bytes32","name":"","internalType":"bytes32"}],"name":"syncChainData","inputs":[{"type":"uint64","name":"_chainId","internalType":"uint64"},{"type":"bytes32","name":"_kind","internalType":"bytes32"},{"type":"uint64","name":"_blockId","internalType":"uint64"},{"type":"bytes32","name":"_chainData","internalType":"bytes32"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint64","name":"blockId","internalType":"uint64"}],"name":"topBlockId","inputs":[{"type":"uint64","name":"chainId","internalType":"uint64"},{"type":"bytes32","name":"kind","internalType":"bytes32"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"transferOwnership","inputs":[{"type":"address","name":"newOwner","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"unpause","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"upgradeTo","inputs":[{"type":"address","name":"newImplementation","internalType":"address"}]},{"type":"function","stateMutability":"payable","outputs":[],"name":"upgradeToAndCall","inputs":[{"type":"address","name":"newImplementation","internalType":"address"},{"type":"bytes","name":"data","internalType":"bytes"}]},{"type":"function","stateMutability":"view","outputs":[],"name":"verifySignalReceived","inputs":[{"type":"uint64","name":"_chainId","internalType":"uint64"},{"type":"address","name":"_app","internalType":"address"},{"type":"bytes32","name":"_signal","internalType":"bytes32"},{"type":"bytes","name":"_proof","internalType":"bytes"}]}]
Deployed ByteCode
0x6080604052600436106101c5575f3560e01c806379ba5097116100f2578063a86f9d9e11610092578063e30c397811610062578063e30c39781461052f578063f09a40161461054c578063f2fde38b1461056b578063fe9fbb801461058a575f80fd5b8063a86f9d9e1461048e578063ce9d0820146104ad578063dfc8ff1d146104cc578063e07baba61461050a575f80fd5b80638da5cb5b116100cd5780638da5cb5b14610414578063910af6ed1461043157806391f3f74b146104505780639b527cfa1461046f575f80fd5b806379ba5097146103d85780638456cb59146103ec5780638abf607714610400575f80fd5b80633eb6b8cf1161016857806352d1902d1161013857806352d1902d146103715780635c975abb1461038557806366ca2bc0146103a5578063715018a6146103c4575f80fd5b80633eb6b8cf146102fe5780633f4ba83a1461031d5780634f1ef286146103315780634f90a67414610344575f80fd5b8063355bcc3d116101a3578063355bcc3d146102325780633659cfe6146102895780633ab76e9f146102a85780633ced0e08146102df575f80fd5b80632d1fb389146101c95780633075db56146101ea57806332676bc614610213575b5f80fd5b3480156101d4575f80fd5b506101e86101e3366004613ad5565b6105b8565b005b3480156101f5575f80fd5b506101fe61065e565b60405190151581526020015b60405180910390f35b34801561021e575f80fd5b506101fe61022d366004613b08565b610672565b34801561023d575f80fd5b5061027161024c366004613b48565b60fb60209081525f92835260408084209091529082529020546001600160401b031681565b6040516001600160401b03909116815260200161020a565b348015610294575f80fd5b506101e86102a3366004613b62565b610688565b3480156102b3575f80fd5b506097546102c7906001600160a01b031681565b6040516001600160a01b03909116815260200161020a565b3480156102ea575f80fd5b506101fe6102f9366004613b7d565b610758565b348015610309575f80fd5b506102c7610318366004613bbe565b61079f565b348015610328575f80fd5b506101e86107b5565b6101e861033f366004613cce565b6107c9565b34801561034f575f80fd5b5061036361035e366004613b7d565b610882565b60405190815260200161020a565b34801561037c575f80fd5b506103636108c8565b348015610390575f80fd5b506101fe60c954610100900460ff1660021490565b3480156103b0575f80fd5b506103636103bf366004613d1a565b610979565b3480156103cf575f80fd5b506101e8610985565b3480156103e3575f80fd5b506101e8610996565b3480156103f7575f80fd5b506101e8610a0d565b34801561040b575f80fd5b506102c7610a20565b34801561041f575f80fd5b506033546001600160a01b03166102c7565b34801561043c575f80fd5b5061036361044b366004613d31565b610a2e565b34801561045b575f80fd5b5061036361046a366004613dc5565b610afe565b34801561047a575f80fd5b50610363610489366004613e01565b610b69565b348015610499575f80fd5b506102c76104a8366004613e31565b610b95565b3480156104b8575f80fd5b506101e86104c7366004613d31565b610ba1565b3480156104d7575f80fd5b506104eb6104e6366004613e01565b610bb7565b604080516001600160401b03909316835260208301919091520161020a565b348015610515575f80fd5b5060c954610271906201000090046001600160401b031681565b34801561053a575f80fd5b506065546001600160a01b03166102c7565b348015610557575f80fd5b506101e8610566366004613e52565b610c4b565b348015610576575f80fd5b506101e8610585366004613b62565b610d5a565b348015610595575f80fd5b506101fe6105a4366004613b62565b60fc6020525f908152604090205460ff1681565b6105c0610dcb565b6001600160a01b0382165f90815260fc602052604090205481151560ff909116151503610600576040516398f26f4560e01b815260040160405180910390fd5b6001600160a01b0382165f81815260fc6020908152604091829020805460ff191685151590811790915591519182527f4c0079b9bcd37cd5d29a13938effd97c881798cbc6bd52a3026a29d94b27d1bf910160405180910390a25050565b5f6002610669610e25565b60ff1614905090565b5f61067d8383610e64565b151590505b92915050565b6001600160a01b037f00000000000000000000000001670000000000000000000000000000000000051630036106d95760405162461bcd60e51b81526004016106d090613e89565b60405180910390fd5b7f00000000000000000000000001670000000000000000000000000000000000056001600160a01b031661070b610ec6565b6001600160a01b0316146107315760405162461bcd60e51b81526004016106d090613ed5565b61073a81610ee1565b604080515f8082526020820190925261075591839190610ee9565b50565b5f8180820361077a5760405163ec73295960e01b815260040160405180910390fd5b5f610786878787610b69565b9050836107933083610e64565b14979650505050505050565b5f6107ab848484611053565b90505b9392505050565b6107bd611144565b6107c7335f6111d4565b565b6001600160a01b037f00000000000000000000000001670000000000000000000000000000000000051630036108115760405162461bcd60e51b81526004016106d090613e89565b7f00000000000000000000000001670000000000000000000000000000000000056001600160a01b0316610843610ec6565b6001600160a01b0316146108695760405162461bcd60e51b81526004016106d090613ed5565b61087282610ee1565b61087e82826001610ee9565b5050565b335f90815260fc602052604081205460ff166108b157604051631f67751f60e01b815260040160405180910390fd5b6108bd858585856111ed565b90505b949350505050565b5f306001600160a01b037f000000000000000000000000016700000000000000000000000000000000000516146109675760405162461bcd60e51b815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c60448201527f6c6564207468726f7567682064656c656761746563616c6c000000000000000060648201526084016106d0565b505f805160206144e883398151915290565b5f6106823383846112cf565b61098d610dcb565b6107c75f6113a8565b60655433906001600160a01b03168114610a045760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b60648201526084016106d0565b610755816113a8565b610a156113c1565b6107c73360016111d4565b5f610a29610ec6565b905090565b5f610a4360c954610100900460ff1660021490565b15610a615760405163bae6e2a960e01b815260040160405180910390fd5b6002610a6b610e25565b60ff1603610a8c5760405163dfc60d8560e01b815260040160405180910390fd5b610a966002611432565b5f610aa68787878787600161147a565b90505f5b8151811015610ae957610ad5828281518110610ac857610ac8613f21565b6020026020010151611936565b610adf9084613f49565b9250600101610aaa565b5050610af56001611432565b95945050505050565b6040516514d251d3905360d21b60208201526001600160c01b031960c085901b1660268201526bffffffffffffffffffffffff19606084901b16602e820152604281018290525f906062015b6040516020818303038152906040528051906020012090509392505050565b604080516001600160401b03808616602083015291810184905290821660608201525f90608001610b4a565b5f6107ae468484611053565b610baf85858585855f61147a565b505050505050565b5f80826001600160401b03165f03610bf3576001600160401b038086165f90815260fb6020908152604080832088845290915290205416610bf5565b825b91506001600160401b03821615610c43575f610c12868685610b69565b9050610c1e3082610e64565b91505f829003610c415760405163738afa0560e01b815260040160405180910390fd5b505b935093915050565b5f54610100900460ff1615808015610c6957505f54600160ff909116105b80610c825750303b158015610c8257505f5460ff166001145b610ce55760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084016106d0565b5f805460ff191660011790558015610d06575f805461ff0019166101001790555b610d108383611a7a565b8015610d55575f805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b610d62610dcb565b606580546001600160a01b0383166001600160a01b03199091168117909155610d936033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b6033546001600160a01b031633146107c75760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016106d0565b5f610e2f46611ab4565b15610e5a57507fa5054f728453d3dbe953bdc43e4d0cb97e662ea32d7958190f3dc2da31d9721b5c90565b5060c95460ff1690565b5f826001600160a01b038116610e8d5760405163538ba4f960e01b815260040160405180910390fd5b825f819003610eaf5760405163ec73295960e01b815260040160405180910390fd5b5f610ebb468787610afe565b549695505050505050565b5f805160206144e8833981519152546001600160a01b031690565b610755610dcb565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff1615610f1c57610d5583611ae1565b826001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015610f76575060408051601f3d908101601f19168201909252610f7391810190613f5c565b60015b610fd95760405162461bcd60e51b815260206004820152602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201526d6f6e206973206e6f74205555505360901b60648201526084016106d0565b5f805160206144e883398151915281146110475760405162461bcd60e51b815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f786044820152681a58589b195555525160ba1b60648201526084016106d0565b50610d55838383611b7c565b6097545f906001600160a01b03168061107f57604051638ed88b2560e01b815260040160405180910390fd5b604051630a3dc4f360e21b81526001600160401b0386166004820152602481018590526001600160a01b038216906328f713cc90604401602060405180830381865afa1580156110d1573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906110f59190613f73565b91508215801561110c57506001600160a01b038216155b1561113c57604051632b0d65db60e01b81526001600160401b0386166004820152602481018590526044016106d0565b509392505050565b61115860c954610100900460ff1660021490565b6111755760405163bae6e2a960e01b815260040160405180910390fd5b60c9805461010069ffffffffffffffffff001990911662010000426001600160401b031602171790556040513381527f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa906020015b60405180910390a1565b604051630c2b8f8f60e11b815260040160405180910390fd5b5f6111f9858585610b69565b90506112063082846112cf565b506001600160401b038581165f90815260fb6020908152604080832088845290915290205481851691161015611270576001600160401b038581165f90815260fb602090815260408083208884529091529020805467ffffffffffffffff19169185169190911790555b83836001600160401b0316866001600160401b03167fde247c825b1fb2d7ff9e0e771cba6f9e757ad04479fcdc135d88ae91fd50b37d85856040516112bf929190918252602082015260400190565b60405180910390a4949350505050565b5f836001600160a01b0381166112f85760405163538ba4f960e01b815260040160405180910390fd5b835f81900361131a5760405163ec73295960e01b815260040160405180910390fd5b835f81900361133c5760405163ec73295960e01b815260040160405180910390fd5b611347468888610afe565b858155604080516001600160a01b038a16815260208101899052908101829052606081018790529094507f0ad2d108660a211f47bf7fb43a0443cae181624995d3d42b88ee6879d200e9739060800160405180910390a15050509392505050565b606580546001600160a01b031916905561075581611ba6565b6113d560c954610100900460ff1660021490565b156113f35760405163bae6e2a960e01b815260040160405180910390fd5b60c9805461ff0019166102001790556040513381527f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258906020016111ca565b61143b46611ab4565b1561146657807fa5054f728453d3dbe953bdc43e4d0cb97e662ea32d7958190f3dc2da31d9721b5d50565b60c9805460ff831660ff1990911617905550565b6060856001600160a01b0381166114a45760405163538ba4f960e01b815260040160405180910390fd5b855f8190036114c65760405163ec73295960e01b815260040160405180910390fd5b5f6114d38688018861403d565b905080515f036114f657604051630b92daef60e21b815260040160405180910390fd5b5f60018251611505919061417b565b6001600160401b0381111561151c5761151c613bf7565b604051908082528060200260200182016040528015611545578160200160208202803683370190505b50905085156115d85781516001600160401b0381111561156757611567613bf7565b6040519080825280602002602001820160405280156115d457816020015b6115c16040805160e0810182525f80825260208201819052918101829052606081018290526080810182905260a081018290529060c082015290565b8152602001906001900390816115855790505b5094505b8a8a8a805f6115f9856d7369676e616c5f7365727669636560901b8361079f565b9050306001600160a01b0382160361162457604051637556223560e11b815260040160405180910390fd5b61165c6040805160c0810182525f80825260208201819052918101829052906060820190815260200160608152602001606081525090565b5f805f805b8b518110156118ea578b818151811061167c5761167c613f21565b602002602001015194505f5b818110156116e657855f01516001600160401b03168c82815181106116af576116af613f21565b60200260200101516001600160401b0316036116de576040516348362c2760e11b815260040160405180910390fd5b600101611688565b506116f58a8a8a8a898b611bf7565b93508a518114915081156117355784516001600160401b0316461461172d576040516338bf822760e21b815260040160405180910390fd5b3095506117e0565b845f01518b828151811061174b5761174b613f21565b6001600160401b0392831660209182029290920101528551161580611779575084516001600160401b031646145b1561179757604051637556223560e11b815260040160405180910390fd5b84516117b5906d7369676e616c5f7365727669636560901b5f61079f565b9550306001600160a01b038716036117e057604051637556223560e11b815260040160405180910390fd5b608085015151151592508f15611874576040518060e00160405280866040015181526020018581526020018b6001600160401b0316815260200186602001516001600160401b0316815260200184151581526020018315158152602001866060015160038111156118535761185361418e565b8152508f828151811061186857611868613f21565b60200260200101819052505b6118cf8a846118a3577fc6cdc4f2acf13acb10f410085b821f7b7113b303e9a4799023f928317396aaf56118c5565b7f73e6d340850343cc6f001515dc593377337c95a6ffe034fe1e844d4dab5da1695b8760200151610b69565b604086015186519b5096995097509495508794600101611661565b5085158061190157506118fd3088610e64565b8614155b1561191f5760405163738afa0560e01b815260040160405180910390fd5b505050505050505050505050509695505050505050565b5f8060038360c0015160038111156119505761195061418e565b1480611971575060028360c00151600381111561196f5761196f61418e565b145b9050808015611981575082608001515b801561198f57508260a00151155b156119d157600191506119cf83604001517f73e6d340850343cc6f001515dc593377337c95a6ffe034fe1e844d4dab5da1698560600151865f01516111ed565b505b5f60038460c0015160038111156119ea576119ea61418e565b1480611a0b575060018460c001516003811115611a0957611a0961418e565b145b9050808015611a275750836080015180611a2757508360a00151155b15611a7357611a37600184613f49565b9250611a7184604001517fc6cdc4f2acf13acb10f410085b821f7b7113b303e9a4799023f928317396aaf5866060015187602001516111ed565b505b5050919050565b806001600160a01b038116611aa25760405163538ba4f960e01b815260040160405180910390fd5b611aab83611c96565b610d5582611cf4565b5f6001821480611ac5575061426882145b80611ad2575062aa36a782145b80610682575061068282611d64565b6001600160a01b0381163b611b4e5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b60648201526084016106d0565b5f805160206144e883398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b611b8583611d7b565b5f82511180611b915750805b15610d5557611ba08383611dba565b50505050565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b5f856001600160a01b038116611c205760405163538ba4f960e01b815260040160405180910390fd5b855f819003611c425760405163ec73295960e01b815260040160405180910390fd5b855f819003611c645760405163ec73295960e01b815260040160405180910390fd5b611c88866040015186611c788d8d8d610afe565b8a8a608001518b60a00151611ddf565b9a9950505050505050505050565b5f54610100900460ff16611cbc5760405162461bcd60e51b81526004016106d0906141a2565b611cc4611eec565b611ce26001600160a01b03821615611cdc57816113a8565b336113a8565b5060c9805461ff001916610100179055565b5f54610100900460ff16611d1a5760405162461bcd60e51b81526004016106d0906141a2565b6001600160401b03461115611d425760405163a12e8fa960e01b815260040160405180910390fd5b609780546001600160a01b0319166001600160a01b0392909216919091179055565b5f617e2c8210158015610682575050617e90101590565b611d8481611ae1565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a250565b60606107ae838360405180606001604052806027815260200161450860279139611f12565b5f82515f14611e87576040516bffffffffffffffffffffffff19606088901b1660208201525f90611e2390603401604051602081830303815290604052858a611f86565b905080515f03611e4657604051630414cd5b60e31b815260040160405180910390fd5b5f611e5082611f9f565b9050611e7581600281518110611e6857611e68613f21565b6020026020010151611fb2565b611e7e906141ed565b92505050611e8a565b50855b5f611ec186604051602001611ea191815260200190565b60408051601f19818403018152919052611eba876120d2565b85856120e5565b905080611ee157604051638d9a4db360e01b815260040160405180910390fd5b509695505050505050565b5f54610100900460ff166107c75760405162461bcd60e51b81526004016106d0906141a2565b60605f80856001600160a01b031685604051611f2e9190614235565b5f60405180830381855af49150503d805f8114611f66576040519150601f19603f3d011682016040523d82523d5f602084013e611f6b565b606091505b5091509150611f7c868383876120fe565b9695505050505050565b60605f611f9285612176565b9050610af58185856121a8565b6060610682611fad83612a15565b612a66565b60605f805f611fc085612c83565b919450925090505f816001811115611fda57611fda61418e565b1461204d5760405162461bcd60e51b815260206004820152603960248201527f524c505265616465723a206465636f646564206974656d207479706520666f7260448201527f206279746573206973206e6f7420612064617461206974656d0000000000000060648201526084016106d0565b6120578284613f49565b8551146120c35760405162461bcd60e51b815260206004820152603460248201527f524c505265616465723a2062797465732076616c756520636f6e7461696e732060448201527330b71034b73b30b634b2103932b6b0b4b73232b960611b60648201526084016106d0565b610af58560200151848461332a565b60606106826120e0836133ba565b6134cd565b5f806120f086612176565b9050611f7c81868686613525565b6060831561216c5782515f03612165576001600160a01b0385163b6121655760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016106d0565b50816108c0565b6108c0838361354b565b6060818051906020012060405160200161219291815260200190565b6040516020818303038152906040529050919050565b60605f8451116121f25760405162461bcd60e51b81526020600482015260156024820152744d65726b6c65547269653a20656d707479206b657960581b60448201526064016106d0565b5f6121fc84613575565b90505f61220886613658565b90505f8460405160200161221e91815260200190565b60405160208183030381529060405290505f805b84518110156129be575f85828151811061224e5761224e613f21565b6020026020010151905084518311156122c05760405162461bcd60e51b815260206004820152602e60248201527f4d65726b6c65547269653a206b657920696e646578206578636565647320746f60448201526d0e8c2d840d6caf240d8cadccee8d60931b60648201526084016106d0565b825f0361235e578051805160209182012060405161230d926122e792910190815260200190565b604051602081830303815290604052858051602091820120825192909101919091201490565b6123595760405162461bcd60e51b815260206004820152601d60248201527f4d65726b6c65547269653a20696e76616c696420726f6f74206861736800000060448201526064016106d0565b612454565b8051516020116123e45780518051602091820120604051612388926122e792910190815260200190565b6123595760405162461bcd60e51b815260206004820152602760248201527f4d65726b6c65547269653a20696e76616c6964206c6172676520696e7465726e6044820152660c2d840d0c2e6d60cb1b60648201526084016106d0565b8051845160208087019190912082519190920120146124545760405162461bcd60e51b815260206004820152602660248201527f4d65726b6c65547269653a20696e76616c696420696e7465726e616c206e6f646044820152650ca40d0c2e6d60d31b60648201526084016106d0565b61246060106001613f49565b816020015151036125f857845183036125925761248d8160200151601081518110611e6857611e68613f21565b96505f8751116125055760405162461bcd60e51b815260206004820152603b60248201527f4d65726b6c65547269653a2076616c7565206c656e677468206d75737420626560448201527f2067726561746572207468616e207a65726f20286272616e636829000000000060648201526084016106d0565b60018651612513919061417b565b82146125875760405162461bcd60e51b815260206004820152603a60248201527f4d65726b6c65547269653a2076616c7565206e6f6465206d757374206265206c60448201527f617374206e6f646520696e2070726f6f6620286272616e63682900000000000060648201526084016106d0565b5050505050506107ae565b5f8584815181106125a5576125a5613f21565b602001015160f81c60f81b60f81c90505f82602001518260ff16815181106125cf576125cf613f21565b602002602001015190506125e2816136b9565b95506125ef600186613f49565b945050506129b5565b60028160200151510361295c575f61260f826136dd565b90505f815f8151811061262457612624613f21565b016020015160f81c90505f61263a600283614264565b612645906002614285565b90505f612655848360ff16613700565b90505f6126628a89613700565b90505f61266f8383613735565b9050808351146126e75760405162461bcd60e51b815260206004820152603a60248201527f4d65726b6c65547269653a20706174682072656d61696e646572206d7573742060448201527f736861726520616c6c206e6962626c65732077697468206b657900000000000060648201526084016106d0565b60ff8516600214806126fc575060ff85166003145b1561289c57808251146127775760405162461bcd60e51b815260206004820152603d60248201527f4d65726b6c65547269653a206b65792072656d61696e646572206d757374206260448201527f65206964656e746963616c20746f20706174682072656d61696e64657200000060648201526084016106d0565b6127918760200151600181518110611e6857611e68613f21565b9c505f8d51116128095760405162461bcd60e51b815260206004820152603960248201527f4d65726b6c65547269653a2076616c7565206c656e677468206d75737420626560448201527f2067726561746572207468616e207a65726f20286c656166290000000000000060648201526084016106d0565b60018c51612817919061417b565b881461288b5760405162461bcd60e51b815260206004820152603860248201527f4d65726b6c65547269653a2076616c7565206e6f6465206d757374206265206c60448201527f617374206e6f646520696e2070726f6f6620286c65616629000000000000000060648201526084016106d0565b5050505050505050505050506107ae565b60ff851615806128af575060ff85166001145b156128ee576128db87602001516001815181106128ce576128ce613f21565b60200260200101516136b9565b99506128e7818a613f49565b9850612951565b60405162461bcd60e51b815260206004820152603260248201527f4d65726b6c65547269653a2072656365697665642061206e6f64652077697468604482015271040c2dc40eadcd6dcdeeedc40e0e4caccd2f60731b60648201526084016106d0565b5050505050506129b5565b60405162461bcd60e51b815260206004820152602860248201527f4d65726b6c65547269653a20726563656976656420616e20756e706172736561604482015267626c65206e6f646560c01b60648201526084016106d0565b50600101612232565b5060405162461bcd60e51b815260206004820152602560248201527f4d65726b6c65547269653a2072616e206f7574206f662070726f6f6620656c656044820152646d656e747360d81b60648201526084016106d0565b604080518082019091525f80825260208201525f825111612a485760405162461bcd60e51b81526004016106d09061429e565b50604080518082019091528151815260209182019181019190915290565b60605f805f612a7485612c83565b919450925090506001816001811115612a8f57612a8f61418e565b14612b025760405162461bcd60e51b815260206004820152603860248201527f524c505265616465723a206465636f646564206974656d207479706520666f7260448201527f206c697374206973206e6f742061206c697374206974656d000000000000000060648201526084016106d0565b8451612b0e8385613f49565b14612b765760405162461bcd60e51b815260206004820152603260248201527f524c505265616465723a206c697374206974656d2068617320616e20696e76616044820152713634b2103230ba30903932b6b0b4b73232b960711b60648201526084016106d0565b604080516020808252610420820190925290816020015b604080518082019091525f8082526020820152815260200190600190039081612b8d5790505093505f835b8651811015612c77575f80612bfc6040518060400160405280858c5f0151612be0919061417b565b8152602001858c60200151612bf59190613f49565b9052612c83565b509150915060405180604001604052808383612c189190613f49565b8152602001848b60200151612c2d9190613f49565b815250888581518110612c4257612c42613f21565b6020908102919091010152612c58600185613f49565b9350612c648183613f49565b612c6e9084613f49565b92505050612bb8565b50845250919392505050565b5f805f80845f015111612ca85760405162461bcd60e51b81526004016106d09061429e565b602084015180515f1a607f8111612cca575f60015f9450945094505050613323565b60b78111612e23575f612cde60808361417b565b905080875f015111612d5c5760405162461bcd60e51b815260206004820152604e60248201525f805160206144c883398151915260448201527f742062652067726561746572207468616e20737472696e67206c656e6774682060648201526d2873686f727420737472696e672960901b608482015260a4016106d0565b6001838101516001600160f81b0319169082141580612d895750600160ff1b6001600160f81b0319821610155b612e115760405162461bcd60e51b815260206004820152604d60248201527f524c505265616465723a20696e76616c6964207072656669782c2073696e676c60448201527f652062797465203c203078383020617265206e6f74207072656669786564202860648201526c73686f727420737472696e672960981b608482015260a4016106d0565b506001955093505f9250613323915050565b60bf811161305c575f612e3760b78361417b565b905080875f015111612eb85760405162461bcd60e51b815260206004820152605160248201525f805160206144c883398151915260448201527f74206265203e207468616e206c656e677468206f6620737472696e67206c656e60648201527067746820286c6f6e6720737472696e672960781b608482015260a4016106d0565b60018301516001600160f81b0319165f819003612f3d5760405162461bcd60e51b815260206004820152604a60248201525f805160206144c883398151915260448201527f74206e6f74206861766520616e79206c656164696e67207a65726f7320286c6f6064820152696e6720737472696e672960b01b608482015260a4016106d0565b600184015160088302610100031c60378111612fbf5760405162461bcd60e51b815260206004820152604860248201525f805160206144c883398151915260448201527f742062652067726561746572207468616e20353520627974657320286c6f6e6760648201526720737472696e672960c01b608482015260a4016106d0565b612fc98184613f49565b8951116130405760405162461bcd60e51b815260206004820152604c60248201525f805160206144c883398151915260448201527f742062652067726561746572207468616e20746f74616c206c656e677468202860648201526b6c6f6e6720737472696e672960a01b608482015260a4016106d0565b61304b836001613f49565b975095505f94506133239350505050565b60f781116130fb575f61307060c08361417b565b905080875f0151116130ea5760405162461bcd60e51b815260206004820152604a60248201525f805160206144c883398151915260448201527f742062652067726561746572207468616e206c697374206c656e677468202873606482015269686f7274206c6973742960b01b608482015260a4016106d0565b600195509350849250613323915050565b5f61310760f78361417b565b905080875f0151116131845760405162461bcd60e51b815260206004820152604d60248201525f805160206144c883398151915260448201527f74206265203e207468616e206c656e677468206f66206c697374206c656e677460648201526c6820286c6f6e67206c6973742960981b608482015260a4016106d0565b60018301516001600160f81b0319165f8190036132075760405162461bcd60e51b815260206004820152604860248201525f805160206144c883398151915260448201527f74206e6f74206861766520616e79206c656164696e67207a65726f7320286c6f6064820152676e67206c6973742960c01b608482015260a4016106d0565b600184015160088302610100031c603781116132875760405162461bcd60e51b815260206004820152604660248201525f805160206144c883398151915260448201527f742062652067726561746572207468616e20353520627974657320286c6f6e67606482015265206c6973742960d01b608482015260a4016106d0565b6132918184613f49565b8951116133065760405162461bcd60e51b815260206004820152604a60248201525f805160206144c883398151915260448201527f742062652067726561746572207468616e20746f74616c206c656e67746820286064820152696c6f6e67206c6973742960b01b608482015260a4016106d0565b613311836001613f49565b97509550600194506133239350505050565b9193909250565b6060816001600160401b0381111561334457613344613bf7565b6040519080825280601f01601f19166020018201604052801561336e576020820181803683370190505b50905081156107ae575f6133828486613f49565b9050602082015f5b848110156133a257828101518282015260200161338a565b848111156133b0575f858301525b5050509392505050565b60605f826040516020016133d091815260200190565b60405160208183030381529060405290505f5b602081101561341b578181815181106133fe576133fe613f21565b01602001516001600160f81b0319165f0361341b576001016133e3565b61342681602061417b565b6001600160401b0381111561343d5761343d613bf7565b6040519080825280601f01601f191660200182016040528015613467576020820181803683370190505b5092505f5b8351811015611a715782826134808161430e565b93508151811061349257613492613f21565b602001015160f81c60f81b8482815181106134af576134af613f21565b60200101906001600160f81b03191690815f1a90535060010161346c565b6060815160011480156134f957506080825f815181106134ef576134ef613f21565b016020015160f81c105b15613502575090565b61350e825160806137b8565b82604051602001612192929190614326565b919050565b5f6108bd846135358786866121a8565b8051602091820120825192909101919091201490565b81511561355b5781518083602001fd5b8060405162461bcd60e51b81526004016106d09190614354565b8051606090806001600160401b0381111561359257613592613bf7565b6040519080825280602002602001820160405280156135d757816020015b60408051808201909152606080825260208201528152602001906001900390816135b05790505b5091505f5b81811015611a7357604051806040016040528085838151811061360157613601613f21565b6020026020010151815260200161363086848151811061362357613623613f21565b6020026020010151611f9f565b81525083828151811061364557613645613f21565b60209081029190910101526001016135dc565b606080604051905082518060011b603f8101601f191683016040528083525060208401602083015f5b838110156136ae578060011b8201818401515f1a8060041c8253600f811660018301535050600101613681565b509295945050505050565b60606020825f0151106136d4576136cf82611fb2565b610682565b6106828261395d565b60606106826136fb83602001515f81518110611e6857611e68613f21565b613658565b60608251821061371e575060408051602081019091525f8152610682565b6107ae8383848651613730919061417b565b613971565b5f80825184511061374757825161374a565b83515b90505b80821080156137a1575082828151811061376957613769613f21565b602001015160f81c60f81b6001600160f81b03191684838151811061379057613790613f21565b01602001516001600160f81b031916145b156137b15781600101915061374d565b5092915050565b6060603883101561381c57604080516001808252818301909252906020820181803683370190505090506137ec8284614386565b60f81b815f8151811061380157613801613f21565b60200101906001600160f81b03191690815f1a905350610682565b5f60015b61382a818661439f565b1561385057816138398161430e565b92506138499050610100826143b2565b9050613820565b61385b826001613f49565b6001600160401b0381111561387257613872613bf7565b6040519080825280601f01601f19166020018201604052801561389c576020820181803683370190505b5092506138a98483614386565b6138b4906037614386565b60f81b835f815181106138c9576138c9613f21565b60200101906001600160f81b03191690815f1a905350600190505b818111613955576101006138f8828461417b565b613904906101006144a9565b61390e908761439f565b61391891906144b4565b60f81b83828151811061392d5761392d613f21565b60200101906001600160f81b03191690815f1a9053508061394d8161430e565b9150506138e4565b505092915050565b606061068282602001515f845f015161332a565b60608182601f0110156139b75760405162461bcd60e51b815260206004820152600e60248201526d736c6963655f6f766572666c6f7760901b60448201526064016106d0565b8282840110156139fa5760405162461bcd60e51b815260206004820152600e60248201526d736c6963655f6f766572666c6f7760901b60448201526064016106d0565b81830184511015613a415760405162461bcd60e51b8152602060048201526011602482015270736c6963655f6f75744f66426f756e647360781b60448201526064016106d0565b606082158015613a5f5760405191505f825260208201604052613aa9565b6040519150601f8416801560200281840101858101878315602002848b0101015b81831015613a98578051835260209283019201613a80565b5050858452601f01601f1916604052505b50949350505050565b6001600160a01b0381168114610755575f80fd5b80358015158114613520575f80fd5b5f8060408385031215613ae6575f80fd5b8235613af181613ab2565b9150613aff60208401613ac6565b90509250929050565b5f8060408385031215613b19575f80fd5b8235613b2481613ab2565b946020939093013593505050565b80356001600160401b0381168114613520575f80fd5b5f8060408385031215613b59575f80fd5b613b2483613b32565b5f60208284031215613b72575f80fd5b81356107ae81613ab2565b5f805f8060808587031215613b90575f80fd5b613b9985613b32565b935060208501359250613bae60408601613b32565b9396929550929360600135925050565b5f805f60608486031215613bd0575f80fd5b613bd984613b32565b925060208401359150613bee60408501613ac6565b90509250925092565b634e487b7160e01b5f52604160045260245ffd5b60405160c081016001600160401b0381118282101715613c2d57613c2d613bf7565b60405290565b604051601f8201601f191681016001600160401b0381118282101715613c5b57613c5b613bf7565b604052919050565b5f82601f830112613c72575f80fd5b81356001600160401b03811115613c8b57613c8b613bf7565b613c9e601f8201601f1916602001613c33565b818152846020838601011115613cb2575f80fd5b816020850160208301375f918101602001919091529392505050565b5f8060408385031215613cdf575f80fd5b8235613cea81613ab2565b915060208301356001600160401b03811115613d04575f80fd5b613d1085828601613c63565b9150509250929050565b5f60208284031215613d2a575f80fd5b5035919050565b5f805f805f60808688031215613d45575f80fd5b613d4e86613b32565b94506020860135613d5e81613ab2565b93506040860135925060608601356001600160401b0380821115613d80575f80fd5b818801915088601f830112613d93575f80fd5b813581811115613da1575f80fd5b896020828501011115613db2575f80fd5b9699959850939650602001949392505050565b5f805f60608486031215613dd7575f80fd5b613de084613b32565b92506020840135613df081613ab2565b929592945050506040919091013590565b5f805f60608486031215613e13575f80fd5b613e1c84613b32565b925060208401359150613bee60408501613b32565b5f8060408385031215613e42575f80fd5b82359150613aff60208401613ac6565b5f8060408385031215613e63575f80fd5b8235613e6e81613ab2565b91506020830135613e7e81613ab2565b809150509250929050565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b19195b1959d85d1958d85b1b60a21b606082015260800190565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b6163746976652070726f787960a01b606082015260800190565b634e487b7160e01b5f52603260045260245ffd5b634e487b7160e01b5f52601160045260245ffd5b8082018082111561068257610682613f35565b5f60208284031215613f6c575f80fd5b5051919050565b5f60208284031215613f83575f80fd5b81516107ae81613ab2565b5f6001600160401b03821115613fa657613fa6613bf7565b5060051b60200190565b803560048110613520575f80fd5b5f82601f830112613fcd575f80fd5b81356020613fe2613fdd83613f8e565b613c33565b82815260059290921b84018101918181019086841115614000575f80fd5b8286015b84811015611ee15780356001600160401b03811115614021575f80fd5b61402f8986838b0101613c63565b845250918301918301614004565b5f602080838503121561404e575f80fd5b82356001600160401b0380821115614064575f80fd5b818501915085601f830112614077575f80fd5b8135614085613fdd82613f8e565b81815260059190911b830184019084810190888311156140a3575f80fd5b8585015b8381101561416e578035858111156140bd575f80fd5b860160c0818c03601f190112156140d2575f80fd5b6140da613c0b565b6140e5898301613b32565b815260406140f4818401613b32565b8a8301526060808401358284015260809150614111828501613fb0565b9083015260a08381013589811115614127575f80fd5b6141358f8d83880101613fbe565b838501525060c084013591508882111561414d575f80fd5b61415b8e8c84870101613fbe565b90830152508452509186019186016140a7565b5098975050505050505050565b8181038181111561068257610682613f35565b634e487b7160e01b5f52602160045260245ffd5b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b8051602080830151919081101561420d575f198160200360031b1b821691505b50919050565b5f5b8381101561422d578181015183820152602001614215565b50505f910152565b5f8251614246818460208701614213565b9190910192915050565b634e487b7160e01b5f52601260045260245ffd5b5f60ff83168061427657614276614250565b8060ff84160691505092915050565b60ff828116828216039081111561068257610682613f35565b6020808252604a908201527f524c505265616465723a206c656e677468206f6620616e20524c50206974656d60408201527f206d7573742062652067726561746572207468616e207a65726f20746f206265606082015269206465636f6461626c6560b01b608082015260a00190565b5f6001820161431f5761431f613f35565b5060010190565b5f8351614337818460208801614213565b83519083019061434b818360208801614213565b01949350505050565b602081525f8251806020840152614372816040850160208701614213565b601f01601f19169190910160400192915050565b60ff818116838216019081111561068257610682613f35565b5f826143ad576143ad614250565b500490565b808202811582820484141761068257610682613f35565b600181815b8085111561440357815f19048211156143e9576143e9613f35565b808516156143f657918102915b93841c93908002906143ce565b509250929050565b5f8261441957506001610682565b8161442557505f610682565b816001811461443b576002811461444557614461565b6001915050610682565b60ff84111561445657614456613f35565b50506001821b610682565b5060208310610133831016604e8410600b8410161715614484575081810a610682565b61448e83836143c9565b805f19048211156144a1576144a1613f35565b029392505050565b5f6107ae838361440b565b5f826144c2576144c2614250565b50069056fe524c505265616465723a206c656e677468206f6620636f6e74656e74206d7573360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a26469706673582212205659405515807d049e6589a2728fe0863d5c3072540f53ef4e8701e75661788864736f6c63430008180033