S Price: $0.824303 (-3.87%)

Contract

0xFF1137243698CaA18EE364Cc966CF0e02A4e6327

Overview

S Balance

Sonic LogoSonic LogoSonic Logo0 S

S Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To

There are no matching entries

Please try again later

Parent Transaction Hash Block From To
View All Internal Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
PayloadsController

Compiler Version
v0.8.22+commit.4fc1097e

Optimization Enabled:
Yes with 200 runs

Other Settings:
shanghai EvmVersion
File 1 of 27 : PayloadsController.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.8;

import {PayloadsControllerCore, PayloadsControllerUtils} from './PayloadsControllerCore.sol';
import {IPayloadsController, IBaseReceiverPortal} from './interfaces/IPayloadsController.sol';
import {Errors} from '../libraries/Errors.sol';

/**
 * @title PayloadsController
 * @author BGD Labs
 * @notice Contract with the logic to manage receiving cross chain messages. This contract knows how to receive and
           decode messages from CrossChainController
 */
contract PayloadsController is PayloadsControllerCore, IPayloadsController {
  /// @inheritdoc IPayloadsController
  address public immutable MESSAGE_ORIGINATOR;

  /// @inheritdoc IPayloadsController
  address public immutable CROSS_CHAIN_CONTROLLER;

  /// @inheritdoc IPayloadsController
  uint256 public immutable ORIGIN_CHAIN_ID;

  /**
   * @param crossChainController address of the CrossChainController contract deployed on current chain. This contract
            is the one responsible to send here the voting configurations once they are bridged.
   * @param messageOriginator address of the contract where the message originates (mainnet governance)
   * @param originChainId the id of the network where the messages originate from
   */
  constructor(
    address crossChainController,
    address messageOriginator,
    uint256 originChainId
  ) {
    require(
      crossChainController != address(0),
      Errors.INVALID_CROSS_CHAIN_CONTROLLER_ADDRESS
    );
    require(
      messageOriginator != address(0),
      Errors.INVALID_MESSAGE_ORIGINATOR_ADDRESS
    );
    require(originChainId > 0, Errors.INVALID_ORIGIN_CHAIN_ID);

    CROSS_CHAIN_CONTROLLER = crossChainController;
    MESSAGE_ORIGINATOR = messageOriginator;
    ORIGIN_CHAIN_ID = originChainId;
  }

  /// @inheritdoc IBaseReceiverPortal
  function receiveCrossChainMessage(
    address originSender,
    uint256 originChainId,
    bytes memory message
  ) external {
    require(
      msg.sender == CROSS_CHAIN_CONTROLLER &&
        originSender == MESSAGE_ORIGINATOR &&
        originChainId == ORIGIN_CHAIN_ID,
      Errors.WRONG_MESSAGE_ORIGIN
    );

    try this.decodeMessage(message) returns (
      uint40 payloadId,
      PayloadsControllerUtils.AccessControl accessLevel,
      uint40 proposalVoteActivationTimestamp
    ) {
      _queuePayload(payloadId, accessLevel, proposalVoteActivationTimestamp);
      bytes memory empty;
      emit PayloadExecutionMessageReceived(
        originSender,
        originChainId,
        true,
        message,
        empty
      );
    } catch (bytes memory decodingError) {
      emit PayloadExecutionMessageReceived(
        originSender,
        originChainId,
        false,
        message,
        decodingError
      );
    }
  }

  /// @inheritdoc IPayloadsController
  function decodeMessage(
    bytes memory message
  )
    external
    pure
    returns (uint40, PayloadsControllerUtils.AccessControl, uint40)
  {
    return
      abi.decode(
        message,
        (uint40, PayloadsControllerUtils.AccessControl, uint40)
      );
  }
}

File 2 of 27 : PayloadsControllerCore.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.8;

import {OwnableWithGuardian} from 'aave-delivery-infrastructure/contracts/old-oz/OwnableWithGuardian.sol';
import {Rescuable, RescuableBase} from 'solidity-utils/contracts/utils/Rescuable.sol';
import {IRescuable, IRescuableBase} from 'solidity-utils/contracts/utils/interfaces/IRescuable.sol';
import {IERC20} from 'openzeppelin-contracts/contracts/token/ERC20/IERC20.sol';
import {Initializable} from 'aave-delivery-infrastructure/contracts/old-oz/Initializable.sol';
import {SafeERC20} from 'openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol';
import {SafeCast} from 'openzeppelin-contracts/contracts/utils/math/SafeCast.sol';

import {IPayloadsControllerCore, PayloadsControllerUtils} from './interfaces/IPayloadsControllerCore.sol';
import {IExecutor} from './interfaces/IExecutor.sol';
import {Errors} from '../libraries/Errors.sol';

/**
 * @title PayloadsControllerCore
 * @author BGD Labs
 * @notice this contract contains the logic to create and execute a payload.
 * @dev To execute a created payload, the payload id must be bridged from governance chain.
 * @dev The methods to update the contract configuration are callable only by owner. Owner being the registered
        lvl1 Executor. So to update the PayloadsController configuration, a proposal will need to pass in gov chain and
        be executed by the appropriate executor.
 */
abstract contract PayloadsControllerCore is
  OwnableWithGuardian,
  Rescuable,
  IPayloadsControllerCore,
  Initializable
{
  using SafeCast for uint256;
  using SafeERC20 for IERC20;

  uint40 internal _payloadsCount;

  // stores the executor configuration for every lvl of access control
  mapping(PayloadsControllerUtils.AccessControl => ExecutorConfig)
    internal _accessLevelToExecutorConfig;

  mapping(uint40 => Payload) internal _payloads;

  // should be always set with respect to the proposal flow duration
  // for example: voting takes 5 days + 2 days for bridging + 3 days for cooldown + 2 days of safety gap
  // then expirationDelay should be not less then 12 days.
  // As expiration delay of proposal is 30 days, payload needs to be able to live longer as its created before and
  // will be executed after.
  // so nobody should be able to set expiration delay less then that
  /// @inheritdoc IPayloadsControllerCore
  function EXPIRATION_DELAY() public pure virtual returns (uint40) {
    return 35 days;
  }

  /// @inheritdoc IPayloadsControllerCore
  function GRACE_PERIOD() public pure virtual returns (uint40) {
    return 7 days;
  }

  /// @inheritdoc IPayloadsControllerCore
  function MIN_EXECUTION_DELAY() public view virtual returns (uint40) {
    return 1 days;
  }

  /// @inheritdoc IPayloadsControllerCore
  function MAX_EXECUTION_DELAY() public view virtual returns (uint40) {
    return 10 days;
  }

  function initialize(
    address owner,
    address guardian,
    UpdateExecutorInput[] calldata executors
  ) public virtual initializer {
    require(executors.length != 0, Errors.SHOULD_BE_AT_LEAST_ONE_EXECUTOR);

    _updateExecutors(executors);

    _updateGuardian(guardian);
    _transferOwnership(owner);
  }

  /// @inheritdoc IPayloadsControllerCore
  function createPayload(
    ExecutionAction[] calldata actions
  ) public virtual returns (uint40) {
    require(actions.length != 0, Errors.INVALID_EMPTY_TARGETS);

    uint40 payloadId = _payloadsCount++;
    uint40 creationTime = uint40(block.timestamp);
    Payload storage newPayload = _payloads[payloadId];
    newPayload.creator = msg.sender;
    newPayload.state = PayloadState.Created;
    newPayload.createdAt = creationTime;
    newPayload.expirationTime = creationTime + EXPIRATION_DELAY();
    newPayload.gracePeriod = GRACE_PERIOD();

    PayloadsControllerUtils.AccessControl maximumAccessLevelRequired;
    for (uint256 i = 0; i < actions.length; i++) {
      require(actions[i].target != address(0), Errors.INVALID_ACTION_TARGET);
      require(
        actions[i].accessLevel >
          PayloadsControllerUtils.AccessControl.Level_null,
        Errors.INVALID_ACTION_ACCESS_LEVEL
      );
      require(
        _accessLevelToExecutorConfig[actions[i].accessLevel].executor !=
          address(0),
        Errors.EXECUTOR_WAS_NOT_SPECIFIED_FOR_REQUESTED_ACCESS_LEVEL
      );

      newPayload.actions.push(actions[i]);

      if (actions[i].accessLevel > maximumAccessLevelRequired) {
        maximumAccessLevelRequired = actions[i].accessLevel;
      }
    }
    newPayload.maximumAccessLevelRequired = maximumAccessLevelRequired;
    ExecutorConfig
      memory maxRequiredExecutorConfig = _accessLevelToExecutorConfig[
        maximumAccessLevelRequired
      ];
    newPayload.delay = maxRequiredExecutorConfig.delay;

    emit PayloadCreated(
      payloadId,
      msg.sender,
      actions,
      maximumAccessLevelRequired
    );
    return payloadId;
  }

  /// @inheritdoc IPayloadsControllerCore
  function executePayload(uint40 payloadId) external payable {
    Payload storage payload = _payloads[payloadId];

    require(
      _getPayloadState(payload) == PayloadState.Queued,
      Errors.PAYLOAD_NOT_IN_QUEUED_STATE
    );

    uint256 executionTime = payload.queuedAt + payload.delay;
    require(block.timestamp > executionTime, Errors.TIMELOCK_NOT_FINISHED);

    payload.state = PayloadState.Executed;
    payload.executedAt = uint40(block.timestamp);

    for (uint256 i = 0; i < payload.actions.length; i++) {
      ExecutionAction storage action = payload.actions[i];
      IExecutor executor = IExecutor(
        _accessLevelToExecutorConfig[action.accessLevel].executor
      );

      executor.executeTransaction{value: action.value}(
        action.target,
        action.value,
        action.signature,
        action.callData,
        action.withDelegateCall
      );
    }

    emit PayloadExecuted(payloadId);
  }

  /// @inheritdoc IPayloadsControllerCore
  function cancelPayload(
    uint40 payloadId
  ) external virtual onlyGuardian {
    _cancelPayload(payloadId);
  }

  /// @inheritdoc IPayloadsControllerCore
  function updateExecutors(
    UpdateExecutorInput[] calldata executors
  ) external virtual onlyOwner {
    _updateExecutors(executors);
  }

  /// @inheritdoc IPayloadsControllerCore
  function getPayloadById(
    uint40 payloadId
  ) external view returns (Payload memory) {
    Payload memory payload = _payloads[payloadId];
    payload.state = _getPayloadState(payload);
    return payload;
  }

  /// @inheritdoc IPayloadsControllerCore
  function getPayloadState(
    uint40 payloadId
  ) external view returns (PayloadState) {
    return _getPayloadState(_payloads[payloadId]);
  }

  /// @inheritdoc IPayloadsControllerCore
  function getPayloadsCount() external view returns (uint40) {
    return _payloadsCount;
  }

  /// @inheritdoc IPayloadsControllerCore
  function getExecutorSettingsByAccessControl(
    PayloadsControllerUtils.AccessControl accessControl
  ) external view returns (ExecutorConfig memory) {
    return _accessLevelToExecutorConfig[accessControl];
  }

  /// @inheritdoc Rescuable
  function whoCanRescue()
    public
    view
    override(Rescuable)
    returns (address)
  {
    return owner();
  }

  /// @inheritdoc IRescuableBase
  function maxRescue(
    address erc20Token
  ) public view override(IRescuableBase, RescuableBase) returns (uint256) {
    return IERC20(erc20Token).balanceOf(address(this));
  }

  receive() external payable {}

  /**
   * @notice method to cancel a payload
   * @param payloadId id of the payload that needs to be canceled
   */
  function _cancelPayload(uint40 payloadId) internal {
    Payload storage payload = _payloads[payloadId];

    PayloadState payloadState = _getPayloadState(payload);
    require(
      payloadState < PayloadState.Executed &&
        payloadState >= PayloadState.Created,
      Errors.PAYLOAD_NOT_IN_THE_CORRECT_STATE
    );
    payload.state = PayloadState.Cancelled;
    payload.cancelledAt = uint40(block.timestamp);

    emit PayloadCancelled(payloadId);
  }

  /**
   * @notice method to get the current state of a payload
   * @param payload object with all pertinent payload information
   * @return current state of the payload
   */
  function _getPayloadState(
    Payload memory payload
  ) internal view returns (PayloadState) {
    PayloadState state = payload.state;
    if (state == PayloadState.None || state >= PayloadState.Executed) {
      return state;
    }

    if (
      (state == PayloadState.Created &&
        block.timestamp >= payload.expirationTime) ||
      (state == PayloadState.Queued &&
        block.timestamp >=
        payload.queuedAt + payload.delay + payload.gracePeriod)
    ) {
      return PayloadState.Expired;
    }

    return state;
  }

  /**
   * @notice method to queue a payload
   * @param payloadId id of the payload that needs to be queued
   * @param accessLevel access level used for the proposal voting
   * @param proposalVoteActivationTimestamp proposal vote activation timestamp in seconds
   * @dev this method will be called when a payload is bridged from governance chain
   */
  function _queuePayload(
    uint40 payloadId,
    PayloadsControllerUtils.AccessControl accessLevel,
    uint40 proposalVoteActivationTimestamp
  ) internal {
    Payload storage payload = _payloads[payloadId];
    require(
      _getPayloadState(payload) == PayloadState.Created,
      Errors.PAYLOAD_NOT_IN_CREATED_STATE
    );

    // by allowing >= it enables the proposal to use a higher level of voting configuration
    // than the one set by the payload actions
    require(
      accessLevel >= payload.maximumAccessLevelRequired,
      Errors.INVALID_PROPOSAL_ACCESS_LEVEL
    );
    // this checks that the payload has been created before the proposal vote started.
    // this ensures that the voters where able to check the content of the payload they voted on
    require(
      proposalVoteActivationTimestamp > payload.createdAt,
      Errors.PAYLOAD_NOT_CREATED_BEFORE_PROPOSAL
    );

    payload.state = PayloadState.Queued;
    payload.queuedAt = uint40(block.timestamp);

    emit PayloadQueued(payloadId);
  }

  /**
   * @notice add new executor configs
   * @param executors array of UpdateExecutorInput with needed executor configurations
   */
  function _updateExecutors(UpdateExecutorInput[] memory executors) internal {
    for (uint256 i = 0; i < executors.length; i++) {
      UpdateExecutorInput memory newExecutorConfig = executors[i];

      require(
        newExecutorConfig.executorConfig.executor != address(0),
        Errors.INVALID_EXECUTOR_ADDRESS
      );

      require(
        newExecutorConfig.accessLevel >
          PayloadsControllerUtils.AccessControl.Level_null,
        Errors.INVALID_EXECUTOR_ACCESS_LEVEL
      );

      require(
        newExecutorConfig.executorConfig.delay >= MIN_EXECUTION_DELAY() &&
          newExecutorConfig.executorConfig.delay <= MAX_EXECUTION_DELAY(),
        Errors.INVALID_EXECUTOR_DELAY
      );

      // check that the new executor is not already being used in a different level
      PayloadsControllerUtils.AccessControl levelToCheck = newExecutorConfig
        .accessLevel == PayloadsControllerUtils.AccessControl.Level_1
        ? PayloadsControllerUtils.AccessControl.Level_2
        : PayloadsControllerUtils.AccessControl.Level_1;
      require(
        _accessLevelToExecutorConfig[levelToCheck].executor !=
          newExecutorConfig.executorConfig.executor,
        Errors.EXECUTOR_ALREADY_SET_IN_DIFFERENT_LEVEL
      );

      _accessLevelToExecutorConfig[
        newExecutorConfig.accessLevel
      ] = newExecutorConfig.executorConfig;

      emit ExecutorSet(
        newExecutorConfig.accessLevel,
        newExecutorConfig.executorConfig.executor,
        newExecutorConfig.executorConfig.delay
      );
    }
  }
}

File 3 of 27 : IPayloadsController.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import {IBaseReceiverPortal} from 'aave-delivery-infrastructure/contracts/interfaces/IBaseReceiverPortal.sol';
import {IPayloadsControllerCore} from './IPayloadsControllerCore.sol';
import {PayloadsControllerUtils} from '../PayloadsControllerUtils.sol';

/**
 * @title IPayloadsController
 * @author BGD Labs
 * @notice interface containing the objects, events and methods definitions of the PayloadsController contract
 */
interface IPayloadsController is IBaseReceiverPortal, IPayloadsControllerCore {
  /**
   * @notice get contract address from where the messages come
   * @return address of the message registry
   */
  function CROSS_CHAIN_CONTROLLER() external view returns (address);

  /**
   * @notice get chain id of the message originator network
   * @return chain id of the originator network
   */
  function ORIGIN_CHAIN_ID() external view returns (uint256);

  /**
   * @notice get address of the message sender in originator network
   * @return address of the originator contract
   */
  function MESSAGE_ORIGINATOR() external view returns (address);

  /**
   * @notice method to decode a message from from governance chain
   * @param message encoded message with message type
   * @return payloadId, accessLevel, proposalVoteActivationTimestamp from the decoded message
   */
  function decodeMessage(
    bytes memory message
  )
    external
    pure
    returns (uint40, PayloadsControllerUtils.AccessControl, uint40);
}

File 4 of 27 : Errors.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

/**
 * @title Errors library
 * @author BGD Labs
 * @notice Defines the error messages emitted by the different contracts of the Aave Governance V3
 */
library Errors {
  string public constant VOTING_PORTALS_COUNT_NOT_0 = '1'; // to be able to rescue voting portals count must be 0
  string public constant AT_LEAST_ONE_PAYLOAD = '2'; // to create a proposal, it must have at least one payload
  string public constant VOTING_PORTAL_NOT_APPROVED = '3'; // the voting portal used to vote on proposal must be approved
  string public constant PROPOSITION_POWER_IS_TOO_LOW = '4'; // proposition power of proposal creator must be equal or higher than the specified threshold for the access level
  string public constant PROPOSAL_NOT_IN_CREATED_STATE = '5'; // proposal should be in the CREATED state
  string public constant PROPOSAL_NOT_IN_ACTIVE_STATE = '6'; // proposal must be in an ACTIVE state
  string public constant PROPOSAL_NOT_IN_QUEUED_STATE = '7'; // proposal must be in a QUEUED state
  string public constant VOTING_START_COOLDOWN_PERIOD_NOT_PASSED = '8'; // to activate a proposal vote, the cool down delay must pass
  string public constant CALLER_NOT_A_VALID_VOTING_PORTAL = '9'; // only an allowed voting portal can queue a proposal
  string public constant QUEUE_COOLDOWN_PERIOD_NOT_PASSED = '10'; // to execute a proposal a cooldown delay must pass
  string public constant PROPOSAL_NOT_IN_THE_CORRECT_STATE = '11'; // proposal must be created but not executed yet to be able to be canceled
  string public constant CALLER_NOT_GOVERNANCE = '12'; // caller must be governance
  string public constant VOTER_ALREADY_VOTED_ON_PROPOSAL = '13'; // voter can only vote once per proposal using voting portal
  string public constant WRONG_MESSAGE_ORIGIN = '14'; // received message must come from registered source address, chain id, CrossChainController
  string public constant NO_VOTING_ASSETS = '15'; // Strategy must have voting assets
  string public constant PROPOSAL_VOTE_ALREADY_CREATED = '16'; // vote on proposal can only be created once
  string public constant INVALID_SIGNATURE = '17'; // submitted signature is not valid
  string public constant PROPOSAL_VOTE_NOT_FINISHED = '18'; // proposal vote must be finished
  string public constant PROPOSAL_VOTE_NOT_IN_ACTIVE_STATE = '19'; // proposal vote must be in active state
  string public constant PROPOSAL_VOTE_ALREADY_EXISTS = '20'; // proposal vote already exists
  string public constant VOTE_ONCE_FOR_ASSET = '21'; // an asset can only be used once per vote
  string public constant USER_BALANCE_DOES_NOT_EXISTS = '22'; // to vote an user must have balance in the token the user is voting with
  string public constant USER_VOTING_BALANCE_IS_ZERO = '23'; // to vote an user must have some balance between all the tokens selected for voting
  string public constant MISSING_AAVE_ROOTS = '24'; // must have AAVE roots registered to use strategy
  string public constant MISSING_STK_AAVE_ROOTS = '25'; // must have stkAAVE roots registered to use strategy
  string public constant MISSING_STK_AAVE_SLASHING_EXCHANGE_RATE = '26'; // must have stkAAVE slashing exchange rate registered to use strategy
  string public constant UNPROCESSED_STORAGE_ROOT = '27'; // root must be registered beforehand
  string public constant NOT_ENOUGH_MSG_VALUE = '28'; // method was not called with enough value to execute the call
  string public constant FAILED_ACTION_EXECUTION = '29'; // action failed to execute
  string public constant SHOULD_BE_AT_LEAST_ONE_EXECUTOR = '30'; // at least one executor is needed
  string public constant INVALID_EMPTY_TARGETS = '31'; // target of the payload execution must not be empty
  string public constant EXECUTOR_WAS_NOT_SPECIFIED_FOR_REQUESTED_ACCESS_LEVEL =
    '32'; // payload executor must be registered for the specified payload access level
  string public constant PAYLOAD_NOT_IN_QUEUED_STATE = '33'; // payload must be en the queued state
  string public constant TIMELOCK_NOT_FINISHED = '34'; // delay has not passed before execution can be called
  string public constant PAYLOAD_NOT_IN_THE_CORRECT_STATE = '35'; // payload must be created but not executed yet to be able to be canceled
  string public constant PAYLOAD_NOT_IN_CREATED_STATE = '36'; // payload must be in the created state
  string public constant MISSING_A_AAVE_ROOTS = '37'; // must have aAAVE roots registered to use strategy
  string public constant MISSING_PROPOSAL_BLOCK_HASH = '38'; // block hash for this proposal was not bridged before
  string public constant PROPOSAL_VOTE_CONFIGURATION_ALREADY_BRIDGED = '39'; // configuration for this proposal bridged already
  string public constant INVALID_VOTING_PORTAL_ADDRESS = '40'; // voting portal address can't be 0x0
  string public constant INVALID_POWER_STRATEGY = '41'; // 0x0 is not valid as the power strategy
  string public constant INVALID_EXECUTOR_ADDRESS = '42'; // executor address can't be 0x0
  string public constant EXECUTOR_ALREADY_SET_IN_DIFFERENT_LEVEL = '43'; // executor address already being used as executor of a different level
  string public constant INVALID_VOTING_DURATION = '44'; // voting duration can not be bigger than the time it takes to execute a proposal
  string public constant VOTING_DURATION_NOT_PASSED = '45'; // at least votingDuration should have passed since voting started for a proposal to be queued
  string public constant INVALID_PROPOSAL_ACCESS_LEVEL = '46'; // the bridged proposal access level does not correspond with the maximum access level required by the payload
  string public constant PAYLOAD_NOT_CREATED_BEFORE_PROPOSAL = '47'; // payload must be created before proposal
  string public constant INVALID_CROSS_CHAIN_CONTROLLER_ADDRESS = '48';
  string public constant INVALID_MESSAGE_ORIGINATOR_ADDRESS = '49';
  string public constant INVALID_ORIGIN_CHAIN_ID = '50';
  string public constant INVALID_ACTION_TARGET = '51';
  string public constant INVALID_ACTION_ACCESS_LEVEL = '52';
  string public constant INVALID_EXECUTOR_ACCESS_LEVEL = '53';
  string public constant INVALID_VOTING_PORTAL_CROSS_CHAIN_CONTROLLER = '54';
  string public constant INVALID_VOTING_PORTAL_VOTING_MACHINE = '55';
  string public constant INVALID_VOTING_PORTAL_GOVERNANCE = '56';
  string public constant INVALID_VOTING_MACHINE_CHAIN_ID = '57';
  string public constant G_INVALID_CROSS_CHAIN_CONTROLLER_ADDRESS = '58';
  string public constant G_INVALID_IPFS_HASH = '59';
  string public constant G_INVALID_PAYLOAD_ACCESS_LEVEL = '60';
  string public constant G_INVALID_PAYLOADS_CONTROLLER = '61';
  string public constant G_INVALID_PAYLOAD_CHAIN = '62';
  string public constant POWER_STRATEGY_HAS_NO_TOKENS = '63'; // power strategy should at least have
  string public constant INVALID_VOTING_CONFIG_ACCESS_LEVEL = '64';
  string public constant VOTING_DURATION_TOO_SMALL = '65';
  string public constant NO_BRIDGED_VOTING_ASSETS = '66';
  string public constant INVALID_VOTER = '67';
  string public constant INVALID_DATA_WAREHOUSE = '68';
  string public constant INVALID_VOTING_MACHINE_CROSS_CHAIN_CONTROLLER = '69';
  string public constant INVALID_L1_VOTING_PORTAL = '70';
  string public constant INVALID_VOTING_PORTAL_CHAIN_ID = '71';
  string public constant INVALID_VOTING_STRATEGY = '72';
  string public constant INVALID_VOTE_CONFIGURATION_BLOCKHASH = '73';
  string public constant INVALID_VOTE_CONFIGURATION_VOTING_DURATION = '74';
  string public constant INVALID_GAS_LIMIT = '75';
  string public constant INVALID_VOTING_CONFIGS = '76'; // a lvl2 voting configuration must be sent to initializer
  string public constant INVALID_EXECUTOR_DELAY = '77';
  string public constant REPEATED_STRATEGY_ASSET = '78';
  string public constant EMPTY_ASSET_STORAGE_SLOTS = '79';
  string public constant REPEATED_STRATEGY_ASSET_SLOT = '80';
  string public constant INVALID_EXECUTION_TARGET = '81';
  string public constant MISSING_VOTING_CONFIGURATIONS = '82'; // voting configurations for lvl1 and lvl2 must be included on initialization
  string public constant INVALID_PROPOSITION_POWER = '83';
  string public constant INVALID_YES_THRESHOLD = '84';
  string public constant INVALID_YES_NO_DIFFERENTIAL = '85';
  string public constant ETH_TRANSFER_FAILED = '86';
  string public constant INVALID_INITIAL_VOTING_CONFIGS = '87'; // initial voting configurations can not be of the same level
  string public constant INVALID_VOTING_PORTAL_ADDRESS_IN_VOTING_MACHINE = '88';
  string public constant INVALID_VOTING_PORTAL_OWNER = '89';
  string public constant CANCELLATION_FEE_REDEEM_FAILED = '90'; // cancellation fee was not able to be redeemed
  string public constant INVALID_CANCELLATION_FEE_COLLECTOR = '91'; // collector can not be address 0
  string public constant INVALID_CANCELLATION_FEE_SENT = '92'; // cancellation fee sent does not match the needed amount
  string public constant CANCELLATION_FEE_ALREADY_REDEEMED = '93'; // cancellation fee already redeemed
  string public constant INVALID_STATE_TO_REDEEM_CANCELLATION_FEE = '94'; // proposal state is not a valid state to redeem cancellation fee
  string public constant MISSING_REPRESENTATION_ROOTS = '95'; // to represent a voter the representation roots need to be registered
  string public constant CALLER_IS_NOT_VOTER_REPRESENTATIVE = '96'; // to represent a voter, caller must be the stored representative
  string public constant VM_INVALID_GOVERNANCE_ADDRESS = '97'; // governance address can not be 0
  string public constant ALL_DELEGATION_ACTIONS_FAILED = '98'; // all meta delegation actions failed on MetaDelegateHelper
  string public constant ONLY_BY_PAYLOADS_MANAGER = '99'; // only payloads manager can call this function
  string public constant ONLY_BY_PAYLOADS_MANAGER_OR_GUARDIAN = '100'; // only payloads manager or guardian can call this function
  string public constant FUNCTION_NOT_SUPPORTED = '101'; // function not supported
}

File 5 of 27 : OwnableWithGuardian.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.7.0;

import {IWithGuardian} from './interfaces/IWithGuardian.sol';
import {Ownable} from 'openzeppelin-contracts/contracts/access/Ownable.sol';

abstract contract OwnableWithGuardian is Ownable, IWithGuardian {
  address private _guardian;

  constructor() Ownable(_msgSender()) {
    _updateGuardian(_msgSender());
  }

  modifier onlyGuardian() {
    _checkGuardian();
    _;
  }
  modifier onlyOwnerOrGuardian() {
    _checkOwnerOrGuardian();
    _;
  }
  function guardian() public view override returns (address) {
    return _guardian;
  }
  /// @inheritdoc IWithGuardian
  function updateGuardian(address newGuardian) external override onlyOwnerOrGuardian {
    _updateGuardian(newGuardian);
  }
  /**
   * @dev method to update the guardian
   * @param newGuardian the new guardian address
   */
  function _updateGuardian(address newGuardian) internal {
    address oldGuardian = _guardian;
    _guardian = newGuardian;
    emit GuardianUpdated(oldGuardian, newGuardian);
  }

  function _checkGuardian() internal view {
    require(guardian() == _msgSender(), 'ONLY_BY_GUARDIAN');
  }

  function _checkOwnerOrGuardian() internal view {
    require(_msgSender() == owner() || _msgSender() == guardian(), 'ONLY_BY_OWNER_OR_GUARDIAN');
  }
}

File 6 of 27 : Rescuable.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.8;

import {IERC20} from 'openzeppelin-contracts/contracts/token/ERC20/IERC20.sol';
import {RescuableBase} from './RescuableBase.sol';
import {IRescuable} from './interfaces/IRescuable.sol';

/**
 * @title Rescuable
 * @author BGD Labs
 * @notice abstract contract with the methods to rescue tokens (ERC20 and native)  from a contract
 */
abstract contract Rescuable is RescuableBase, IRescuable {
  /// @notice modifier that checks that caller is allowed address
  modifier onlyRescueGuardian() {
    if (msg.sender != whoCanRescue()) {
      revert OnlyRescueGuardian();
    }
    _;
  }

  /// @inheritdoc IRescuable
  function emergencyTokenTransfer(
    address erc20Token,
    address to,
    uint256 amount
  ) external virtual onlyRescueGuardian {
    _emergencyTokenTransfer(erc20Token, to, amount);
  }

  /// @inheritdoc IRescuable
  function emergencyEtherTransfer(address to, uint256 amount) external virtual onlyRescueGuardian {
    _emergencyEtherTransfer(to, amount);
  }

  function whoCanRescue() public view virtual returns (address);
}

File 7 of 27 : IRescuable.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.8;

import {IRescuableBase} from './IRescuableBase.sol';

/**
 * @title IRescuable
 * @author BGD Labs
 * @notice interface containing the objects, events and methods definitions of the Rescuable contract
 */
interface IRescuable is IRescuableBase {
  error OnlyRescueGuardian();

  /**
   * @notice method called to rescue tokens sent erroneously to the contract. Only callable by owner
   * @param erc20Token address of the token to rescue
   * @param to address to send the tokens
   * @param amount of tokens to rescue
   */
  function emergencyTokenTransfer(address erc20Token, address to, uint256 amount) external;

  /**
   * @notice method called to rescue ether sent erroneously to the contract. Only callable by owner
   * @param to address to send the eth
   * @param amount of eth to rescue
   */
  function emergencyEtherTransfer(address to, uint256 amount) external;
}

File 8 of 27 : IERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.20;

/**
 * @dev Interface of the ERC-20 standard as defined in the ERC.
 */
interface IERC20 {
    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);

    /**
     * @dev Returns the value of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the value of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves a `value` amount of tokens from the caller's account to `to`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address to, uint256 value) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender) external view returns (uint256);

    /**
     * @dev Sets a `value` amount of tokens as the allowance of `spender` over the
     * caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 value) external returns (bool);

    /**
     * @dev Moves a `value` amount of tokens from `from` to `to` using the
     * allowance mechanism. `value` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(address from, address to, uint256 value) external returns (bool);
}

File 9 of 27 : Initializable.sol
// SPDX-License-Identifier: MIT

/**
 * @dev OpenZeppelin Contracts (last updated v4.7.0) (proxy/utils/Initializable.sol)
 * From https://github.com/OpenZeppelin/openzeppelin-contracts/tree/8b778fa20d6d76340c5fac1ed66c80273f05b95a
 *
 * BGD Labs adaptations:
 * - Added a constructor disabling initialization for implementation contracts
 * - Linting
 */

pragma solidity ^0.8.2;

import './Address.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]
 * ```
 * 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 OPINIONATED. Generally is not a good practise to allow initialization of implementations
   */
  constructor() {
    _disableInitializers();
  }

  /**
   * @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. Equivalent to `reinitializer(1)`.
   */
  modifier initializer() {
    bool isTopLevelCall = !_initializing;
    require(
      (isTopLevelCall && _initialized < 1) ||
        (!Address.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.
   *
   * `initializer` is equivalent to `reinitializer(1)`, so 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.
   *
   * 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.
   */
  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.
   */
  function _disableInitializers() internal virtual {
    require(!_initializing, 'Initializable: contract is initializing');
    if (_initialized < type(uint8).max) {
      _initialized = type(uint8).max;
      emit Initialized(type(uint8).max);
    }
  }
}

File 10 of 27 : SafeERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/utils/SafeERC20.sol)

pragma solidity ^0.8.20;

import {IERC20} from "../IERC20.sol";
import {IERC1363} from "../../../interfaces/IERC1363.sol";
import {Address} from "../../../utils/Address.sol";

/**
 * @title SafeERC20
 * @dev Wrappers around ERC-20 operations that throw on failure (when the token
 * contract returns false). Tokens that return no value (and instead revert or
 * throw on failure) are also supported, non-reverting calls are assumed to be
 * successful.
 * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
 * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
 */
library SafeERC20 {
    /**
     * @dev An operation with an ERC-20 token failed.
     */
    error SafeERC20FailedOperation(address token);

    /**
     * @dev Indicates a failed `decreaseAllowance` request.
     */
    error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);

    /**
     * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,
     * non-reverting calls are assumed to be successful.
     */
    function safeTransfer(IERC20 token, address to, uint256 value) internal {
        _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));
    }

    /**
     * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the
     * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.
     */
    function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
        _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));
    }

    /**
     * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
     * non-reverting calls are assumed to be successful.
     *
     * IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the "client"
     * smart contract uses ERC-7674 to set temporary allowances, then the "client" smart contract should avoid using
     * this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract
     * that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.
     */
    function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
        uint256 oldAllowance = token.allowance(address(this), spender);
        forceApprove(token, spender, oldAllowance + value);
    }

    /**
     * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no
     * value, non-reverting calls are assumed to be successful.
     *
     * IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the "client"
     * smart contract uses ERC-7674 to set temporary allowances, then the "client" smart contract should avoid using
     * this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract
     * that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.
     */
    function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {
        unchecked {
            uint256 currentAllowance = token.allowance(address(this), spender);
            if (currentAllowance < requestedDecrease) {
                revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);
            }
            forceApprove(token, spender, currentAllowance - requestedDecrease);
        }
    }

    /**
     * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,
     * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval
     * to be set to zero before setting it to a non-zero value, such as USDT.
     *
     * NOTE: If the token implements ERC-7674, this function will not modify any temporary allowance. This function
     * only sets the "standard" allowance. Any temporary allowance will remain active, in addition to the value being
     * set here.
     */
    function forceApprove(IERC20 token, address spender, uint256 value) internal {
        bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));

        if (!_callOptionalReturnBool(token, approvalCall)) {
            _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));
            _callOptionalReturn(token, approvalCall);
        }
    }

    /**
     * @dev Performs an {ERC1363} transferAndCall, with a fallback to the simple {ERC20} transfer if the target has no
     * code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when
     * targeting contracts.
     *
     * Reverts if the returned value is other than `true`.
     */
    function transferAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {
        if (to.code.length == 0) {
            safeTransfer(token, to, value);
        } else if (!token.transferAndCall(to, value, data)) {
            revert SafeERC20FailedOperation(address(token));
        }
    }

    /**
     * @dev Performs an {ERC1363} transferFromAndCall, with a fallback to the simple {ERC20} transferFrom if the target
     * has no code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when
     * targeting contracts.
     *
     * Reverts if the returned value is other than `true`.
     */
    function transferFromAndCallRelaxed(
        IERC1363 token,
        address from,
        address to,
        uint256 value,
        bytes memory data
    ) internal {
        if (to.code.length == 0) {
            safeTransferFrom(token, from, to, value);
        } else if (!token.transferFromAndCall(from, to, value, data)) {
            revert SafeERC20FailedOperation(address(token));
        }
    }

    /**
     * @dev Performs an {ERC1363} approveAndCall, with a fallback to the simple {ERC20} approve if the target has no
     * code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when
     * targeting contracts.
     *
     * NOTE: When the recipient address (`to`) has no code (i.e. is an EOA), this function behaves as {forceApprove}.
     * Opposedly, when the recipient address (`to`) has code, this function only attempts to call {ERC1363-approveAndCall}
     * once without retrying, and relies on the returned value to be true.
     *
     * Reverts if the returned value is other than `true`.
     */
    function approveAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {
        if (to.code.length == 0) {
            forceApprove(token, to, value);
        } else if (!token.approveAndCall(to, value, data)) {
            revert SafeERC20FailedOperation(address(token));
        }
    }

    /**
     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
     * on the return value: the return value is optional (but if data is returned, it must not be false).
     * @param token The token targeted by the call.
     * @param data The call data (encoded using abi.encode or one of its variants).
     *
     * This is a variant of {_callOptionalReturnBool} that reverts if call fails to meet the requirements.
     */
    function _callOptionalReturn(IERC20 token, bytes memory data) private {
        uint256 returnSize;
        uint256 returnValue;
        assembly ("memory-safe") {
            let success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20)
            // bubble errors
            if iszero(success) {
                let ptr := mload(0x40)
                returndatacopy(ptr, 0, returndatasize())
                revert(ptr, returndatasize())
            }
            returnSize := returndatasize()
            returnValue := mload(0)
        }

        if (returnSize == 0 ? address(token).code.length == 0 : returnValue != 1) {
            revert SafeERC20FailedOperation(address(token));
        }
    }

    /**
     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
     * on the return value: the return value is optional (but if data is returned, it must not be false).
     * @param token The token targeted by the call.
     * @param data The call data (encoded using abi.encode or one of its variants).
     *
     * This is a variant of {_callOptionalReturn} that silently catches all reverts and returns a bool instead.
     */
    function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {
        bool success;
        uint256 returnSize;
        uint256 returnValue;
        assembly ("memory-safe") {
            success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20)
            returnSize := returndatasize()
            returnValue := mload(0)
        }
        return success && (returnSize == 0 ? address(token).code.length > 0 : returnValue == 1);
    }
}

File 11 of 27 : SafeCast.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/math/SafeCast.sol)
// This file was procedurally generated from scripts/generate/templates/SafeCast.js.

pragma solidity ^0.8.20;

/**
 * @dev Wrappers over Solidity's uintXX/intXX/bool casting operators with added overflow
 * checks.
 *
 * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can
 * easily result in undesired exploitation or bugs, since developers usually
 * assume that overflows raise errors. `SafeCast` restores this intuition by
 * reverting the transaction when such an operation overflows.
 *
 * Using this library instead of the unchecked operations eliminates an entire
 * class of bugs, so it's recommended to use it always.
 */
library SafeCast {
    /**
     * @dev Value doesn't fit in an uint of `bits` size.
     */
    error SafeCastOverflowedUintDowncast(uint8 bits, uint256 value);

    /**
     * @dev An int value doesn't fit in an uint of `bits` size.
     */
    error SafeCastOverflowedIntToUint(int256 value);

    /**
     * @dev Value doesn't fit in an int of `bits` size.
     */
    error SafeCastOverflowedIntDowncast(uint8 bits, int256 value);

    /**
     * @dev An uint value doesn't fit in an int of `bits` size.
     */
    error SafeCastOverflowedUintToInt(uint256 value);

    /**
     * @dev Returns the downcasted uint248 from uint256, reverting on
     * overflow (when the input is greater than largest uint248).
     *
     * Counterpart to Solidity's `uint248` operator.
     *
     * Requirements:
     *
     * - input must fit into 248 bits
     */
    function toUint248(uint256 value) internal pure returns (uint248) {
        if (value > type(uint248).max) {
            revert SafeCastOverflowedUintDowncast(248, value);
        }
        return uint248(value);
    }

    /**
     * @dev Returns the downcasted uint240 from uint256, reverting on
     * overflow (when the input is greater than largest uint240).
     *
     * Counterpart to Solidity's `uint240` operator.
     *
     * Requirements:
     *
     * - input must fit into 240 bits
     */
    function toUint240(uint256 value) internal pure returns (uint240) {
        if (value > type(uint240).max) {
            revert SafeCastOverflowedUintDowncast(240, value);
        }
        return uint240(value);
    }

    /**
     * @dev Returns the downcasted uint232 from uint256, reverting on
     * overflow (when the input is greater than largest uint232).
     *
     * Counterpart to Solidity's `uint232` operator.
     *
     * Requirements:
     *
     * - input must fit into 232 bits
     */
    function toUint232(uint256 value) internal pure returns (uint232) {
        if (value > type(uint232).max) {
            revert SafeCastOverflowedUintDowncast(232, value);
        }
        return uint232(value);
    }

    /**
     * @dev Returns the downcasted uint224 from uint256, reverting on
     * overflow (when the input is greater than largest uint224).
     *
     * Counterpart to Solidity's `uint224` operator.
     *
     * Requirements:
     *
     * - input must fit into 224 bits
     */
    function toUint224(uint256 value) internal pure returns (uint224) {
        if (value > type(uint224).max) {
            revert SafeCastOverflowedUintDowncast(224, value);
        }
        return uint224(value);
    }

    /**
     * @dev Returns the downcasted uint216 from uint256, reverting on
     * overflow (when the input is greater than largest uint216).
     *
     * Counterpart to Solidity's `uint216` operator.
     *
     * Requirements:
     *
     * - input must fit into 216 bits
     */
    function toUint216(uint256 value) internal pure returns (uint216) {
        if (value > type(uint216).max) {
            revert SafeCastOverflowedUintDowncast(216, value);
        }
        return uint216(value);
    }

    /**
     * @dev Returns the downcasted uint208 from uint256, reverting on
     * overflow (when the input is greater than largest uint208).
     *
     * Counterpart to Solidity's `uint208` operator.
     *
     * Requirements:
     *
     * - input must fit into 208 bits
     */
    function toUint208(uint256 value) internal pure returns (uint208) {
        if (value > type(uint208).max) {
            revert SafeCastOverflowedUintDowncast(208, value);
        }
        return uint208(value);
    }

    /**
     * @dev Returns the downcasted uint200 from uint256, reverting on
     * overflow (when the input is greater than largest uint200).
     *
     * Counterpart to Solidity's `uint200` operator.
     *
     * Requirements:
     *
     * - input must fit into 200 bits
     */
    function toUint200(uint256 value) internal pure returns (uint200) {
        if (value > type(uint200).max) {
            revert SafeCastOverflowedUintDowncast(200, value);
        }
        return uint200(value);
    }

    /**
     * @dev Returns the downcasted uint192 from uint256, reverting on
     * overflow (when the input is greater than largest uint192).
     *
     * Counterpart to Solidity's `uint192` operator.
     *
     * Requirements:
     *
     * - input must fit into 192 bits
     */
    function toUint192(uint256 value) internal pure returns (uint192) {
        if (value > type(uint192).max) {
            revert SafeCastOverflowedUintDowncast(192, value);
        }
        return uint192(value);
    }

    /**
     * @dev Returns the downcasted uint184 from uint256, reverting on
     * overflow (when the input is greater than largest uint184).
     *
     * Counterpart to Solidity's `uint184` operator.
     *
     * Requirements:
     *
     * - input must fit into 184 bits
     */
    function toUint184(uint256 value) internal pure returns (uint184) {
        if (value > type(uint184).max) {
            revert SafeCastOverflowedUintDowncast(184, value);
        }
        return uint184(value);
    }

    /**
     * @dev Returns the downcasted uint176 from uint256, reverting on
     * overflow (when the input is greater than largest uint176).
     *
     * Counterpart to Solidity's `uint176` operator.
     *
     * Requirements:
     *
     * - input must fit into 176 bits
     */
    function toUint176(uint256 value) internal pure returns (uint176) {
        if (value > type(uint176).max) {
            revert SafeCastOverflowedUintDowncast(176, value);
        }
        return uint176(value);
    }

    /**
     * @dev Returns the downcasted uint168 from uint256, reverting on
     * overflow (when the input is greater than largest uint168).
     *
     * Counterpart to Solidity's `uint168` operator.
     *
     * Requirements:
     *
     * - input must fit into 168 bits
     */
    function toUint168(uint256 value) internal pure returns (uint168) {
        if (value > type(uint168).max) {
            revert SafeCastOverflowedUintDowncast(168, value);
        }
        return uint168(value);
    }

    /**
     * @dev Returns the downcasted uint160 from uint256, reverting on
     * overflow (when the input is greater than largest uint160).
     *
     * Counterpart to Solidity's `uint160` operator.
     *
     * Requirements:
     *
     * - input must fit into 160 bits
     */
    function toUint160(uint256 value) internal pure returns (uint160) {
        if (value > type(uint160).max) {
            revert SafeCastOverflowedUintDowncast(160, value);
        }
        return uint160(value);
    }

    /**
     * @dev Returns the downcasted uint152 from uint256, reverting on
     * overflow (when the input is greater than largest uint152).
     *
     * Counterpart to Solidity's `uint152` operator.
     *
     * Requirements:
     *
     * - input must fit into 152 bits
     */
    function toUint152(uint256 value) internal pure returns (uint152) {
        if (value > type(uint152).max) {
            revert SafeCastOverflowedUintDowncast(152, value);
        }
        return uint152(value);
    }

    /**
     * @dev Returns the downcasted uint144 from uint256, reverting on
     * overflow (when the input is greater than largest uint144).
     *
     * Counterpart to Solidity's `uint144` operator.
     *
     * Requirements:
     *
     * - input must fit into 144 bits
     */
    function toUint144(uint256 value) internal pure returns (uint144) {
        if (value > type(uint144).max) {
            revert SafeCastOverflowedUintDowncast(144, value);
        }
        return uint144(value);
    }

    /**
     * @dev Returns the downcasted uint136 from uint256, reverting on
     * overflow (when the input is greater than largest uint136).
     *
     * Counterpart to Solidity's `uint136` operator.
     *
     * Requirements:
     *
     * - input must fit into 136 bits
     */
    function toUint136(uint256 value) internal pure returns (uint136) {
        if (value > type(uint136).max) {
            revert SafeCastOverflowedUintDowncast(136, value);
        }
        return uint136(value);
    }

    /**
     * @dev Returns the downcasted uint128 from uint256, reverting on
     * overflow (when the input is greater than largest uint128).
     *
     * Counterpart to Solidity's `uint128` operator.
     *
     * Requirements:
     *
     * - input must fit into 128 bits
     */
    function toUint128(uint256 value) internal pure returns (uint128) {
        if (value > type(uint128).max) {
            revert SafeCastOverflowedUintDowncast(128, value);
        }
        return uint128(value);
    }

    /**
     * @dev Returns the downcasted uint120 from uint256, reverting on
     * overflow (when the input is greater than largest uint120).
     *
     * Counterpart to Solidity's `uint120` operator.
     *
     * Requirements:
     *
     * - input must fit into 120 bits
     */
    function toUint120(uint256 value) internal pure returns (uint120) {
        if (value > type(uint120).max) {
            revert SafeCastOverflowedUintDowncast(120, value);
        }
        return uint120(value);
    }

    /**
     * @dev Returns the downcasted uint112 from uint256, reverting on
     * overflow (when the input is greater than largest uint112).
     *
     * Counterpart to Solidity's `uint112` operator.
     *
     * Requirements:
     *
     * - input must fit into 112 bits
     */
    function toUint112(uint256 value) internal pure returns (uint112) {
        if (value > type(uint112).max) {
            revert SafeCastOverflowedUintDowncast(112, value);
        }
        return uint112(value);
    }

    /**
     * @dev Returns the downcasted uint104 from uint256, reverting on
     * overflow (when the input is greater than largest uint104).
     *
     * Counterpart to Solidity's `uint104` operator.
     *
     * Requirements:
     *
     * - input must fit into 104 bits
     */
    function toUint104(uint256 value) internal pure returns (uint104) {
        if (value > type(uint104).max) {
            revert SafeCastOverflowedUintDowncast(104, value);
        }
        return uint104(value);
    }

    /**
     * @dev Returns the downcasted uint96 from uint256, reverting on
     * overflow (when the input is greater than largest uint96).
     *
     * Counterpart to Solidity's `uint96` operator.
     *
     * Requirements:
     *
     * - input must fit into 96 bits
     */
    function toUint96(uint256 value) internal pure returns (uint96) {
        if (value > type(uint96).max) {
            revert SafeCastOverflowedUintDowncast(96, value);
        }
        return uint96(value);
    }

    /**
     * @dev Returns the downcasted uint88 from uint256, reverting on
     * overflow (when the input is greater than largest uint88).
     *
     * Counterpart to Solidity's `uint88` operator.
     *
     * Requirements:
     *
     * - input must fit into 88 bits
     */
    function toUint88(uint256 value) internal pure returns (uint88) {
        if (value > type(uint88).max) {
            revert SafeCastOverflowedUintDowncast(88, value);
        }
        return uint88(value);
    }

    /**
     * @dev Returns the downcasted uint80 from uint256, reverting on
     * overflow (when the input is greater than largest uint80).
     *
     * Counterpart to Solidity's `uint80` operator.
     *
     * Requirements:
     *
     * - input must fit into 80 bits
     */
    function toUint80(uint256 value) internal pure returns (uint80) {
        if (value > type(uint80).max) {
            revert SafeCastOverflowedUintDowncast(80, value);
        }
        return uint80(value);
    }

    /**
     * @dev Returns the downcasted uint72 from uint256, reverting on
     * overflow (when the input is greater than largest uint72).
     *
     * Counterpart to Solidity's `uint72` operator.
     *
     * Requirements:
     *
     * - input must fit into 72 bits
     */
    function toUint72(uint256 value) internal pure returns (uint72) {
        if (value > type(uint72).max) {
            revert SafeCastOverflowedUintDowncast(72, value);
        }
        return uint72(value);
    }

    /**
     * @dev Returns the downcasted uint64 from uint256, reverting on
     * overflow (when the input is greater than largest uint64).
     *
     * Counterpart to Solidity's `uint64` operator.
     *
     * Requirements:
     *
     * - input must fit into 64 bits
     */
    function toUint64(uint256 value) internal pure returns (uint64) {
        if (value > type(uint64).max) {
            revert SafeCastOverflowedUintDowncast(64, value);
        }
        return uint64(value);
    }

    /**
     * @dev Returns the downcasted uint56 from uint256, reverting on
     * overflow (when the input is greater than largest uint56).
     *
     * Counterpart to Solidity's `uint56` operator.
     *
     * Requirements:
     *
     * - input must fit into 56 bits
     */
    function toUint56(uint256 value) internal pure returns (uint56) {
        if (value > type(uint56).max) {
            revert SafeCastOverflowedUintDowncast(56, value);
        }
        return uint56(value);
    }

    /**
     * @dev Returns the downcasted uint48 from uint256, reverting on
     * overflow (when the input is greater than largest uint48).
     *
     * Counterpart to Solidity's `uint48` operator.
     *
     * Requirements:
     *
     * - input must fit into 48 bits
     */
    function toUint48(uint256 value) internal pure returns (uint48) {
        if (value > type(uint48).max) {
            revert SafeCastOverflowedUintDowncast(48, value);
        }
        return uint48(value);
    }

    /**
     * @dev Returns the downcasted uint40 from uint256, reverting on
     * overflow (when the input is greater than largest uint40).
     *
     * Counterpart to Solidity's `uint40` operator.
     *
     * Requirements:
     *
     * - input must fit into 40 bits
     */
    function toUint40(uint256 value) internal pure returns (uint40) {
        if (value > type(uint40).max) {
            revert SafeCastOverflowedUintDowncast(40, value);
        }
        return uint40(value);
    }

    /**
     * @dev Returns the downcasted uint32 from uint256, reverting on
     * overflow (when the input is greater than largest uint32).
     *
     * Counterpart to Solidity's `uint32` operator.
     *
     * Requirements:
     *
     * - input must fit into 32 bits
     */
    function toUint32(uint256 value) internal pure returns (uint32) {
        if (value > type(uint32).max) {
            revert SafeCastOverflowedUintDowncast(32, value);
        }
        return uint32(value);
    }

    /**
     * @dev Returns the downcasted uint24 from uint256, reverting on
     * overflow (when the input is greater than largest uint24).
     *
     * Counterpart to Solidity's `uint24` operator.
     *
     * Requirements:
     *
     * - input must fit into 24 bits
     */
    function toUint24(uint256 value) internal pure returns (uint24) {
        if (value > type(uint24).max) {
            revert SafeCastOverflowedUintDowncast(24, value);
        }
        return uint24(value);
    }

    /**
     * @dev Returns the downcasted uint16 from uint256, reverting on
     * overflow (when the input is greater than largest uint16).
     *
     * Counterpart to Solidity's `uint16` operator.
     *
     * Requirements:
     *
     * - input must fit into 16 bits
     */
    function toUint16(uint256 value) internal pure returns (uint16) {
        if (value > type(uint16).max) {
            revert SafeCastOverflowedUintDowncast(16, value);
        }
        return uint16(value);
    }

    /**
     * @dev Returns the downcasted uint8 from uint256, reverting on
     * overflow (when the input is greater than largest uint8).
     *
     * Counterpart to Solidity's `uint8` operator.
     *
     * Requirements:
     *
     * - input must fit into 8 bits
     */
    function toUint8(uint256 value) internal pure returns (uint8) {
        if (value > type(uint8).max) {
            revert SafeCastOverflowedUintDowncast(8, value);
        }
        return uint8(value);
    }

    /**
     * @dev Converts a signed int256 into an unsigned uint256.
     *
     * Requirements:
     *
     * - input must be greater than or equal to 0.
     */
    function toUint256(int256 value) internal pure returns (uint256) {
        if (value < 0) {
            revert SafeCastOverflowedIntToUint(value);
        }
        return uint256(value);
    }

    /**
     * @dev Returns the downcasted int248 from int256, reverting on
     * overflow (when the input is less than smallest int248 or
     * greater than largest int248).
     *
     * Counterpart to Solidity's `int248` operator.
     *
     * Requirements:
     *
     * - input must fit into 248 bits
     */
    function toInt248(int256 value) internal pure returns (int248 downcasted) {
        downcasted = int248(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(248, value);
        }
    }

    /**
     * @dev Returns the downcasted int240 from int256, reverting on
     * overflow (when the input is less than smallest int240 or
     * greater than largest int240).
     *
     * Counterpart to Solidity's `int240` operator.
     *
     * Requirements:
     *
     * - input must fit into 240 bits
     */
    function toInt240(int256 value) internal pure returns (int240 downcasted) {
        downcasted = int240(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(240, value);
        }
    }

    /**
     * @dev Returns the downcasted int232 from int256, reverting on
     * overflow (when the input is less than smallest int232 or
     * greater than largest int232).
     *
     * Counterpart to Solidity's `int232` operator.
     *
     * Requirements:
     *
     * - input must fit into 232 bits
     */
    function toInt232(int256 value) internal pure returns (int232 downcasted) {
        downcasted = int232(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(232, value);
        }
    }

    /**
     * @dev Returns the downcasted int224 from int256, reverting on
     * overflow (when the input is less than smallest int224 or
     * greater than largest int224).
     *
     * Counterpart to Solidity's `int224` operator.
     *
     * Requirements:
     *
     * - input must fit into 224 bits
     */
    function toInt224(int256 value) internal pure returns (int224 downcasted) {
        downcasted = int224(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(224, value);
        }
    }

    /**
     * @dev Returns the downcasted int216 from int256, reverting on
     * overflow (when the input is less than smallest int216 or
     * greater than largest int216).
     *
     * Counterpart to Solidity's `int216` operator.
     *
     * Requirements:
     *
     * - input must fit into 216 bits
     */
    function toInt216(int256 value) internal pure returns (int216 downcasted) {
        downcasted = int216(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(216, value);
        }
    }

    /**
     * @dev Returns the downcasted int208 from int256, reverting on
     * overflow (when the input is less than smallest int208 or
     * greater than largest int208).
     *
     * Counterpart to Solidity's `int208` operator.
     *
     * Requirements:
     *
     * - input must fit into 208 bits
     */
    function toInt208(int256 value) internal pure returns (int208 downcasted) {
        downcasted = int208(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(208, value);
        }
    }

    /**
     * @dev Returns the downcasted int200 from int256, reverting on
     * overflow (when the input is less than smallest int200 or
     * greater than largest int200).
     *
     * Counterpart to Solidity's `int200` operator.
     *
     * Requirements:
     *
     * - input must fit into 200 bits
     */
    function toInt200(int256 value) internal pure returns (int200 downcasted) {
        downcasted = int200(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(200, value);
        }
    }

    /**
     * @dev Returns the downcasted int192 from int256, reverting on
     * overflow (when the input is less than smallest int192 or
     * greater than largest int192).
     *
     * Counterpart to Solidity's `int192` operator.
     *
     * Requirements:
     *
     * - input must fit into 192 bits
     */
    function toInt192(int256 value) internal pure returns (int192 downcasted) {
        downcasted = int192(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(192, value);
        }
    }

    /**
     * @dev Returns the downcasted int184 from int256, reverting on
     * overflow (when the input is less than smallest int184 or
     * greater than largest int184).
     *
     * Counterpart to Solidity's `int184` operator.
     *
     * Requirements:
     *
     * - input must fit into 184 bits
     */
    function toInt184(int256 value) internal pure returns (int184 downcasted) {
        downcasted = int184(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(184, value);
        }
    }

    /**
     * @dev Returns the downcasted int176 from int256, reverting on
     * overflow (when the input is less than smallest int176 or
     * greater than largest int176).
     *
     * Counterpart to Solidity's `int176` operator.
     *
     * Requirements:
     *
     * - input must fit into 176 bits
     */
    function toInt176(int256 value) internal pure returns (int176 downcasted) {
        downcasted = int176(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(176, value);
        }
    }

    /**
     * @dev Returns the downcasted int168 from int256, reverting on
     * overflow (when the input is less than smallest int168 or
     * greater than largest int168).
     *
     * Counterpart to Solidity's `int168` operator.
     *
     * Requirements:
     *
     * - input must fit into 168 bits
     */
    function toInt168(int256 value) internal pure returns (int168 downcasted) {
        downcasted = int168(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(168, value);
        }
    }

    /**
     * @dev Returns the downcasted int160 from int256, reverting on
     * overflow (when the input is less than smallest int160 or
     * greater than largest int160).
     *
     * Counterpart to Solidity's `int160` operator.
     *
     * Requirements:
     *
     * - input must fit into 160 bits
     */
    function toInt160(int256 value) internal pure returns (int160 downcasted) {
        downcasted = int160(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(160, value);
        }
    }

    /**
     * @dev Returns the downcasted int152 from int256, reverting on
     * overflow (when the input is less than smallest int152 or
     * greater than largest int152).
     *
     * Counterpart to Solidity's `int152` operator.
     *
     * Requirements:
     *
     * - input must fit into 152 bits
     */
    function toInt152(int256 value) internal pure returns (int152 downcasted) {
        downcasted = int152(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(152, value);
        }
    }

    /**
     * @dev Returns the downcasted int144 from int256, reverting on
     * overflow (when the input is less than smallest int144 or
     * greater than largest int144).
     *
     * Counterpart to Solidity's `int144` operator.
     *
     * Requirements:
     *
     * - input must fit into 144 bits
     */
    function toInt144(int256 value) internal pure returns (int144 downcasted) {
        downcasted = int144(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(144, value);
        }
    }

    /**
     * @dev Returns the downcasted int136 from int256, reverting on
     * overflow (when the input is less than smallest int136 or
     * greater than largest int136).
     *
     * Counterpart to Solidity's `int136` operator.
     *
     * Requirements:
     *
     * - input must fit into 136 bits
     */
    function toInt136(int256 value) internal pure returns (int136 downcasted) {
        downcasted = int136(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(136, value);
        }
    }

    /**
     * @dev Returns the downcasted int128 from int256, reverting on
     * overflow (when the input is less than smallest int128 or
     * greater than largest int128).
     *
     * Counterpart to Solidity's `int128` operator.
     *
     * Requirements:
     *
     * - input must fit into 128 bits
     */
    function toInt128(int256 value) internal pure returns (int128 downcasted) {
        downcasted = int128(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(128, value);
        }
    }

    /**
     * @dev Returns the downcasted int120 from int256, reverting on
     * overflow (when the input is less than smallest int120 or
     * greater than largest int120).
     *
     * Counterpart to Solidity's `int120` operator.
     *
     * Requirements:
     *
     * - input must fit into 120 bits
     */
    function toInt120(int256 value) internal pure returns (int120 downcasted) {
        downcasted = int120(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(120, value);
        }
    }

    /**
     * @dev Returns the downcasted int112 from int256, reverting on
     * overflow (when the input is less than smallest int112 or
     * greater than largest int112).
     *
     * Counterpart to Solidity's `int112` operator.
     *
     * Requirements:
     *
     * - input must fit into 112 bits
     */
    function toInt112(int256 value) internal pure returns (int112 downcasted) {
        downcasted = int112(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(112, value);
        }
    }

    /**
     * @dev Returns the downcasted int104 from int256, reverting on
     * overflow (when the input is less than smallest int104 or
     * greater than largest int104).
     *
     * Counterpart to Solidity's `int104` operator.
     *
     * Requirements:
     *
     * - input must fit into 104 bits
     */
    function toInt104(int256 value) internal pure returns (int104 downcasted) {
        downcasted = int104(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(104, value);
        }
    }

    /**
     * @dev Returns the downcasted int96 from int256, reverting on
     * overflow (when the input is less than smallest int96 or
     * greater than largest int96).
     *
     * Counterpart to Solidity's `int96` operator.
     *
     * Requirements:
     *
     * - input must fit into 96 bits
     */
    function toInt96(int256 value) internal pure returns (int96 downcasted) {
        downcasted = int96(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(96, value);
        }
    }

    /**
     * @dev Returns the downcasted int88 from int256, reverting on
     * overflow (when the input is less than smallest int88 or
     * greater than largest int88).
     *
     * Counterpart to Solidity's `int88` operator.
     *
     * Requirements:
     *
     * - input must fit into 88 bits
     */
    function toInt88(int256 value) internal pure returns (int88 downcasted) {
        downcasted = int88(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(88, value);
        }
    }

    /**
     * @dev Returns the downcasted int80 from int256, reverting on
     * overflow (when the input is less than smallest int80 or
     * greater than largest int80).
     *
     * Counterpart to Solidity's `int80` operator.
     *
     * Requirements:
     *
     * - input must fit into 80 bits
     */
    function toInt80(int256 value) internal pure returns (int80 downcasted) {
        downcasted = int80(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(80, value);
        }
    }

    /**
     * @dev Returns the downcasted int72 from int256, reverting on
     * overflow (when the input is less than smallest int72 or
     * greater than largest int72).
     *
     * Counterpart to Solidity's `int72` operator.
     *
     * Requirements:
     *
     * - input must fit into 72 bits
     */
    function toInt72(int256 value) internal pure returns (int72 downcasted) {
        downcasted = int72(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(72, value);
        }
    }

    /**
     * @dev Returns the downcasted int64 from int256, reverting on
     * overflow (when the input is less than smallest int64 or
     * greater than largest int64).
     *
     * Counterpart to Solidity's `int64` operator.
     *
     * Requirements:
     *
     * - input must fit into 64 bits
     */
    function toInt64(int256 value) internal pure returns (int64 downcasted) {
        downcasted = int64(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(64, value);
        }
    }

    /**
     * @dev Returns the downcasted int56 from int256, reverting on
     * overflow (when the input is less than smallest int56 or
     * greater than largest int56).
     *
     * Counterpart to Solidity's `int56` operator.
     *
     * Requirements:
     *
     * - input must fit into 56 bits
     */
    function toInt56(int256 value) internal pure returns (int56 downcasted) {
        downcasted = int56(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(56, value);
        }
    }

    /**
     * @dev Returns the downcasted int48 from int256, reverting on
     * overflow (when the input is less than smallest int48 or
     * greater than largest int48).
     *
     * Counterpart to Solidity's `int48` operator.
     *
     * Requirements:
     *
     * - input must fit into 48 bits
     */
    function toInt48(int256 value) internal pure returns (int48 downcasted) {
        downcasted = int48(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(48, value);
        }
    }

    /**
     * @dev Returns the downcasted int40 from int256, reverting on
     * overflow (when the input is less than smallest int40 or
     * greater than largest int40).
     *
     * Counterpart to Solidity's `int40` operator.
     *
     * Requirements:
     *
     * - input must fit into 40 bits
     */
    function toInt40(int256 value) internal pure returns (int40 downcasted) {
        downcasted = int40(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(40, value);
        }
    }

    /**
     * @dev Returns the downcasted int32 from int256, reverting on
     * overflow (when the input is less than smallest int32 or
     * greater than largest int32).
     *
     * Counterpart to Solidity's `int32` operator.
     *
     * Requirements:
     *
     * - input must fit into 32 bits
     */
    function toInt32(int256 value) internal pure returns (int32 downcasted) {
        downcasted = int32(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(32, value);
        }
    }

    /**
     * @dev Returns the downcasted int24 from int256, reverting on
     * overflow (when the input is less than smallest int24 or
     * greater than largest int24).
     *
     * Counterpart to Solidity's `int24` operator.
     *
     * Requirements:
     *
     * - input must fit into 24 bits
     */
    function toInt24(int256 value) internal pure returns (int24 downcasted) {
        downcasted = int24(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(24, value);
        }
    }

    /**
     * @dev Returns the downcasted int16 from int256, reverting on
     * overflow (when the input is less than smallest int16 or
     * greater than largest int16).
     *
     * Counterpart to Solidity's `int16` operator.
     *
     * Requirements:
     *
     * - input must fit into 16 bits
     */
    function toInt16(int256 value) internal pure returns (int16 downcasted) {
        downcasted = int16(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(16, value);
        }
    }

    /**
     * @dev Returns the downcasted int8 from int256, reverting on
     * overflow (when the input is less than smallest int8 or
     * greater than largest int8).
     *
     * Counterpart to Solidity's `int8` operator.
     *
     * Requirements:
     *
     * - input must fit into 8 bits
     */
    function toInt8(int256 value) internal pure returns (int8 downcasted) {
        downcasted = int8(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(8, value);
        }
    }

    /**
     * @dev Converts an unsigned uint256 into a signed int256.
     *
     * Requirements:
     *
     * - input must be less than or equal to maxInt256.
     */
    function toInt256(uint256 value) internal pure returns (int256) {
        // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive
        if (value > uint256(type(int256).max)) {
            revert SafeCastOverflowedUintToInt(value);
        }
        return int256(value);
    }

    /**
     * @dev Cast a boolean (false or true) to a uint256 (0 or 1) with no jump.
     */
    function toUint(bool b) internal pure returns (uint256 u) {
        assembly ("memory-safe") {
            u := iszero(iszero(b))
        }
    }
}

File 12 of 27 : IPayloadsControllerCore.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import {IRescuable} from 'solidity-utils/contracts/utils/interfaces/IRescuable.sol';
import {PayloadsControllerUtils} from '../PayloadsControllerUtils.sol';

/**
 * @title IPayloadsControllerCore
 * @author BGD Labs
 * @notice interface containing the objects, events and methods definitions of the IPayloadsControllerCore contract
 */
interface IPayloadsControllerCore is IRescuable {
  /**
   * @notice Enum indicating the possible payload states
   * @dev PayloadState enum defines the state machine of a payload, so the order on which the state is
          defined is important. Check logic correctness if new states are added / removed
   */
  enum PayloadState {
    None, // state 0 left as empty
    Created,
    Queued,
    Executed,
    Cancelled,
    Expired
  }

  /**
   * @notice holds configuration of the executor
   * @param executor address of the executor
   * @param delay time in seconds between queuing and execution
   */
  struct ExecutorConfig {
    address executor;
    uint40 delay;
  }

  /**
   * @notice Object containing the information necessary to set a new executor
   * @param accessLevel level of access that the executor will be assigned to
   * @param executorConfig object containing the configurations for the accessLevel specified
   */
  struct UpdateExecutorInput {
    PayloadsControllerUtils.AccessControl accessLevel;
    ExecutorConfig executorConfig;
  }

  /**
   * @notice Object containing the information necessary to define a payload action
   * @param target address of the contract that needs to be executed
   * @param withDelegateCall boolean indicating if execution needs to be delegated
   * @param accessLevel access level of the executor needed for the execution
   * @param value value amount that needs to be sent to the executeTransaction method
   * @param signature method signature that will be executed
   * @param callData data needed for the execution of the signature
   */
  struct ExecutionAction {
    address target;
    bool withDelegateCall;
    PayloadsControllerUtils.AccessControl accessLevel;
    uint256 value;
    string signature;
    bytes callData;
  }

  /**
   * @notice Object containing a payload information
   * @param creator address of the createPayload method caller
   * @param maximumAccessLevelRequired min level needed to be able to execute all actions
   * @param state indicates the current state of the payload
   * @param createdAt time indicating when payload has been created. In seconds // max is: 1.099511628×10¹² (ie 34'865 years)
   * @param queuedAt time indicating when payload has been queued. In seconds  // max is: 1.099511628×10¹² (ie 34'865 years)
   * @param executedAt time indicating when a payload has been executed. In seconds  // max is: 1.099511628×10¹² (ie 34'865 years)
   * @param cancelledAt time indicating when the payload has been cancelled. In seconds
   * @param expirationTime time indicating when the Payload will expire
   * @param delay time in seconds that a payload must remain queued before execution
   * @param gracePeriod time in seconds that a payload has to be executed
   * @param actions array of actions to be executed
   */
  struct Payload {
    address creator;
    PayloadsControllerUtils.AccessControl maximumAccessLevelRequired;
    PayloadState state;
    uint40 createdAt;
    uint40 queuedAt;
    uint40 executedAt;
    uint40 cancelledAt;
    uint40 expirationTime;
    uint40 delay;
    uint40 gracePeriod;
    ExecutionAction[] actions;
  }

  /**
   * @notice Event emitted when an executor has been set for a determined access level
   * @param accessLevel level of access that the executor will be set to
   * @param executor address that will be set for the determined access level
   * @param delay time in seconds between queuing and execution
   */
  event ExecutorSet(
    PayloadsControllerUtils.AccessControl indexed accessLevel,
    address indexed executor,
    uint40 delay
  );

  /**
   * @notice Event emitted when a payload has been created
   * @param payloadId id of the payload created
   * @param creator address pertaining to the caller of the method createPayload
   * @param actions array of the actions conforming the payload
   * @param maximumAccessLevelRequired maximum level of the access control
   */
  event PayloadCreated(
    uint40 indexed payloadId,
    address indexed creator,
    ExecutionAction[] actions,
    PayloadsControllerUtils.AccessControl indexed maximumAccessLevelRequired
  );

  /**
   * @notice emitted when a cross chain message gets received
   * @param originSender address that sent the message on the origin chain
   * @param originChainId id of the chain where the message originated
   * @param delivered flag indicating if message has been delivered
   * @param message bytes containing the necessary information to queue the bridged payload id
   * @param reason bytes with the revert information
   */
  event PayloadExecutionMessageReceived(
    address indexed originSender,
    uint256 indexed originChainId,
    bool indexed delivered,
    bytes message,
    bytes reason
  );

  /**
   * @notice Event emitted when a payload has been executed
   * @param payloadId id of the payload being enqueued
   */
  event PayloadExecuted(uint40 payloadId);

  /**
   * @notice Event emitted when a payload has been queued
   * @param payloadId id of the payload being enqueued
   */
  event PayloadQueued(uint40 payloadId);

  /**
   * @notice Event emitted when cancelling a payload
   * @param payloadId id of the cancelled payload
   */
  event PayloadCancelled(uint40 payloadId);

  /**
   * @notice method to initialize the contract with starter params. Only callable by proxy
   * @param owner address of the owner of the contract. with permissions to call certain methods
   * @param guardian address of the guardian. With permissions to call certain methods
   * @param executors array of executor configurations
   */
  function initialize(
    address owner,
    address guardian,
    UpdateExecutorInput[] calldata executors
  ) external;

  /**
   * @notice get the expiration delay of a payload
   * @return expiration delay in seconds
   */
  function EXPIRATION_DELAY() external view returns (uint40);

  /**
   * @notice get the maximum time in seconds that a proposal must spend being queued
   * @return max delay in seconds
   */
  function MAX_EXECUTION_DELAY() external view returns (uint40);

  /**
   * @notice get the minimum time in seconds that a proposal must spend being queued
   * @return min delay in seconds
   */
  function MIN_EXECUTION_DELAY() external view returns (uint40);

  /**
   * @notice time in seconds where the proposal can be executed (from executionTime) before it expires
   * @return grace period in seconds
   */
  function GRACE_PERIOD() external view returns (uint40);

  /**
   * @notice get a previously created payload object
   * @param payloadId id of the payload to retrieve
   * @return payload information
   */
  function getPayloadById(
    uint40 payloadId
  ) external view returns (Payload memory);

  /**
   * @notice get the current state of a payload
   * @param payloadId id of the payload to retrieve the state from
   * @return payload state
   */
  function getPayloadState(
    uint40 payloadId
  ) external view returns (PayloadState);

  /**
   * @notice get the total count of payloads created
   * @return number of payloads
   */
  function getPayloadsCount() external view returns (uint40);

  /**
   * @notice method that will create a Payload object for every action sent
   * @param actions array of actions which this proposal payload will contain
   * @return id of the created payload
   */
  function createPayload(
    ExecutionAction[] calldata actions
  ) external returns (uint40);

  /**
   * @notice method to execute a payload
   * @param payloadId id of the payload that needs to be executed
   */
  function executePayload(uint40 payloadId) external payable;

  /**
   * @notice method to cancel a payload
   * @param payloadId id of the payload that needs to be canceled
   */
  function cancelPayload(uint40 payloadId) external;

  /**
   * @notice method to add executors and its configuration
   * @param executors array of UpdateExecutorInput objects
   */
  function updateExecutors(UpdateExecutorInput[] calldata executors) external;

  /**
   * @notice method to get the executor configuration assigned to the specified level
   * @param accessControl level of which we want to get the executor configuration from
   * @return executor configuration
   */
  function getExecutorSettingsByAccessControl(
    PayloadsControllerUtils.AccessControl accessControl
  ) external view returns (ExecutorConfig memory);
}

File 13 of 27 : IExecutor.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

/**
 * @title IExecutor
 * @author BGD Labs
 * @notice interface containing the objects, events and methods definitions of the Executor contract
 */
interface IExecutor {
  /**
   * @notice emitted when an action got executed
   * @param target address of the targeted contract
   * @param value wei value of the transaction
   * @param signature function signature of the transaction
   * @param data function arguments of the transaction or callData if signature empty
   * @param executionTime time at which to execute the transaction
   * @param withDelegatecall boolean, true = transaction delegatecalls the target, else calls the target
   * @param resultData the actual callData used on the target
   **/
  event ExecutedAction(
    address indexed target,
    uint256 value,
    string signature,
    bytes data,
    uint256 executionTime,
    bool withDelegatecall,
    bytes resultData
  );

  /**
   * @notice Function, called by Governance, that executes a transaction, returns the callData executed
   * @param target smart contract target
   * @param value wei value of the transaction
   * @param signature function signature of the transaction
   * @param data function arguments of the transaction or callData if signature empty
   * @param withDelegatecall boolean, true = transaction delegatecalls the target, else calls the target
   * @return result data of the execution call.
   **/
  function executeTransaction(
    address target,
    uint256 value,
    string memory signature,
    bytes memory data,
    bool withDelegatecall
  ) external payable returns (bytes memory);
}

File 14 of 27 : IBaseReceiverPortal.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

/**
 * @title IBaseReceiverPortal
 * @author BGD Labs
 * @notice interface defining the method that needs to be implemented by all receiving portals, as its the one that
           will be called when a received message gets confirmed
 */
interface IBaseReceiverPortal {
  /**
   * @notice method called by CrossChainController when a message has been confirmed
   * @param originSender address of the sender of the bridged message
   * @param originChainId id of the chain where the message originated
   * @param message bytes bridged containing the desired information
   */
  function receiveCrossChainMessage(
    address originSender,
    uint256 originChainId,
    bytes memory message
  ) external;
}

File 15 of 27 : PayloadsControllerUtils.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;

library PayloadsControllerUtils {
  /// @notice enum with supported access levels
  enum AccessControl {
    Level_null, // to not use 0
    Level_1, // LEVEL_1 - short executor before, listing assets, changes of assets params, updates of the protocol etc
    Level_2 // LEVEL_2 - long executor before, payloads controller updates
  }

  /**
   * @notice Object containing the necessary payload information.
   * @param chain
   * @param accessLevel
   * @param payloadsController
   * @param payloadId
   */
  struct Payload {
    uint256 chain;
    AccessControl accessLevel;
    address payloadsController; // address which holds the logic to execute after success proposal voting
    uint40 payloadId; // number of the payload placed to payloadsController, max is: ~10¹²
  }
}

File 16 of 27 : IWithGuardian.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.7.0;

interface IWithGuardian {
  /**
   * @dev Event emitted when guardian gets updated
   * @param oldGuardian address of previous guardian
   * @param newGuardian address of the new guardian
   */
  event GuardianUpdated(address oldGuardian, address newGuardian);

  /**
   * @dev The caller account is not authorized to perform an operation.
   */
  error OnlyGuardianInvalidCaller(address account);

  /**
   * @dev The caller account is not authorized to perform an operation.
   */
  error OnlyGuardianOrOwnerInvalidCaller(address account);

  /**
   * @dev get guardian address;
   */
  function guardian() external view returns (address);
  /**
   * @dev method to update the guardian
   * @param newGuardian the new guardian address
   */
  function updateGuardian(address newGuardian) external;
}

File 17 of 27 : Ownable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)

pragma solidity ^0.8.20;

import {Context} from "../utils/Context.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.
 *
 * The initial owner is set to the address provided by the deployer. 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 Ownable is Context {
    address private _owner;

    /**
     * @dev The caller account is not authorized to perform an operation.
     */
    error OwnableUnauthorizedAccount(address account);

    /**
     * @dev The owner is not a valid owner account. (eg. `address(0)`)
     */
    error OwnableInvalidOwner(address owner);

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    /**
     * @dev Initializes the contract setting the address provided by the deployer as the initial owner.
     */
    constructor(address initialOwner) {
        if (initialOwner == address(0)) {
            revert OwnableInvalidOwner(address(0));
        }
        _transferOwnership(initialOwner);
    }

    /**
     * @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 {
        if (owner() != _msgSender()) {
            revert OwnableUnauthorizedAccount(_msgSender());
        }
    }

    /**
     * @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 {
        if (newOwner == address(0)) {
            revert OwnableInvalidOwner(address(0));
        }
        _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);
    }
}

File 18 of 27 : RescuableBase.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.8;

import {IERC20} from 'openzeppelin-contracts/contracts/token/ERC20/IERC20.sol';
import {SafeERC20} from 'openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol';
import {IRescuableBase} from './interfaces/IRescuableBase.sol';

abstract contract RescuableBase is IRescuableBase {
  using SafeERC20 for IERC20;

  /// @inheritdoc IRescuableBase
  function maxRescue(address erc20Token) public view virtual returns (uint256);

  function _emergencyTokenTransfer(address erc20Token, address to, uint256 amount) internal {
    uint256 max = maxRescue(erc20Token);
    amount = max > amount ? amount : max;
    IERC20(erc20Token).safeTransfer(to, amount);

    emit ERC20Rescued(msg.sender, erc20Token, to, amount);
  }

  function _emergencyEtherTransfer(address to, uint256 amount) internal {
    (bool success, ) = to.call{value: amount}(new bytes(0));
    if (!success) {
      revert EthTransferFailed();
    }

    emit NativeTokensRescued(msg.sender, to, amount);
  }
}

File 19 of 27 : IRescuableBase.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.8;

/**
 * @title IRescuableBase
 * @author BGD Labs
 * @notice interface containing the objects, events and methods definitions of the RescuableBase contract
 */
interface IRescuableBase {
  error EthTransferFailed();
  /**
   * @notice emitted when erc20 tokens get rescued
   * @param caller address that triggers the rescue
   * @param token address of the rescued token
   * @param to address that will receive the rescued tokens
   * @param amount quantity of tokens rescued
   */
  event ERC20Rescued(
    address indexed caller,
    address indexed token,
    address indexed to,
    uint256 amount
  );

  /**
   * @notice emitted when native tokens get rescued
   * @param caller address that triggers the rescue
   * @param to address that will receive the rescued tokens
   * @param amount quantity of tokens rescued
   */
  event NativeTokensRescued(address indexed caller, address indexed to, uint256 amount);

  /**
   * @notice method that defined the maximum amount rescuable for any given asset.
   * @dev there's currently no way to limit the rescuable "native asset", as we assume erc20s as intended underlying.
   * @return the maximum amount of
   */
  function maxRescue(address erc20Token) external view returns (uint256);
}

File 20 of 27 : Address.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol)
// From commit https://github.com/OpenZeppelin/openzeppelin-contracts/commit/8b778fa20d6d76340c5fac1ed66c80273f05b95a

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
   * ====
   *
   * [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://diligence.consensys.net/posts/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.5.11/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);
    }
  }
}

File 21 of 27 : IERC1363.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (interfaces/IERC1363.sol)

pragma solidity ^0.8.20;

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

/**
 * @title IERC1363
 * @dev Interface of the ERC-1363 standard as defined in the https://eips.ethereum.org/EIPS/eip-1363[ERC-1363].
 *
 * Defines an extension interface for ERC-20 tokens that supports executing code on a recipient contract
 * after `transfer` or `transferFrom`, or code on a spender contract after `approve`, in a single transaction.
 */
interface IERC1363 is IERC20, IERC165 {
    /*
     * Note: the ERC-165 identifier for this interface is 0xb0202a11.
     * 0xb0202a11 ===
     *   bytes4(keccak256('transferAndCall(address,uint256)')) ^
     *   bytes4(keccak256('transferAndCall(address,uint256,bytes)')) ^
     *   bytes4(keccak256('transferFromAndCall(address,address,uint256)')) ^
     *   bytes4(keccak256('transferFromAndCall(address,address,uint256,bytes)')) ^
     *   bytes4(keccak256('approveAndCall(address,uint256)')) ^
     *   bytes4(keccak256('approveAndCall(address,uint256,bytes)'))
     */

    /**
     * @dev Moves a `value` amount of tokens from the caller's account to `to`
     * and then calls {IERC1363Receiver-onTransferReceived} on `to`.
     * @param to The address which you want to transfer to.
     * @param value The amount of tokens to be transferred.
     * @return A boolean value indicating whether the operation succeeded unless throwing.
     */
    function transferAndCall(address to, uint256 value) external returns (bool);

    /**
     * @dev Moves a `value` amount of tokens from the caller's account to `to`
     * and then calls {IERC1363Receiver-onTransferReceived} on `to`.
     * @param to The address which you want to transfer to.
     * @param value The amount of tokens to be transferred.
     * @param data Additional data with no specified format, sent in call to `to`.
     * @return A boolean value indicating whether the operation succeeded unless throwing.
     */
    function transferAndCall(address to, uint256 value, bytes calldata data) external returns (bool);

    /**
     * @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism
     * and then calls {IERC1363Receiver-onTransferReceived} on `to`.
     * @param from The address which you want to send tokens from.
     * @param to The address which you want to transfer to.
     * @param value The amount of tokens to be transferred.
     * @return A boolean value indicating whether the operation succeeded unless throwing.
     */
    function transferFromAndCall(address from, address to, uint256 value) external returns (bool);

    /**
     * @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism
     * and then calls {IERC1363Receiver-onTransferReceived} on `to`.
     * @param from The address which you want to send tokens from.
     * @param to The address which you want to transfer to.
     * @param value The amount of tokens to be transferred.
     * @param data Additional data with no specified format, sent in call to `to`.
     * @return A boolean value indicating whether the operation succeeded unless throwing.
     */
    function transferFromAndCall(address from, address to, uint256 value, bytes calldata data) external returns (bool);

    /**
     * @dev Sets a `value` amount of tokens as the allowance of `spender` over the
     * caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.
     * @param spender The address which will spend the funds.
     * @param value The amount of tokens to be spent.
     * @return A boolean value indicating whether the operation succeeded unless throwing.
     */
    function approveAndCall(address spender, uint256 value) external returns (bool);

    /**
     * @dev Sets a `value` amount of tokens as the allowance of `spender` over the
     * caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.
     * @param spender The address which will spend the funds.
     * @param value The amount of tokens to be spent.
     * @param data Additional data with no specified format, sent in call to `spender`.
     * @return A boolean value indicating whether the operation succeeded unless throwing.
     */
    function approveAndCall(address spender, uint256 value, bytes calldata data) external returns (bool);
}

File 22 of 27 : Address.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/Address.sol)

pragma solidity ^0.8.20;

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

/**
 * @dev Collection of functions related to the address type
 */
library Address {
    /**
     * @dev There's no code at `target` (it is not a contract).
     */
    error AddressEmptyCode(address target);

    /**
     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
     * `recipient`, forwarding all available gas and reverting on errors.
     *
     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
     * of certain opcodes, possibly making contracts go over the 2300 gas limit
     * imposed by `transfer`, making them unable to receive funds via
     * `transfer`. {sendValue} removes this limitation.
     *
     * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].
     *
     * IMPORTANT: because control is transferred to `recipient`, care must be
     * taken to not create reentrancy vulnerabilities. Consider using
     * {ReentrancyGuard} or the
     * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
     */
    function sendValue(address payable recipient, uint256 amount) internal {
        if (address(this).balance < amount) {
            revert Errors.InsufficientBalance(address(this).balance, amount);
        }

        (bool success, ) = recipient.call{value: amount}("");
        if (!success) {
            revert Errors.FailedCall();
        }
    }

    /**
     * @dev Performs a Solidity function call using a low level `call`. A
     * plain `call` is an unsafe replacement for a function call: use this
     * function instead.
     *
     * If `target` reverts with a revert reason or custom error, it is bubbled
     * up by this function (like regular Solidity function calls). However, if
     * the call reverted with no returned reason, this function reverts with a
     * {Errors.FailedCall} error.
     *
     * Returns the raw returned data. To convert to the expected return value,
     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
     *
     * Requirements:
     *
     * - `target` must be a contract.
     * - calling `target` with `data` must not revert.
     */
    function functionCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionCallWithValue(target, data, 0);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but also transferring `value` wei to `target`.
     *
     * Requirements:
     *
     * - the calling contract must have an ETH balance of at least `value`.
     * - the called Solidity function must be `payable`.
     */
    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
        if (address(this).balance < value) {
            revert Errors.InsufficientBalance(address(this).balance, value);
        }
        (bool success, bytes memory returndata) = target.call{value: value}(data);
        return verifyCallResultFromTarget(target, success, returndata);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a static call.
     */
    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
        (bool success, bytes memory returndata) = target.staticcall(data);
        return verifyCallResultFromTarget(target, success, returndata);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a delegate call.
     */
    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
        (bool success, bytes memory returndata) = target.delegatecall(data);
        return verifyCallResultFromTarget(target, success, returndata);
    }

    /**
     * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target
     * was not a contract or bubbling up the revert reason (falling back to {Errors.FailedCall}) in case
     * of an unsuccessful call.
     */
    function verifyCallResultFromTarget(
        address target,
        bool success,
        bytes memory returndata
    ) internal view returns (bytes memory) {
        if (!success) {
            _revert(returndata);
        } else {
            // only check if target is a contract if the call was successful and the return data is empty
            // otherwise we already know that it was a contract
            if (returndata.length == 0 && target.code.length == 0) {
                revert AddressEmptyCode(target);
            }
            return returndata;
        }
    }

    /**
     * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the
     * revert reason or with a default {Errors.FailedCall} error.
     */
    function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {
        if (!success) {
            _revert(returndata);
        } else {
            return returndata;
        }
    }

    /**
     * @dev Reverts with returndata if present. Otherwise reverts with {Errors.FailedCall}.
     */
    function _revert(bytes memory returndata) private pure {
        // Look for revert reason and bubble it up if present
        if (returndata.length > 0) {
            // The easiest way to bubble the revert reason is using memory via assembly
            assembly ("memory-safe") {
                let returndata_size := mload(returndata)
                revert(add(32, returndata), returndata_size)
            }
        } else {
            revert Errors.FailedCall();
        }
    }
}

File 23 of 27 : Context.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)

pragma solidity ^0.8.20;

/**
 * @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 Context {
    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;
    }
}

File 24 of 27 : IERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC20.sol)

pragma solidity ^0.8.20;

import {IERC20} from "../token/ERC20/IERC20.sol";

File 25 of 27 : IERC165.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC165.sol)

pragma solidity ^0.8.20;

import {IERC165} from "../utils/introspection/IERC165.sol";

File 26 of 27 : Errors.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/Errors.sol)

pragma solidity ^0.8.20;

/**
 * @dev Collection of common custom errors used in multiple contracts
 *
 * IMPORTANT: Backwards compatibility is not guaranteed in future versions of the library.
 * It is recommended to avoid relying on the error API for critical functionality.
 *
 * _Available since v5.1._
 */
library Errors {
    /**
     * @dev The ETH balance of the account is not enough to perform the operation.
     */
    error InsufficientBalance(uint256 balance, uint256 needed);

    /**
     * @dev A call to an address target failed. The target may have reverted.
     */
    error FailedCall();

    /**
     * @dev The deployment failed.
     */
    error FailedDeployment();

    /**
     * @dev A necessary precompile is missing.
     */
    error MissingPrecompile(address);
}

File 27 of 27 : IERC165.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol)

pragma solidity ^0.8.20;

/**
 * @dev Interface of the ERC-165 standard, as defined in the
 * https://eips.ethereum.org/EIPS/eip-165[ERC].
 *
 * Implementers can declare support of contract interfaces, which can then be
 * queried by others ({ERC165Checker}).
 *
 * For an implementation, see {ERC165}.
 */
interface IERC165 {
    /**
     * @dev Returns true if this contract implements the interface defined by
     * `interfaceId`. See the corresponding
     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]
     * to learn more about how these ids are created.
     *
     * This function call must use less than 30 000 gas.
     */
    function supportsInterface(bytes4 interfaceId) external view returns (bool);
}

Settings
{
  "remappings": [
    "aave-delivery-infrastructure/=lib/adi-deploy/lib/aave-delivery-infrastructure/src/",
    "solidity-utils/=lib/adi-deploy/lib/aave-delivery-infrastructure/lib/solidity-utils/src/",
    "forge-std/=lib/adi-deploy/lib/aave-helpers/lib/forge-std/src/",
    "openzeppelin-contracts/=lib/adi-deploy/lib/aave-delivery-infrastructure/lib/solidity-utils/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/",
    "aave-helpers/=lib/adi-deploy/lib/aave-helpers/src/",
    "aave-address-book/=lib/adi-deploy/lib/aave-helpers/lib/aave-address-book/src/",
    "aave-v3-origin/=lib/adi-deploy/lib/aave-helpers/lib/aave-address-book/lib/aave-v3-origin/src/",
    "adi-deploy/=lib/adi-deploy/",
    "@openzeppelin/=lib/adi-deploy/lib/aave-delivery-infrastructure/lib/openzeppelin-contracts/",
    "@openzeppelin/contracts-upgradeable/=lib/adi-deploy/lib/aave-delivery-infrastructure/lib/solidity-utils/lib/openzeppelin-contracts-upgradeable/contracts/",
    "@openzeppelin/contracts/=lib/adi-deploy/lib/aave-delivery-infrastructure/lib/solidity-utils/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/",
    "aave-v3-origin-tests/=lib/adi-deploy/lib/aave-helpers/lib/aave-address-book/lib/aave-v3-origin/tests/",
    "adi-scripts/=lib/adi-deploy/lib/aave-delivery-infrastructure/scripts/",
    "adi-tests/=lib/adi-deploy/lib/aave-delivery-infrastructure/tests/",
    "adi/=lib/adi-deploy/lib/aave-delivery-infrastructure/src/contracts/",
    "ds-test/=lib/adi-deploy/lib/aave-delivery-infrastructure/lib/solidity-utils/lib/forge-std/lib/ds-test/src/",
    "erc4626-tests/=lib/adi-deploy/lib/aave-delivery-infrastructure/lib/openzeppelin-contracts/lib/erc4626-tests/",
    "halmos-cheatcodes/=lib/adi-deploy/lib/aave-delivery-infrastructure/lib/solidity-utils/lib/openzeppelin-contracts-upgradeable/lib/halmos-cheatcodes/src/",
    "hyperlane-monorepo/=lib/adi-deploy/lib/aave-delivery-infrastructure/lib/hyperlane-monorepo/solidity/contracts/",
    "openzeppelin-contracts-upgradeable/=lib/adi-deploy/lib/aave-delivery-infrastructure/lib/solidity-utils/lib/openzeppelin-contracts-upgradeable/",
    "openzeppelin/=lib/adi-deploy/lib/aave-delivery-infrastructure/lib/openzeppelin-contracts/contracts/"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "metadata": {
    "useLiteralContent": false,
    "bytecodeHash": "none",
    "appendCBOR": true
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "evmVersion": "shanghai",
  "viaIR": false,
  "libraries": {}
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"crossChainController","type":"address"},{"internalType":"address","name":"messageOriginator","type":"address"},{"internalType":"uint256","name":"originChainId","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"EthTransferFailed","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OnlyGuardianInvalidCaller","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OnlyGuardianOrOwnerInvalidCaller","type":"error"},{"inputs":[],"name":"OnlyRescueGuardian","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ERC20Rescued","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"enum PayloadsControllerUtils.AccessControl","name":"accessLevel","type":"uint8"},{"indexed":true,"internalType":"address","name":"executor","type":"address"},{"indexed":false,"internalType":"uint40","name":"delay","type":"uint40"}],"name":"ExecutorSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldGuardian","type":"address"},{"indexed":false,"internalType":"address","name":"newGuardian","type":"address"}],"name":"GuardianUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"NativeTokensRescued","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint40","name":"payloadId","type":"uint40"}],"name":"PayloadCancelled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint40","name":"payloadId","type":"uint40"},{"indexed":true,"internalType":"address","name":"creator","type":"address"},{"components":[{"internalType":"address","name":"target","type":"address"},{"internalType":"bool","name":"withDelegateCall","type":"bool"},{"internalType":"enum PayloadsControllerUtils.AccessControl","name":"accessLevel","type":"uint8"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"string","name":"signature","type":"string"},{"internalType":"bytes","name":"callData","type":"bytes"}],"indexed":false,"internalType":"struct IPayloadsControllerCore.ExecutionAction[]","name":"actions","type":"tuple[]"},{"indexed":true,"internalType":"enum PayloadsControllerUtils.AccessControl","name":"maximumAccessLevelRequired","type":"uint8"}],"name":"PayloadCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint40","name":"payloadId","type":"uint40"}],"name":"PayloadExecuted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"originSender","type":"address"},{"indexed":true,"internalType":"uint256","name":"originChainId","type":"uint256"},{"indexed":true,"internalType":"bool","name":"delivered","type":"bool"},{"indexed":false,"internalType":"bytes","name":"message","type":"bytes"},{"indexed":false,"internalType":"bytes","name":"reason","type":"bytes"}],"name":"PayloadExecutionMessageReceived","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint40","name":"payloadId","type":"uint40"}],"name":"PayloadQueued","type":"event"},{"inputs":[],"name":"CROSS_CHAIN_CONTROLLER","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"EXPIRATION_DELAY","outputs":[{"internalType":"uint40","name":"","type":"uint40"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"GRACE_PERIOD","outputs":[{"internalType":"uint40","name":"","type":"uint40"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"MAX_EXECUTION_DELAY","outputs":[{"internalType":"uint40","name":"","type":"uint40"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MESSAGE_ORIGINATOR","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MIN_EXECUTION_DELAY","outputs":[{"internalType":"uint40","name":"","type":"uint40"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ORIGIN_CHAIN_ID","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint40","name":"payloadId","type":"uint40"}],"name":"cancelPayload","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"target","type":"address"},{"internalType":"bool","name":"withDelegateCall","type":"bool"},{"internalType":"enum PayloadsControllerUtils.AccessControl","name":"accessLevel","type":"uint8"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"string","name":"signature","type":"string"},{"internalType":"bytes","name":"callData","type":"bytes"}],"internalType":"struct IPayloadsControllerCore.ExecutionAction[]","name":"actions","type":"tuple[]"}],"name":"createPayload","outputs":[{"internalType":"uint40","name":"","type":"uint40"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"message","type":"bytes"}],"name":"decodeMessage","outputs":[{"internalType":"uint40","name":"","type":"uint40"},{"internalType":"enum PayloadsControllerUtils.AccessControl","name":"","type":"uint8"},{"internalType":"uint40","name":"","type":"uint40"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"emergencyEtherTransfer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"erc20Token","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"emergencyTokenTransfer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint40","name":"payloadId","type":"uint40"}],"name":"executePayload","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"enum PayloadsControllerUtils.AccessControl","name":"accessControl","type":"uint8"}],"name":"getExecutorSettingsByAccessControl","outputs":[{"components":[{"internalType":"address","name":"executor","type":"address"},{"internalType":"uint40","name":"delay","type":"uint40"}],"internalType":"struct IPayloadsControllerCore.ExecutorConfig","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint40","name":"payloadId","type":"uint40"}],"name":"getPayloadById","outputs":[{"components":[{"internalType":"address","name":"creator","type":"address"},{"internalType":"enum PayloadsControllerUtils.AccessControl","name":"maximumAccessLevelRequired","type":"uint8"},{"internalType":"enum IPayloadsControllerCore.PayloadState","name":"state","type":"uint8"},{"internalType":"uint40","name":"createdAt","type":"uint40"},{"internalType":"uint40","name":"queuedAt","type":"uint40"},{"internalType":"uint40","name":"executedAt","type":"uint40"},{"internalType":"uint40","name":"cancelledAt","type":"uint40"},{"internalType":"uint40","name":"expirationTime","type":"uint40"},{"internalType":"uint40","name":"delay","type":"uint40"},{"internalType":"uint40","name":"gracePeriod","type":"uint40"},{"components":[{"internalType":"address","name":"target","type":"address"},{"internalType":"bool","name":"withDelegateCall","type":"bool"},{"internalType":"enum PayloadsControllerUtils.AccessControl","name":"accessLevel","type":"uint8"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"string","name":"signature","type":"string"},{"internalType":"bytes","name":"callData","type":"bytes"}],"internalType":"struct IPayloadsControllerCore.ExecutionAction[]","name":"actions","type":"tuple[]"}],"internalType":"struct IPayloadsControllerCore.Payload","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint40","name":"payloadId","type":"uint40"}],"name":"getPayloadState","outputs":[{"internalType":"enum IPayloadsControllerCore.PayloadState","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPayloadsCount","outputs":[{"internalType":"uint40","name":"","type":"uint40"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"guardian","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"guardian","type":"address"},{"components":[{"internalType":"enum PayloadsControllerUtils.AccessControl","name":"accessLevel","type":"uint8"},{"components":[{"internalType":"address","name":"executor","type":"address"},{"internalType":"uint40","name":"delay","type":"uint40"}],"internalType":"struct IPayloadsControllerCore.ExecutorConfig","name":"executorConfig","type":"tuple"}],"internalType":"struct IPayloadsControllerCore.UpdateExecutorInput[]","name":"executors","type":"tuple[]"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"erc20Token","type":"address"}],"name":"maxRescue","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"originSender","type":"address"},{"internalType":"uint256","name":"originChainId","type":"uint256"},{"internalType":"bytes","name":"message","type":"bytes"}],"name":"receiveCrossChainMessage","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"enum PayloadsControllerUtils.AccessControl","name":"accessLevel","type":"uint8"},{"components":[{"internalType":"address","name":"executor","type":"address"},{"internalType":"uint40","name":"delay","type":"uint40"}],"internalType":"struct IPayloadsControllerCore.ExecutorConfig","name":"executorConfig","type":"tuple"}],"internalType":"struct IPayloadsControllerCore.UpdateExecutorInput[]","name":"executors","type":"tuple[]"}],"name":"updateExecutors","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newGuardian","type":"address"}],"name":"updateGuardian","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"whoCanRescue","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]

60e060405234801562000010575f80fd5b5060405162003bff38038062003bff8339810160408190526200003391620002f2565b33806200005a57604051631e4fbdf760e01b81525f60048201526024015b60405180910390fd5b62000065816200015a565b506200007133620001a9565b6200007b6200020a565b604080518082019091526002815261068760f31b60208201526001600160a01b038416620000be5760405162461bcd60e51b815260040162000051919062000330565b50604080518082019091526002815261343960f01b60208201526001600160a01b038316620001025760405162461bcd60e51b815260040162000051919062000330565b50604080518082019091526002815261035360f41b6020820152816200013d5760405162461bcd60e51b815260040162000051919062000330565b506001600160a01b0392831660a052911660805260c0526200037e565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b600180546001600160a01b038381166001600160a01b031983168117909355604080519190921680825260208201939093527f064d28d3d3071c5cbc271a261c10c2f0f0d9e319390397101aa0eb23c6bad909910160405180910390a15050565b600154600160a81b900460ff1615620002765760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840162000051565b60015460ff600160a01b90910481161015620002d4576001805460ff60a01b191660ff60a01b17905560405160ff81527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b80516001600160a01b0381168114620002ed575f80fd5b919050565b5f805f6060848603121562000305575f80fd5b6200031084620002d6565b92506200032060208501620002d6565b9150604084015190509250925092565b5f602080835283518060208501525f5b818110156200035e5785810183015185820160400152820162000340565b505f604082860101526040601f19601f8301168501019250505092915050565b60805160a05160c051613841620003be5f395f81816101b401526105c501525f81816103fa015261055e01525f818161048a015261058801526138415ff3fe608060405260043610610198575f3560e01c8063a4757b0f116100e7578063d740871511610087578063eed88b8d11610062578063eed88b8d146104ac578063f2fde38b146104cb578063f80281fb146104ea578063fc52539514610534575f80fd5b8063d74087151461043b578063e87338941461045a578063eddd795514610479575f80fd5b8063bcbde212116100c2578063bcbde212146103bf578063c1a287e2146103d4578063c4956366146103e9578063d2c4487a1461041c575f80fd5b8063a4757b0f1461031b578063aa30b6ea14610388578063bc03d280146103aa575f80fd5b8063634d45b2116101525780638da5cb5b1161012d5780638da5cb5b1461031b578063910ae3d91461033757806392cdb83414610356578063a3d5b25514610369575f80fd5b8063634d45b2146102ad578063715018a6146102db57806374730f0d146102ef575f80fd5b80630dd85b00146101a357806315034cba146101e95780632c1b77071461020a578063452a932014610231578063568690f41461026257806358007a4e14610281575f80fd5b3661019f57005b5f80fd5b3480156101ae575f80fd5b506101d67f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020015b60405180910390f35b3480156101f4575f80fd5b50610208610203366004612c56565b610553565b005b348015610215575f80fd5b50622e24805b60405164ffffffffff90911681526020016101e0565b34801561023c575f80fd5b506001546001600160a01b03165b6040516001600160a01b0390911681526020016101e0565b34801561026d575f80fd5b5061020861027c366004612cf1565b610765565b34801561028c575f80fd5b506102a061029b366004612d63565b61092d565b6040516101e09190612ec8565b3480156102b8575f80fd5b506102cc6102c7366004612fc5565b610cb9565b6040516101e093929190612ff6565b3480156102e6575f80fd5b50610208610cdd565b3480156102fa575f80fd5b5061030e610309366004612d63565b610cf0565b6040516101e09190613024565b348015610326575f80fd5b505f546001600160a01b031661024a565b348015610342575f80fd5b50610208610351366004612d63565b610feb565b610208610364366004612d63565b610fff565b348015610374575f80fd5b50610208610383366004613032565b61152e565b348015610393575f80fd5b50600154600160b01b900464ffffffffff1661021b565b3480156103b5575f80fd5b50620d2f0061021b565b3480156103ca575f80fd5b506201518061021b565b3480156103df575f80fd5b5062093a8061021b565b3480156103f4575f80fd5b5061024a7f000000000000000000000000000000000000000000000000000000000000000081565b348015610427575f80fd5b50610208610436366004613070565b611563565b348015610446575f80fd5b506101d66104553660046130ae565b6115bf565b348015610465575f80fd5b5061021b6104743660046130c9565b611627565b348015610484575f80fd5b5061024a7f000000000000000000000000000000000000000000000000000000000000000081565b3480156104b7575f80fd5b506102086104c6366004613137565b611af4565b3480156104d6575f80fd5b506102086104e53660046130ae565b611b28565b3480156104f5575f80fd5b5061050961050436600461316d565b611b62565b6040805182516001600160a01b0316815260209283015164ffffffffff1692810192909252016101e0565b34801561053f575f80fd5b5061020861054e3660046130ae565b611bdd565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161480156105bc57507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b0316145b80156105e757507f000000000000000000000000000000000000000000000000000000000000000082145b604051806040016040528060028152602001610c4d60f21b815250906106295760405162461bcd60e51b81526004016106209190613188565b60405180910390fd5b506040516331a6a2d960e11b8152309063634d45b29061064d908490600401613188565b606060405180830381865afa925050508015610686575060408051601f3d908101601f191682019092526106839181019061319a565b60015b610706573d8080156106b3576040519150601f19603f3d011682016040523d82523d5f602084013e6106b8565b606091505b505f151583856001600160a01b03167fc25b8a395435c70772056c57a733c070ec65d7aa03edf1ab08ccd58c51b9082585856040516106f89291906131e4565b60405180910390a450505050565b610711838383611bee565b60606001151586886001600160a01b03167fc25b8a395435c70772056c57a733c070ec65d7aa03edf1ab08ccd58c51b9082588856040516107539291906131e4565b60405180910390a4505050505b505050565b600154600160a81b900460ff161580801561078b575060018054600160a01b900460ff16105b806107ab5750303b1580156107ab575060018054600160a01b900460ff16145b61080e5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610620565b6001805460ff60a01b1916600160a01b179055801561083b576001805460ff60a81b1916600160a81b1790555b604080518082019091526002815261033360f41b6020820152826108725760405162461bcd60e51b81526004016106209190613188565b506108cd8383808060200260200160405190810160405280939291908181526020015f905b828210156108c3576108b460608302860136819003810190613211565b81526020019060010190610897565b5050505050612049565b6108d68461231d565b6108df8561237e565b8015610926576001805460ff60a81b191681556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050565b61098b6040805161016081019091525f808252602082019081526020015f81525f602082018190526040820181905260608083018290526080830182905260a0830182905260c0830182905260e08301919091526101009091015290565b64ffffffffff82165f9081526003602090815260408083208151610160810190925280546001600160a01b03811683529192909190830190600160a01b900460ff1660028111156109de576109de612d85565b60028111156109ef576109ef612d85565b81528154602090910190600160a81b900460ff166005811115610a1457610a14612d85565b6005811115610a2557610a25612d85565b8152815464ffffffffff600160b01b82048116602080850191909152600160d81b909204811660408085019190915260018501548083166060860152600160281b810483166080860152600160501b8104831660a0860152600160781b8104831660c0860152600160a01b900490911660e08401526002840180548251818502810185019093528083526101009094019391929091905f9084015b82821015610c74575f8481526020908190206040805160c0810182526004860290920180546001600160a01b038116845260ff600160a01b820481161515958501959095529293909291840191600160a81b9004166002811115610b2657610b26612d85565b6002811115610b3757610b37612d85565b815260200160018201548152602001600282018054610b5590613286565b80601f0160208091040260200160405190810160405280929190818152602001828054610b8190613286565b8015610bcc5780601f10610ba357610100808354040283529160200191610bcc565b820191905f5260205f20905b815481529060010190602001808311610baf57829003601f168201915b50505050508152602001600382018054610be590613286565b80601f0160208091040260200160405190810160405280929190818152602001828054610c1190613286565b8015610c5c5780601f10610c3357610100808354040283529160200191610c5c565b820191905f5260205f20905b815481529060010190602001808311610c3f57829003601f168201915b50505050508152505081526020019060010190610ac0565b50505050815250509050610c87816123cd565b81604001906005811115610c9d57610c9d612d85565b90816005811115610cb057610cb0612d85565b90525092915050565b5f805f83806020019051810190610cd0919061319a565b9250925092509193909250565b610ce561249c565b610cee5f61237e565b565b64ffffffffff81165f9081526003602090815260408083208151610160810190925280546001600160a01b0381168352610fe593830190600160a01b900460ff166002811115610d4257610d42612d85565b6002811115610d5357610d53612d85565b81528154602090910190600160a81b900460ff166005811115610d7857610d78612d85565b6005811115610d8957610d89612d85565b8152815464ffffffffff600160b01b82048116602080850191909152600160d81b909204811660408085019190915260018501548083166060860152600160281b810483166080860152600160501b8104831660a0860152600160781b8104831660c0860152600160a01b900490911660e08401526002840180548251818502810185019093528083526101009094019391929091905f9084015b82821015610fd8575f8481526020908190206040805160c0810182526004860290920180546001600160a01b038116845260ff600160a01b820481161515958501959095529293909291840191600160a81b9004166002811115610e8a57610e8a612d85565b6002811115610e9b57610e9b612d85565b815260200160018201548152602001600282018054610eb990613286565b80601f0160208091040260200160405190810160405280929190818152602001828054610ee590613286565b8015610f305780601f10610f0757610100808354040283529160200191610f30565b820191905f5260205f20905b815481529060010190602001808311610f1357829003601f168201915b50505050508152602001600382018054610f4990613286565b80601f0160208091040260200160405190810160405280929190818152602001828054610f7590613286565b8015610fc05780601f10610f9757610100808354040283529160200191610fc0565b820191905f5260205f20905b815481529060010190602001808311610fa357829003601f168201915b50505050508152505081526020019060010190610e24565b50505050815250506123cd565b92915050565b610ff36124c8565b610ffc81612515565b50565b64ffffffffff81165f908152600360205260409020600260408051610160810190915282546001600160a01b03811682526112ed919084906020830190600160a01b900460ff16600281111561105757611057612d85565b600281111561106857611068612d85565b81528154602090910190600160a81b900460ff16600581111561108d5761108d612d85565b600581111561109e5761109e612d85565b8152815464ffffffffff600160b01b82048116602080850191909152600160d81b909204811660408085019190915260018501548083166060860152600160281b810483166080860152600160501b8104831660a0860152600160781b8104831660c0860152600160a01b900490911660e08401526002840180548251818502810185019093528083526101009094019391929091905f9084015b82821015610fd8575f8481526020908190206040805160c0810182526004860290920180546001600160a01b038116845260ff600160a01b820481161515958501959095529293909291840191600160a81b900416600281111561119f5761119f612d85565b60028111156111b0576111b0612d85565b8152602001600182015481526020016002820180546111ce90613286565b80601f01602080910402602001604051908101604052809291908181526020018280546111fa90613286565b80156112455780601f1061121c57610100808354040283529160200191611245565b820191905f5260205f20905b81548152906001019060200180831161122857829003601f168201915b5050505050815260200160038201805461125e90613286565b80601f016020809104026020016040519081016040528092919081815260200182805461128a90613286565b80156112d55780601f106112ac576101008083540402835291602001916112d5565b820191905f5260205f20905b8154815290600101906020018083116112b857829003601f168201915b50505050508152505081526020019060010190611139565b60058111156112fe576112fe612d85565b1460405180604001604052806002815260200161333360f01b815250906113385760405162461bcd60e51b81526004016106209190613188565b50600181015481545f916113659164ffffffffff600160781b909204821691600160d81b909104166132d2565b64ffffffffff169050804211604051806040016040528060028152602001610ccd60f21b815250906113aa5760405162461bcd60e51b81526004016106209190613188565b50815460ff60a81b1916600360a81b17825560018201805464ffffffffff19164264ffffffffff161790555f5b60028301548110156114ed575f8360020182815481106113f9576113f96132f7565b5f918252602082206004909102018054909250600290829060ff600160a81b909104168281111561142c5761142c612d85565b600281111561143d5761143d612d85565b8152602081019190915260409081015f205460018401548454925163025d36a960e01b81526001600160a01b039283169450849363025d36a99361149f9290821691849160028a019160038b0191600160a01b90910460ff1690600401613384565b5f6040518083038185885af11580156114ba573d5f803e3d5ffd5b50505050506040513d5f823e601f3d908101601f191682016040526114e291908101906133d1565b5050506001016113d7565b5060405164ffffffffff841681527fda6084bb0aa902a7f6da10ba185d4aa129414651c90772417eff02a52112af2a906020015b60405180910390a1505050565b5f546001600160a01b0316331461155857604051633a02626960e01b815260040160405180910390fd5b6107608383836128e0565b61156b61249c565b6115bb8282808060200260200160405190810160405280939291908181526020015f905b828210156108c3576115ac60608302860136819003810190613211565b8152602001906001019061158f565b5050565b6040516370a0823160e01b81523060048201525f906001600160a01b038316906370a0823190602401602060405180830381865afa158015611603573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610fe59190613439565b604080518082019091526002815261333160f01b60208201525f90826116605760405162461bcd60e51b81526004016106209190613188565b50600180545f91600160b01b90910464ffffffffff1690601661168283613450565b82546101009290920a64ffffffffff8181021990931691831602179091558181165f9081526003602052604090208054600161ff0160a01b0319163360ff60a81b191617600160a81b1764ffffffffff60b01b1916600160b01b4293841602178155919250906116f5622e2480836132d2565b60018201805461127560a71b6effffffffff0000000000ffffffffff60501b1990911664ffffffffff93909316600160501b0264ffffffffff60a01b1916929092179190911790555f805b868110156119dd575f88888381811061175b5761175b6132f7565b905060200281019061176d9190613473565b61177b9060208101906130ae565b6001600160a01b0316141560405180604001604052806002815260200161353160f01b815250906117bf5760405162461bcd60e51b81526004016106209190613188565b505f8888838181106117d3576117d36132f7565b90506020028101906117e59190613473565b6117f690606081019060400161316d565b600281111561180757611807612d85565b11604051806040016040528060028152602001611a9960f11b815250906118415760405162461bcd60e51b81526004016106209190613188565b505f6002818a8a85818110611858576118586132f7565b905060200281019061186a9190613473565b61187b90606081019060400161316d565b600281111561188c5761188c612d85565b600281111561189d5761189d612d85565b815260208082019290925260409081015f205481518083019092526002825261199960f11b92820192909252916001600160a01b03909116036118f35760405162461bcd60e51b81526004016106209190613188565b508260020188888381811061190a5761190a6132f7565b905060200281019061191c9190613473565b81546001810183555f928352602090922090916004020161193d828261360a565b505081600281111561195157611951612d85565b888883818110611963576119636132f7565b90506020028101906119759190613473565b61198690606081019060400161316d565b600281111561199757611997612d85565b11156119d5578787828181106119af576119af6132f7565b90506020028101906119c19190613473565b6119d290606081019060400161316d565b91505b600101611740565b5081548190839060ff60a01b1916600160a01b836002811115611a0257611a02612d85565b02179055505f60025f836002811115611a1d57611a1d612d85565b6002811115611a2e57611a2e612d85565b815260208082019290925260409081015f208151808301909252546001600160a01b0381168252600160a01b900464ffffffffff1691810182905260018501805464ffffffffff60781b1916600160781b909302929092179091559050816002811115611a9d57611a9d612d85565b336001600160a01b03168664ffffffffff167f1e4588da4731f84a598f061ee45829a6450aa00aa28962657b6835641afbbac58b8b604051611ae0929190613724565b60405180910390a450929695505050505050565b5f546001600160a01b03163314611b1e57604051633a02626960e01b815260040160405180910390fd5b6115bb8282612960565b611b3061249c565b6001600160a01b038116611b5957604051631e4fbdf760e01b81525f6004820152602401610620565b610ffc8161237e565b604080518082019091525f808252602082015260025f836002811115611b8a57611b8a612d85565b6002811115611b9b57611b9b612d85565b815260208082019290925260409081015f208151808301909252546001600160a01b0381168252600160a01b900464ffffffffff169181019190915292915050565b611be5612a2f565b610ffc8161231d565b64ffffffffff83165f908152600360205260409020600160408051610160810190915282546001600160a01b0381168252611edc919084906020830190600160a01b900460ff166002811115611c4657611c46612d85565b6002811115611c5757611c57612d85565b81528154602090910190600160a81b900460ff166005811115611c7c57611c7c612d85565b6005811115611c8d57611c8d612d85565b8152815464ffffffffff600160b01b82048116602080850191909152600160d81b909204811660408085019190915260018501548083166060860152600160281b810483166080860152600160501b8104831660a0860152600160781b8104831660c0860152600160a01b900490911660e08401526002840180548251818502810185019093528083526101009094019391929091905f9084015b82821015610fd8575f8481526020908190206040805160c0810182526004860290920180546001600160a01b038116845260ff600160a01b820481161515958501959095529293909291840191600160a81b9004166002811115611d8e57611d8e612d85565b6002811115611d9f57611d9f612d85565b815260200160018201548152602001600282018054611dbd90613286565b80601f0160208091040260200160405190810160405280929190818152602001828054611de990613286565b8015611e345780601f10611e0b57610100808354040283529160200191611e34565b820191905f5260205f20905b815481529060010190602001808311611e1757829003601f168201915b50505050508152602001600382018054611e4d90613286565b80601f0160208091040260200160405190810160405280929190818152602001828054611e7990613286565b8015611ec45780601f10611e9b57610100808354040283529160200191611ec4565b820191905f5260205f20905b815481529060010190602001808311611ea757829003601f168201915b50505050508152505081526020019060010190611d28565b6005811115611eed57611eed612d85565b1460405180604001604052806002815260200161199b60f11b81525090611f275760405162461bcd60e51b81526004016106209190613188565b508054600160a01b900460ff166002811115611f4557611f45612d85565b836002811115611f5757611f57612d85565b1015604051806040016040528060028152602001611a1b60f11b81525090611f925760405162461bcd60e51b81526004016106209190613188565b508054604080518082019091526002815261343760f01b60208201529064ffffffffff600160b01b909104811690841611611fe05760405162461bcd60e51b81526004016106209190613188565b508054600160a91b64ffffffffff428116600160d81b02600165ffffffffff0160a81b039093169290921717825560405190851681527f1c4585f98a2bf1a1dca30917ba110f1b978343c7cce2c703495e5e47d51644569060200160405180910390a150505050565b5f5b81518110156115bb575f828281518110612067576120676132f7565b602002602001015190505f6001600160a01b031681602001515f01516001600160a01b03161415604051806040016040528060028152602001611a1960f11b815250906120c75760405162461bcd60e51b81526004016106209190613188565b505f815160028111156120dc576120dc612d85565b1160405180604001604052806002815260200161353360f01b815250906121165760405162461bcd60e51b81526004016106209190613188565b506201518064ffffffffff1681602001516020015164ffffffffff16101580156121595750620d2f0064ffffffffff1681602001516020015164ffffffffff1611155b60405180604001604052806002815260200161373760f01b815250906121925760405162461bcd60e51b81526004016106209190613188565b505f6001825160028111156121a9576121a9612d85565b146121b55760016121b8565b60025b6020830151519091506001600160a01b031660025f83828111156121de576121de612d85565b60028111156121ef576121ef612d85565b815260208082019290925260409081015f205481518083019092526002825261343360f01b92820192909252916001600160a01b03909116036122455760405162461bcd60e51b81526004016106209190613188565b50816020015160025f845f0151600281111561226357612263612d85565b600281111561227457612274612d85565b81526020808201929092526040015f20825181549383015164ffffffffff16600160a01b026001600160c81b03199094166001600160a01b039182161793909317905583015151835191169060028111156122d1576122d1612d85565b60208085015181015160405164ffffffffff90911681527fa7c32b123d845f42a44986cab71b2d81819f15f4478f47d9830a762251372c90910160405180910390a3505060010161204b565b600180546001600160a01b038381166001600160a01b031983168117909355604080519190921680825260208201939093527f064d28d3d3071c5cbc271a261c10c2f0f0d9e319390397101aa0eb23c6bad909910160405180910390a15050565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60408101515f90818160058111156123e7576123e7612d85565b14806124055750600381600581111561240257612402612d85565b10155b156124105792915050565b600181600581111561242457612424612d85565b14801561243c57508260e0015164ffffffffff164210155b8061248e5750600281600581111561245657612456612d85565b14801561248e5750826101200151836101000151846080015161247991906132d2565b61248391906132d2565b64ffffffffff164210155b15610fe55750600592915050565b5f546001600160a01b03163314610cee5760405163118cdaa760e01b8152336004820152602401610620565b6001546001600160a01b03163314610cee5760405162461bcd60e51b815260206004820152601060248201526f27a7262cafa12cafa3aaa0a92224a0a760811b6044820152606401610620565b64ffffffffff81165f9081526003602090815260408083208151610160810190925280546001600160a01b038116835290939261280392918591830190600160a01b900460ff16600281111561256d5761256d612d85565b600281111561257e5761257e612d85565b81528154602090910190600160a81b900460ff1660058111156125a3576125a3612d85565b60058111156125b4576125b4612d85565b8152815464ffffffffff600160b01b82048116602080850191909152600160d81b909204811660408085019190915260018501548083166060860152600160281b810483166080860152600160501b8104831660a0860152600160781b8104831660c0860152600160a01b900490911660e08401526002840180548251818502810185019093528083526101009094019391929091905f9084015b82821015610fd8575f8481526020908190206040805160c0810182526004860290920180546001600160a01b038116845260ff600160a01b820481161515958501959095529293909291840191600160a81b90041660028111156126b5576126b5612d85565b60028111156126c6576126c6612d85565b8152602001600182015481526020016002820180546126e490613286565b80601f016020809104026020016040519081016040528092919081815260200182805461271090613286565b801561275b5780601f106127325761010080835404028352916020019161275b565b820191905f5260205f20905b81548152906001019060200180831161273e57829003601f168201915b5050505050815260200160038201805461277490613286565b80601f01602080910402602001604051908101604052809291908181526020018280546127a090613286565b80156127eb5780601f106127c2576101008083540402835291602001916127eb565b820191905f5260205f20905b8154815290600101906020018083116127ce57829003601f168201915b5050505050815250508152602001906001019061264f565b9050600381600581111561281957612819612d85565b1080156128385750600181600581111561283557612835612d85565b10155b60405180604001604052806002815260200161333560f01b815250906128715760405162461bcd60e51b81526004016106209190613188565b50815460ff60a81b1916600160aa1b17825560018201805464ffffffffff428116600160281b0269ffffffffff0000000000199092169190911790915560405190841681527f1f5679387cd5a407876abac64429108734317fc18c0de46eae3cbc0a69a44d5990602001611521565b5f6128ea846115bf565b90508181116128f957806128fb565b815b91506129116001600160a01b0385168484612a9d565b826001600160a01b0316846001600160a01b0316336001600160a01b03167fc7af665d489507e14ae25ac7ab0030fc7f570869610bdd32117ea56b60ae5c61856040516106f891815260200190565b604080515f808252602082019092526001600160a01b0384169083906040516129899190613823565b5f6040518083038185875af1925050503d805f81146129c3576040519150601f19603f3d011682016040523d82523d5f602084013e6129c8565b606091505b50509050806129ea57604051630db2c7f160e31b815260040160405180910390fd5b6040518281526001600160a01b0384169033907fb7c602059992183c7b767c08204223afc99f1895fd175adf9ece23ce9f5bb8b79060200160405180910390a3505050565b5f546001600160a01b0316331480612a5157506001546001600160a01b031633145b610cee5760405162461bcd60e51b815260206004820152601960248201527f4f4e4c595f42595f4f574e45525f4f525f475541524449414e000000000000006044820152606401610620565b604080516001600160a01b03841660248201526044808201849052825180830390910181526064909101909152602080820180516001600160e01b031663a9059cbb60e01b178152825161076093879390925f9283929183919082885af180612b0b576040513d5f823e3d81fd5b50505f513d91508115612b22578060011415612b2f565b6001600160a01b0384163b155b15612b5857604051635274afe760e01b81526001600160a01b0385166004820152602401610620565b50505050565b6001600160a01b0381168114610ffc575f80fd5b634e487b7160e01b5f52604160045260245ffd5b604080519081016001600160401b0381118282101715612ba857612ba8612b72565b60405290565b604051601f8201601f191681016001600160401b0381118282101715612bd657612bd6612b72565b604052919050565b5f6001600160401b03821115612bf657612bf6612b72565b50601f01601f191660200190565b5f82601f830112612c13575f80fd5b8135612c26612c2182612bde565b612bae565b818152846020838601011115612c3a575f80fd5b816020850160208301375f918101602001919091529392505050565b5f805f60608486031215612c68575f80fd5b8335612c7381612b5e565b92506020840135915060408401356001600160401b03811115612c94575f80fd5b612ca086828701612c04565b9150509250925092565b5f8083601f840112612cba575f80fd5b5081356001600160401b03811115612cd0575f80fd5b602083019150836020606083028501011115612cea575f80fd5b9250929050565b5f805f8060608587031215612d04575f80fd5b8435612d0f81612b5e565b93506020850135612d1f81612b5e565b925060408501356001600160401b03811115612d39575f80fd5b612d4587828801612caa565b95989497509550505050565b64ffffffffff81168114610ffc575f80fd5b5f60208284031215612d73575f80fd5b8135612d7e81612d51565b9392505050565b634e487b7160e01b5f52602160045260245ffd5b60038110612da957612da9612d85565b9052565b60068110612da957612da9612d85565b5f5b83811015612dd7578181015183820152602001612dbf565b50505f910152565b5f8151808452612df6816020860160208601612dbd565b601f01601f19169290920160200192915050565b5f82825180855260208086019550808260051b8401018186015f5b84811015612ebb57858303601f19018952815180516001600160a01b031684528481015115158585015260408082015160c09190612e6582880182612d99565b505060608083015181870152506080808301518282880152612e8983880182612ddf565b9250505060a08083015192508582038187015250612ea78183612ddf565b9a86019a9450505090830190600101612e25565b5090979650505050505050565b60208152612ee26020820183516001600160a01b03169052565b5f6020830151612ef56040840182612d99565b506040830151612f086060840182612dad565b50606083015164ffffffffff8116608084015250608083015164ffffffffff811660a08401525060a083015164ffffffffff811660c08401525060c083015164ffffffffff811660e08401525060e0830151610100612f6f8185018364ffffffffff169052565b8401519050610120612f898482018364ffffffffff169052565b8401519050610140612fa38482018364ffffffffff169052565b840151610160848101529050612fbd610180840182612e0a565b949350505050565b5f60208284031215612fd5575f80fd5b81356001600160401b03811115612fea575f80fd5b612fbd84828501612c04565b64ffffffffff848116825260608201906130136020840186612d99565b808416604084015250949350505050565b60208101610fe58284612dad565b5f805f60608486031215613044575f80fd5b833561304f81612b5e565b9250602084013561305f81612b5e565b929592945050506040919091013590565b5f8060208385031215613081575f80fd5b82356001600160401b03811115613096575f80fd5b6130a285828601612caa565b90969095509350505050565b5f602082840312156130be575f80fd5b8135612d7e81612b5e565b5f80602083850312156130da575f80fd5b82356001600160401b03808211156130f0575f80fd5b818501915085601f830112613103575f80fd5b813581811115613111575f80fd5b8660208260051b8501011115613125575f80fd5b60209290920196919550909350505050565b5f8060408385031215613148575f80fd5b823561315381612b5e565b946020939093013593505050565b60038110610ffc575f80fd5b5f6020828403121561317d575f80fd5b8135612d7e81613161565b602081525f612d7e6020830184612ddf565b5f805f606084860312156131ac575f80fd5b83516131b781612d51565b60208501519093506131c881613161565b60408501519092506131d981612d51565b809150509250925092565b604081525f6131f66040830185612ddf565b82810360208401526132088185612ddf565b95945050505050565b5f8183036060811215613222575f80fd5b61322a612b86565b833561323581613161565b81526040601f1983011215613248575f80fd5b613250612b86565b9150602084013561326081612b5e565b8252604084013561327081612d51565b6020838101919091528101919091529392505050565b600181811c9082168061329a57607f821691505b6020821081036132b857634e487b7160e01b5f52602260045260245ffd5b50919050565b634e487b7160e01b5f52601160045260245ffd5b64ffffffffff8181168382160190808211156132f0576132f06132be565b5092915050565b634e487b7160e01b5f52603260045260245ffd5b5f815461331781613286565b808552602060018381168015613334576001811461334e57613379565b60ff1985168884015283151560051b880183019550613379565b865f52825f205f5b858110156133715781548a8201860152908301908401613356565b890184019650505b505050505092915050565b60018060a01b038616815284602082015260a060408201525f6133aa60a083018661330b565b82810360608401526133bc818661330b565b91505082151560808301529695505050505050565b5f602082840312156133e1575f80fd5b81516001600160401b038111156133f6575f80fd5b8201601f81018413613406575f80fd5b8051613414612c2182612bde565b818152856020838501011115613428575f80fd5b613208826020830160208601612dbd565b5f60208284031215613449575f80fd5b5051919050565b5f64ffffffffff808316818103613469576134696132be565b6001019392505050565b5f823560be19833603018112613487575f80fd5b9190910192915050565b8015158114610ffc575f80fd5b600382106134ae576134ae612d85565b805460ff60a81b191660a89290921b60ff60a81b16919091179055565b5f808335601e198436030181126134e0575f80fd5b8301803591506001600160401b038211156134f9575f80fd5b602001915036819003821315612cea575f80fd5b601f82111561076057805f5260205f20601f840160051c810160208510156135325750805b601f840160051c820191505b81811015610926575f815560010161353e565b6001600160401b0383111561356857613568612b72565b61357c836135768354613286565b8361350d565b5f601f8411600181146135ad575f85156135965750838201355b5f19600387901b1c1916600186901b178355610926565b5f83815260208120601f198716915b828110156135dc57868501358255602094850194600190920191016135bc565b50868210156135f8575f1960f88860031b161c19848701351681555b505060018560011b0183555050505050565b813561361581612b5e565b81546001600160a01b031981166001600160a01b03929092169182178355602084013561364181613491565b6001600160a81b03199190911690911790151560a01b60ff60a01b16178155604082013561366e81613161565b613678818361349e565b506060820135600182015561369060808301836134cb565b61369e818360028601613551565b50506136ad60a08301836134cb565b612b58818360038601613551565b5f808335601e198436030181126136d0575f80fd5b83016020810192503590506001600160401b038111156136ee575f80fd5b803603821315612cea575f80fd5b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b60208082528181018390525f906040808401600586901b8501820187855b8881101561381557878303603f190184528135368b900360be19018112613767575f80fd5b8a0160c0813561377681612b5e565b6001600160a01b031685528188013561378e81613491565b151585890152818701356137a181613161565b6137ad88870182612d99565b506060828101359086015260806137c6818401846136bb565b83838901526137d884890182846136fc565b935050505060a06137eb818401846136bb565b9350868303828801526137ff8385836136fc565b978a019796505050928701925050600101613742565b509098975050505050505050565b5f8251613487818460208701612dbd56fea164736f6c6343000816000a00000000000000000000000058e003a3c6f2aeed6a2a6bc77b504566523cb15c0000000000000000000000009aee0b04504cef83a65ac3f0e838d0593bcb2bc70000000000000000000000000000000000000000000000000000000000000001

Deployed Bytecode

0x608060405260043610610198575f3560e01c8063a4757b0f116100e7578063d740871511610087578063eed88b8d11610062578063eed88b8d146104ac578063f2fde38b146104cb578063f80281fb146104ea578063fc52539514610534575f80fd5b8063d74087151461043b578063e87338941461045a578063eddd795514610479575f80fd5b8063bcbde212116100c2578063bcbde212146103bf578063c1a287e2146103d4578063c4956366146103e9578063d2c4487a1461041c575f80fd5b8063a4757b0f1461031b578063aa30b6ea14610388578063bc03d280146103aa575f80fd5b8063634d45b2116101525780638da5cb5b1161012d5780638da5cb5b1461031b578063910ae3d91461033757806392cdb83414610356578063a3d5b25514610369575f80fd5b8063634d45b2146102ad578063715018a6146102db57806374730f0d146102ef575f80fd5b80630dd85b00146101a357806315034cba146101e95780632c1b77071461020a578063452a932014610231578063568690f41461026257806358007a4e14610281575f80fd5b3661019f57005b5f80fd5b3480156101ae575f80fd5b506101d67f000000000000000000000000000000000000000000000000000000000000000181565b6040519081526020015b60405180910390f35b3480156101f4575f80fd5b50610208610203366004612c56565b610553565b005b348015610215575f80fd5b50622e24805b60405164ffffffffff90911681526020016101e0565b34801561023c575f80fd5b506001546001600160a01b03165b6040516001600160a01b0390911681526020016101e0565b34801561026d575f80fd5b5061020861027c366004612cf1565b610765565b34801561028c575f80fd5b506102a061029b366004612d63565b61092d565b6040516101e09190612ec8565b3480156102b8575f80fd5b506102cc6102c7366004612fc5565b610cb9565b6040516101e093929190612ff6565b3480156102e6575f80fd5b50610208610cdd565b3480156102fa575f80fd5b5061030e610309366004612d63565b610cf0565b6040516101e09190613024565b348015610326575f80fd5b505f546001600160a01b031661024a565b348015610342575f80fd5b50610208610351366004612d63565b610feb565b610208610364366004612d63565b610fff565b348015610374575f80fd5b50610208610383366004613032565b61152e565b348015610393575f80fd5b50600154600160b01b900464ffffffffff1661021b565b3480156103b5575f80fd5b50620d2f0061021b565b3480156103ca575f80fd5b506201518061021b565b3480156103df575f80fd5b5062093a8061021b565b3480156103f4575f80fd5b5061024a7f00000000000000000000000058e003a3c6f2aeed6a2a6bc77b504566523cb15c81565b348015610427575f80fd5b50610208610436366004613070565b611563565b348015610446575f80fd5b506101d66104553660046130ae565b6115bf565b348015610465575f80fd5b5061021b6104743660046130c9565b611627565b348015610484575f80fd5b5061024a7f0000000000000000000000009aee0b04504cef83a65ac3f0e838d0593bcb2bc781565b3480156104b7575f80fd5b506102086104c6366004613137565b611af4565b3480156104d6575f80fd5b506102086104e53660046130ae565b611b28565b3480156104f5575f80fd5b5061050961050436600461316d565b611b62565b6040805182516001600160a01b0316815260209283015164ffffffffff1692810192909252016101e0565b34801561053f575f80fd5b5061020861054e3660046130ae565b611bdd565b336001600160a01b037f00000000000000000000000058e003a3c6f2aeed6a2a6bc77b504566523cb15c161480156105bc57507f0000000000000000000000009aee0b04504cef83a65ac3f0e838d0593bcb2bc76001600160a01b0316836001600160a01b0316145b80156105e757507f000000000000000000000000000000000000000000000000000000000000000182145b604051806040016040528060028152602001610c4d60f21b815250906106295760405162461bcd60e51b81526004016106209190613188565b60405180910390fd5b506040516331a6a2d960e11b8152309063634d45b29061064d908490600401613188565b606060405180830381865afa925050508015610686575060408051601f3d908101601f191682019092526106839181019061319a565b60015b610706573d8080156106b3576040519150601f19603f3d011682016040523d82523d5f602084013e6106b8565b606091505b505f151583856001600160a01b03167fc25b8a395435c70772056c57a733c070ec65d7aa03edf1ab08ccd58c51b9082585856040516106f89291906131e4565b60405180910390a450505050565b610711838383611bee565b60606001151586886001600160a01b03167fc25b8a395435c70772056c57a733c070ec65d7aa03edf1ab08ccd58c51b9082588856040516107539291906131e4565b60405180910390a4505050505b505050565b600154600160a81b900460ff161580801561078b575060018054600160a01b900460ff16105b806107ab5750303b1580156107ab575060018054600160a01b900460ff16145b61080e5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610620565b6001805460ff60a01b1916600160a01b179055801561083b576001805460ff60a81b1916600160a81b1790555b604080518082019091526002815261033360f41b6020820152826108725760405162461bcd60e51b81526004016106209190613188565b506108cd8383808060200260200160405190810160405280939291908181526020015f905b828210156108c3576108b460608302860136819003810190613211565b81526020019060010190610897565b5050505050612049565b6108d68461231d565b6108df8561237e565b8015610926576001805460ff60a81b191681556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050565b61098b6040805161016081019091525f808252602082019081526020015f81525f602082018190526040820181905260608083018290526080830182905260a0830182905260c0830182905260e08301919091526101009091015290565b64ffffffffff82165f9081526003602090815260408083208151610160810190925280546001600160a01b03811683529192909190830190600160a01b900460ff1660028111156109de576109de612d85565b60028111156109ef576109ef612d85565b81528154602090910190600160a81b900460ff166005811115610a1457610a14612d85565b6005811115610a2557610a25612d85565b8152815464ffffffffff600160b01b82048116602080850191909152600160d81b909204811660408085019190915260018501548083166060860152600160281b810483166080860152600160501b8104831660a0860152600160781b8104831660c0860152600160a01b900490911660e08401526002840180548251818502810185019093528083526101009094019391929091905f9084015b82821015610c74575f8481526020908190206040805160c0810182526004860290920180546001600160a01b038116845260ff600160a01b820481161515958501959095529293909291840191600160a81b9004166002811115610b2657610b26612d85565b6002811115610b3757610b37612d85565b815260200160018201548152602001600282018054610b5590613286565b80601f0160208091040260200160405190810160405280929190818152602001828054610b8190613286565b8015610bcc5780601f10610ba357610100808354040283529160200191610bcc565b820191905f5260205f20905b815481529060010190602001808311610baf57829003601f168201915b50505050508152602001600382018054610be590613286565b80601f0160208091040260200160405190810160405280929190818152602001828054610c1190613286565b8015610c5c5780601f10610c3357610100808354040283529160200191610c5c565b820191905f5260205f20905b815481529060010190602001808311610c3f57829003601f168201915b50505050508152505081526020019060010190610ac0565b50505050815250509050610c87816123cd565b81604001906005811115610c9d57610c9d612d85565b90816005811115610cb057610cb0612d85565b90525092915050565b5f805f83806020019051810190610cd0919061319a565b9250925092509193909250565b610ce561249c565b610cee5f61237e565b565b64ffffffffff81165f9081526003602090815260408083208151610160810190925280546001600160a01b0381168352610fe593830190600160a01b900460ff166002811115610d4257610d42612d85565b6002811115610d5357610d53612d85565b81528154602090910190600160a81b900460ff166005811115610d7857610d78612d85565b6005811115610d8957610d89612d85565b8152815464ffffffffff600160b01b82048116602080850191909152600160d81b909204811660408085019190915260018501548083166060860152600160281b810483166080860152600160501b8104831660a0860152600160781b8104831660c0860152600160a01b900490911660e08401526002840180548251818502810185019093528083526101009094019391929091905f9084015b82821015610fd8575f8481526020908190206040805160c0810182526004860290920180546001600160a01b038116845260ff600160a01b820481161515958501959095529293909291840191600160a81b9004166002811115610e8a57610e8a612d85565b6002811115610e9b57610e9b612d85565b815260200160018201548152602001600282018054610eb990613286565b80601f0160208091040260200160405190810160405280929190818152602001828054610ee590613286565b8015610f305780601f10610f0757610100808354040283529160200191610f30565b820191905f5260205f20905b815481529060010190602001808311610f1357829003601f168201915b50505050508152602001600382018054610f4990613286565b80601f0160208091040260200160405190810160405280929190818152602001828054610f7590613286565b8015610fc05780601f10610f9757610100808354040283529160200191610fc0565b820191905f5260205f20905b815481529060010190602001808311610fa357829003601f168201915b50505050508152505081526020019060010190610e24565b50505050815250506123cd565b92915050565b610ff36124c8565b610ffc81612515565b50565b64ffffffffff81165f908152600360205260409020600260408051610160810190915282546001600160a01b03811682526112ed919084906020830190600160a01b900460ff16600281111561105757611057612d85565b600281111561106857611068612d85565b81528154602090910190600160a81b900460ff16600581111561108d5761108d612d85565b600581111561109e5761109e612d85565b8152815464ffffffffff600160b01b82048116602080850191909152600160d81b909204811660408085019190915260018501548083166060860152600160281b810483166080860152600160501b8104831660a0860152600160781b8104831660c0860152600160a01b900490911660e08401526002840180548251818502810185019093528083526101009094019391929091905f9084015b82821015610fd8575f8481526020908190206040805160c0810182526004860290920180546001600160a01b038116845260ff600160a01b820481161515958501959095529293909291840191600160a81b900416600281111561119f5761119f612d85565b60028111156111b0576111b0612d85565b8152602001600182015481526020016002820180546111ce90613286565b80601f01602080910402602001604051908101604052809291908181526020018280546111fa90613286565b80156112455780601f1061121c57610100808354040283529160200191611245565b820191905f5260205f20905b81548152906001019060200180831161122857829003601f168201915b5050505050815260200160038201805461125e90613286565b80601f016020809104026020016040519081016040528092919081815260200182805461128a90613286565b80156112d55780601f106112ac576101008083540402835291602001916112d5565b820191905f5260205f20905b8154815290600101906020018083116112b857829003601f168201915b50505050508152505081526020019060010190611139565b60058111156112fe576112fe612d85565b1460405180604001604052806002815260200161333360f01b815250906113385760405162461bcd60e51b81526004016106209190613188565b50600181015481545f916113659164ffffffffff600160781b909204821691600160d81b909104166132d2565b64ffffffffff169050804211604051806040016040528060028152602001610ccd60f21b815250906113aa5760405162461bcd60e51b81526004016106209190613188565b50815460ff60a81b1916600360a81b17825560018201805464ffffffffff19164264ffffffffff161790555f5b60028301548110156114ed575f8360020182815481106113f9576113f96132f7565b5f918252602082206004909102018054909250600290829060ff600160a81b909104168281111561142c5761142c612d85565b600281111561143d5761143d612d85565b8152602081019190915260409081015f205460018401548454925163025d36a960e01b81526001600160a01b039283169450849363025d36a99361149f9290821691849160028a019160038b0191600160a01b90910460ff1690600401613384565b5f6040518083038185885af11580156114ba573d5f803e3d5ffd5b50505050506040513d5f823e601f3d908101601f191682016040526114e291908101906133d1565b5050506001016113d7565b5060405164ffffffffff841681527fda6084bb0aa902a7f6da10ba185d4aa129414651c90772417eff02a52112af2a906020015b60405180910390a1505050565b5f546001600160a01b0316331461155857604051633a02626960e01b815260040160405180910390fd5b6107608383836128e0565b61156b61249c565b6115bb8282808060200260200160405190810160405280939291908181526020015f905b828210156108c3576115ac60608302860136819003810190613211565b8152602001906001019061158f565b5050565b6040516370a0823160e01b81523060048201525f906001600160a01b038316906370a0823190602401602060405180830381865afa158015611603573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610fe59190613439565b604080518082019091526002815261333160f01b60208201525f90826116605760405162461bcd60e51b81526004016106209190613188565b50600180545f91600160b01b90910464ffffffffff1690601661168283613450565b82546101009290920a64ffffffffff8181021990931691831602179091558181165f9081526003602052604090208054600161ff0160a01b0319163360ff60a81b191617600160a81b1764ffffffffff60b01b1916600160b01b4293841602178155919250906116f5622e2480836132d2565b60018201805461127560a71b6effffffffff0000000000ffffffffff60501b1990911664ffffffffff93909316600160501b0264ffffffffff60a01b1916929092179190911790555f805b868110156119dd575f88888381811061175b5761175b6132f7565b905060200281019061176d9190613473565b61177b9060208101906130ae565b6001600160a01b0316141560405180604001604052806002815260200161353160f01b815250906117bf5760405162461bcd60e51b81526004016106209190613188565b505f8888838181106117d3576117d36132f7565b90506020028101906117e59190613473565b6117f690606081019060400161316d565b600281111561180757611807612d85565b11604051806040016040528060028152602001611a9960f11b815250906118415760405162461bcd60e51b81526004016106209190613188565b505f6002818a8a85818110611858576118586132f7565b905060200281019061186a9190613473565b61187b90606081019060400161316d565b600281111561188c5761188c612d85565b600281111561189d5761189d612d85565b815260208082019290925260409081015f205481518083019092526002825261199960f11b92820192909252916001600160a01b03909116036118f35760405162461bcd60e51b81526004016106209190613188565b508260020188888381811061190a5761190a6132f7565b905060200281019061191c9190613473565b81546001810183555f928352602090922090916004020161193d828261360a565b505081600281111561195157611951612d85565b888883818110611963576119636132f7565b90506020028101906119759190613473565b61198690606081019060400161316d565b600281111561199757611997612d85565b11156119d5578787828181106119af576119af6132f7565b90506020028101906119c19190613473565b6119d290606081019060400161316d565b91505b600101611740565b5081548190839060ff60a01b1916600160a01b836002811115611a0257611a02612d85565b02179055505f60025f836002811115611a1d57611a1d612d85565b6002811115611a2e57611a2e612d85565b815260208082019290925260409081015f208151808301909252546001600160a01b0381168252600160a01b900464ffffffffff1691810182905260018501805464ffffffffff60781b1916600160781b909302929092179091559050816002811115611a9d57611a9d612d85565b336001600160a01b03168664ffffffffff167f1e4588da4731f84a598f061ee45829a6450aa00aa28962657b6835641afbbac58b8b604051611ae0929190613724565b60405180910390a450929695505050505050565b5f546001600160a01b03163314611b1e57604051633a02626960e01b815260040160405180910390fd5b6115bb8282612960565b611b3061249c565b6001600160a01b038116611b5957604051631e4fbdf760e01b81525f6004820152602401610620565b610ffc8161237e565b604080518082019091525f808252602082015260025f836002811115611b8a57611b8a612d85565b6002811115611b9b57611b9b612d85565b815260208082019290925260409081015f208151808301909252546001600160a01b0381168252600160a01b900464ffffffffff169181019190915292915050565b611be5612a2f565b610ffc8161231d565b64ffffffffff83165f908152600360205260409020600160408051610160810190915282546001600160a01b0381168252611edc919084906020830190600160a01b900460ff166002811115611c4657611c46612d85565b6002811115611c5757611c57612d85565b81528154602090910190600160a81b900460ff166005811115611c7c57611c7c612d85565b6005811115611c8d57611c8d612d85565b8152815464ffffffffff600160b01b82048116602080850191909152600160d81b909204811660408085019190915260018501548083166060860152600160281b810483166080860152600160501b8104831660a0860152600160781b8104831660c0860152600160a01b900490911660e08401526002840180548251818502810185019093528083526101009094019391929091905f9084015b82821015610fd8575f8481526020908190206040805160c0810182526004860290920180546001600160a01b038116845260ff600160a01b820481161515958501959095529293909291840191600160a81b9004166002811115611d8e57611d8e612d85565b6002811115611d9f57611d9f612d85565b815260200160018201548152602001600282018054611dbd90613286565b80601f0160208091040260200160405190810160405280929190818152602001828054611de990613286565b8015611e345780601f10611e0b57610100808354040283529160200191611e34565b820191905f5260205f20905b815481529060010190602001808311611e1757829003601f168201915b50505050508152602001600382018054611e4d90613286565b80601f0160208091040260200160405190810160405280929190818152602001828054611e7990613286565b8015611ec45780601f10611e9b57610100808354040283529160200191611ec4565b820191905f5260205f20905b815481529060010190602001808311611ea757829003601f168201915b50505050508152505081526020019060010190611d28565b6005811115611eed57611eed612d85565b1460405180604001604052806002815260200161199b60f11b81525090611f275760405162461bcd60e51b81526004016106209190613188565b508054600160a01b900460ff166002811115611f4557611f45612d85565b836002811115611f5757611f57612d85565b1015604051806040016040528060028152602001611a1b60f11b81525090611f925760405162461bcd60e51b81526004016106209190613188565b508054604080518082019091526002815261343760f01b60208201529064ffffffffff600160b01b909104811690841611611fe05760405162461bcd60e51b81526004016106209190613188565b508054600160a91b64ffffffffff428116600160d81b02600165ffffffffff0160a81b039093169290921717825560405190851681527f1c4585f98a2bf1a1dca30917ba110f1b978343c7cce2c703495e5e47d51644569060200160405180910390a150505050565b5f5b81518110156115bb575f828281518110612067576120676132f7565b602002602001015190505f6001600160a01b031681602001515f01516001600160a01b03161415604051806040016040528060028152602001611a1960f11b815250906120c75760405162461bcd60e51b81526004016106209190613188565b505f815160028111156120dc576120dc612d85565b1160405180604001604052806002815260200161353360f01b815250906121165760405162461bcd60e51b81526004016106209190613188565b506201518064ffffffffff1681602001516020015164ffffffffff16101580156121595750620d2f0064ffffffffff1681602001516020015164ffffffffff1611155b60405180604001604052806002815260200161373760f01b815250906121925760405162461bcd60e51b81526004016106209190613188565b505f6001825160028111156121a9576121a9612d85565b146121b55760016121b8565b60025b6020830151519091506001600160a01b031660025f83828111156121de576121de612d85565b60028111156121ef576121ef612d85565b815260208082019290925260409081015f205481518083019092526002825261343360f01b92820192909252916001600160a01b03909116036122455760405162461bcd60e51b81526004016106209190613188565b50816020015160025f845f0151600281111561226357612263612d85565b600281111561227457612274612d85565b81526020808201929092526040015f20825181549383015164ffffffffff16600160a01b026001600160c81b03199094166001600160a01b039182161793909317905583015151835191169060028111156122d1576122d1612d85565b60208085015181015160405164ffffffffff90911681527fa7c32b123d845f42a44986cab71b2d81819f15f4478f47d9830a762251372c90910160405180910390a3505060010161204b565b600180546001600160a01b038381166001600160a01b031983168117909355604080519190921680825260208201939093527f064d28d3d3071c5cbc271a261c10c2f0f0d9e319390397101aa0eb23c6bad909910160405180910390a15050565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60408101515f90818160058111156123e7576123e7612d85565b14806124055750600381600581111561240257612402612d85565b10155b156124105792915050565b600181600581111561242457612424612d85565b14801561243c57508260e0015164ffffffffff164210155b8061248e5750600281600581111561245657612456612d85565b14801561248e5750826101200151836101000151846080015161247991906132d2565b61248391906132d2565b64ffffffffff164210155b15610fe55750600592915050565b5f546001600160a01b03163314610cee5760405163118cdaa760e01b8152336004820152602401610620565b6001546001600160a01b03163314610cee5760405162461bcd60e51b815260206004820152601060248201526f27a7262cafa12cafa3aaa0a92224a0a760811b6044820152606401610620565b64ffffffffff81165f9081526003602090815260408083208151610160810190925280546001600160a01b038116835290939261280392918591830190600160a01b900460ff16600281111561256d5761256d612d85565b600281111561257e5761257e612d85565b81528154602090910190600160a81b900460ff1660058111156125a3576125a3612d85565b60058111156125b4576125b4612d85565b8152815464ffffffffff600160b01b82048116602080850191909152600160d81b909204811660408085019190915260018501548083166060860152600160281b810483166080860152600160501b8104831660a0860152600160781b8104831660c0860152600160a01b900490911660e08401526002840180548251818502810185019093528083526101009094019391929091905f9084015b82821015610fd8575f8481526020908190206040805160c0810182526004860290920180546001600160a01b038116845260ff600160a01b820481161515958501959095529293909291840191600160a81b90041660028111156126b5576126b5612d85565b60028111156126c6576126c6612d85565b8152602001600182015481526020016002820180546126e490613286565b80601f016020809104026020016040519081016040528092919081815260200182805461271090613286565b801561275b5780601f106127325761010080835404028352916020019161275b565b820191905f5260205f20905b81548152906001019060200180831161273e57829003601f168201915b5050505050815260200160038201805461277490613286565b80601f01602080910402602001604051908101604052809291908181526020018280546127a090613286565b80156127eb5780601f106127c2576101008083540402835291602001916127eb565b820191905f5260205f20905b8154815290600101906020018083116127ce57829003601f168201915b5050505050815250508152602001906001019061264f565b9050600381600581111561281957612819612d85565b1080156128385750600181600581111561283557612835612d85565b10155b60405180604001604052806002815260200161333560f01b815250906128715760405162461bcd60e51b81526004016106209190613188565b50815460ff60a81b1916600160aa1b17825560018201805464ffffffffff428116600160281b0269ffffffffff0000000000199092169190911790915560405190841681527f1f5679387cd5a407876abac64429108734317fc18c0de46eae3cbc0a69a44d5990602001611521565b5f6128ea846115bf565b90508181116128f957806128fb565b815b91506129116001600160a01b0385168484612a9d565b826001600160a01b0316846001600160a01b0316336001600160a01b03167fc7af665d489507e14ae25ac7ab0030fc7f570869610bdd32117ea56b60ae5c61856040516106f891815260200190565b604080515f808252602082019092526001600160a01b0384169083906040516129899190613823565b5f6040518083038185875af1925050503d805f81146129c3576040519150601f19603f3d011682016040523d82523d5f602084013e6129c8565b606091505b50509050806129ea57604051630db2c7f160e31b815260040160405180910390fd5b6040518281526001600160a01b0384169033907fb7c602059992183c7b767c08204223afc99f1895fd175adf9ece23ce9f5bb8b79060200160405180910390a3505050565b5f546001600160a01b0316331480612a5157506001546001600160a01b031633145b610cee5760405162461bcd60e51b815260206004820152601960248201527f4f4e4c595f42595f4f574e45525f4f525f475541524449414e000000000000006044820152606401610620565b604080516001600160a01b03841660248201526044808201849052825180830390910181526064909101909152602080820180516001600160e01b031663a9059cbb60e01b178152825161076093879390925f9283929183919082885af180612b0b576040513d5f823e3d81fd5b50505f513d91508115612b22578060011415612b2f565b6001600160a01b0384163b155b15612b5857604051635274afe760e01b81526001600160a01b0385166004820152602401610620565b50505050565b6001600160a01b0381168114610ffc575f80fd5b634e487b7160e01b5f52604160045260245ffd5b604080519081016001600160401b0381118282101715612ba857612ba8612b72565b60405290565b604051601f8201601f191681016001600160401b0381118282101715612bd657612bd6612b72565b604052919050565b5f6001600160401b03821115612bf657612bf6612b72565b50601f01601f191660200190565b5f82601f830112612c13575f80fd5b8135612c26612c2182612bde565b612bae565b818152846020838601011115612c3a575f80fd5b816020850160208301375f918101602001919091529392505050565b5f805f60608486031215612c68575f80fd5b8335612c7381612b5e565b92506020840135915060408401356001600160401b03811115612c94575f80fd5b612ca086828701612c04565b9150509250925092565b5f8083601f840112612cba575f80fd5b5081356001600160401b03811115612cd0575f80fd5b602083019150836020606083028501011115612cea575f80fd5b9250929050565b5f805f8060608587031215612d04575f80fd5b8435612d0f81612b5e565b93506020850135612d1f81612b5e565b925060408501356001600160401b03811115612d39575f80fd5b612d4587828801612caa565b95989497509550505050565b64ffffffffff81168114610ffc575f80fd5b5f60208284031215612d73575f80fd5b8135612d7e81612d51565b9392505050565b634e487b7160e01b5f52602160045260245ffd5b60038110612da957612da9612d85565b9052565b60068110612da957612da9612d85565b5f5b83811015612dd7578181015183820152602001612dbf565b50505f910152565b5f8151808452612df6816020860160208601612dbd565b601f01601f19169290920160200192915050565b5f82825180855260208086019550808260051b8401018186015f5b84811015612ebb57858303601f19018952815180516001600160a01b031684528481015115158585015260408082015160c09190612e6582880182612d99565b505060608083015181870152506080808301518282880152612e8983880182612ddf565b9250505060a08083015192508582038187015250612ea78183612ddf565b9a86019a9450505090830190600101612e25565b5090979650505050505050565b60208152612ee26020820183516001600160a01b03169052565b5f6020830151612ef56040840182612d99565b506040830151612f086060840182612dad565b50606083015164ffffffffff8116608084015250608083015164ffffffffff811660a08401525060a083015164ffffffffff811660c08401525060c083015164ffffffffff811660e08401525060e0830151610100612f6f8185018364ffffffffff169052565b8401519050610120612f898482018364ffffffffff169052565b8401519050610140612fa38482018364ffffffffff169052565b840151610160848101529050612fbd610180840182612e0a565b949350505050565b5f60208284031215612fd5575f80fd5b81356001600160401b03811115612fea575f80fd5b612fbd84828501612c04565b64ffffffffff848116825260608201906130136020840186612d99565b808416604084015250949350505050565b60208101610fe58284612dad565b5f805f60608486031215613044575f80fd5b833561304f81612b5e565b9250602084013561305f81612b5e565b929592945050506040919091013590565b5f8060208385031215613081575f80fd5b82356001600160401b03811115613096575f80fd5b6130a285828601612caa565b90969095509350505050565b5f602082840312156130be575f80fd5b8135612d7e81612b5e565b5f80602083850312156130da575f80fd5b82356001600160401b03808211156130f0575f80fd5b818501915085601f830112613103575f80fd5b813581811115613111575f80fd5b8660208260051b8501011115613125575f80fd5b60209290920196919550909350505050565b5f8060408385031215613148575f80fd5b823561315381612b5e565b946020939093013593505050565b60038110610ffc575f80fd5b5f6020828403121561317d575f80fd5b8135612d7e81613161565b602081525f612d7e6020830184612ddf565b5f805f606084860312156131ac575f80fd5b83516131b781612d51565b60208501519093506131c881613161565b60408501519092506131d981612d51565b809150509250925092565b604081525f6131f66040830185612ddf565b82810360208401526132088185612ddf565b95945050505050565b5f8183036060811215613222575f80fd5b61322a612b86565b833561323581613161565b81526040601f1983011215613248575f80fd5b613250612b86565b9150602084013561326081612b5e565b8252604084013561327081612d51565b6020838101919091528101919091529392505050565b600181811c9082168061329a57607f821691505b6020821081036132b857634e487b7160e01b5f52602260045260245ffd5b50919050565b634e487b7160e01b5f52601160045260245ffd5b64ffffffffff8181168382160190808211156132f0576132f06132be565b5092915050565b634e487b7160e01b5f52603260045260245ffd5b5f815461331781613286565b808552602060018381168015613334576001811461334e57613379565b60ff1985168884015283151560051b880183019550613379565b865f52825f205f5b858110156133715781548a8201860152908301908401613356565b890184019650505b505050505092915050565b60018060a01b038616815284602082015260a060408201525f6133aa60a083018661330b565b82810360608401526133bc818661330b565b91505082151560808301529695505050505050565b5f602082840312156133e1575f80fd5b81516001600160401b038111156133f6575f80fd5b8201601f81018413613406575f80fd5b8051613414612c2182612bde565b818152856020838501011115613428575f80fd5b613208826020830160208601612dbd565b5f60208284031215613449575f80fd5b5051919050565b5f64ffffffffff808316818103613469576134696132be565b6001019392505050565b5f823560be19833603018112613487575f80fd5b9190910192915050565b8015158114610ffc575f80fd5b600382106134ae576134ae612d85565b805460ff60a81b191660a89290921b60ff60a81b16919091179055565b5f808335601e198436030181126134e0575f80fd5b8301803591506001600160401b038211156134f9575f80fd5b602001915036819003821315612cea575f80fd5b601f82111561076057805f5260205f20601f840160051c810160208510156135325750805b601f840160051c820191505b81811015610926575f815560010161353e565b6001600160401b0383111561356857613568612b72565b61357c836135768354613286565b8361350d565b5f601f8411600181146135ad575f85156135965750838201355b5f19600387901b1c1916600186901b178355610926565b5f83815260208120601f198716915b828110156135dc57868501358255602094850194600190920191016135bc565b50868210156135f8575f1960f88860031b161c19848701351681555b505060018560011b0183555050505050565b813561361581612b5e565b81546001600160a01b031981166001600160a01b03929092169182178355602084013561364181613491565b6001600160a81b03199190911690911790151560a01b60ff60a01b16178155604082013561366e81613161565b613678818361349e565b506060820135600182015561369060808301836134cb565b61369e818360028601613551565b50506136ad60a08301836134cb565b612b58818360038601613551565b5f808335601e198436030181126136d0575f80fd5b83016020810192503590506001600160401b038111156136ee575f80fd5b803603821315612cea575f80fd5b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b60208082528181018390525f906040808401600586901b8501820187855b8881101561381557878303603f190184528135368b900360be19018112613767575f80fd5b8a0160c0813561377681612b5e565b6001600160a01b031685528188013561378e81613491565b151585890152818701356137a181613161565b6137ad88870182612d99565b506060828101359086015260806137c6818401846136bb565b83838901526137d884890182846136fc565b935050505060a06137eb818401846136bb565b9350868303828801526137ff8385836136fc565b978a019796505050928701925050600101613742565b509098975050505050505050565b5f8251613487818460208701612dbd56fea164736f6c6343000816000a

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

00000000000000000000000058e003a3c6f2aeed6a2a6bc77b504566523cb15c0000000000000000000000009aee0b04504cef83a65ac3f0e838d0593bcb2bc70000000000000000000000000000000000000000000000000000000000000001

-----Decoded View---------------
Arg [0] : crossChainController (address): 0x58e003a3C6f2Aeed6a2a6Bc77B504566523cb15c
Arg [1] : messageOriginator (address): 0x9AEE0B04504CeF83A65AC3f0e838D0593BCb2BC7
Arg [2] : originChainId (uint256): 1

-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 00000000000000000000000058e003a3c6f2aeed6a2a6bc77b504566523cb15c
Arg [1] : 0000000000000000000000009aee0b04504cef83a65ac3f0e838d0593bcb2bc7
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000001


Block Transaction Gas Used Reward
view all blocks produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits

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