ETH Price: $3,387.98 (+0.81%)

Contract

0x7A9ff54A6eE4a21223036890bB8c4ea2D62c686b
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00
Transaction Hash
Method
Block
From
To
Toggle Disable A...179045392023-08-13 7:46:35504 days ago1691912795IN
0x7A9ff54A...2D62c686b
0 ETH0.0005675412.37836156
Toggle Disable A...179045362023-08-13 7:45:47504 days ago1691912747IN
0x7A9ff54A...2D62c686b
0 ETH0.0005103511.13089324
Toggle Disable A...179045322023-08-13 7:44:59504 days ago1691912699IN
0x7A9ff54A...2D62c686b
0 ETH0.0005296511.55185105
Toggle Disable A...179045292023-08-13 7:44:23504 days ago1691912663IN
0x7A9ff54A...2D62c686b
0 ETH0.0004914110.71791402
Toggle Disable A...179045262023-08-13 7:43:47504 days ago1691912627IN
0x7A9ff54A...2D62c686b
0 ETH0.0005199711.34069693
Toggle Disable A...178276262023-08-02 13:31:23514 days ago1690983083IN
0x7A9ff54A...2D62c686b
0 ETH0.0013141928.66288573
Toggle Disable A...178114812023-07-31 7:24:59517 days ago1690788299IN
0x7A9ff54A...2D62c686b
0 ETH0.000309412.91877492
Toggle Disable A...178114782023-07-31 7:24:23517 days ago1690788263IN
0x7A9ff54A...2D62c686b
0 ETH0.0003177313.2666307
Toggle Disable A...178114742023-07-31 7:23:35517 days ago1690788215IN
0x7A9ff54A...2D62c686b
0 ETH0.0003171713.24323813
Toggle Disable A...178084782023-07-30 21:18:59517 days ago1690751939IN
0x7A9ff54A...2D62c686b
0 ETH0.0008370618.25658986
Toggle Disable A...178084722023-07-30 21:17:47517 days ago1690751867IN
0x7A9ff54A...2D62c686b
0 ETH0.0008933719.48473411
Toggle Disable A...178084672023-07-30 21:16:47517 days ago1690751807IN
0x7A9ff54A...2D62c686b
0 ETH0.0008727219.03433669
Toggle Disable A...176927242023-07-14 15:55:59533 days ago1689350159IN
0x7A9ff54A...2D62c686b
0 ETH0.0012902528.1407243
Toggle Disable A...176544432023-07-09 6:42:59539 days ago1688884979IN
0x7A9ff54A...2D62c686b
0 ETH0.0006496614.1693313

View more zero value Internal Transactions in Advanced View mode

Advanced mode:
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
EthRobotKeeper

Compiler Version
v0.8.18+commit.87f61d96

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion
File 1 of 8 : EthRobotKeeper.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import {IAaveGovernanceV2} from 'aave-address-book/AaveGovernanceV2.sol';
import {IProposalValidator} from '../interfaces/IProposalValidator.sol';
import {IEthRobotKeeper, AutomationCompatibleInterface} from '../interfaces/IEthRobotKeeper.sol';
import {IAaveCLRobotOperator} from '../interfaces/IAaveCLRobotOperator.sol';
import {Ownable} from 'solidity-utils/contracts/oz-common/Ownable.sol';

/**
 * @title EthRobotKeeper
 * @author BGD Labs
 * @dev Aave chainlink keeper-compatible contract for proposal automation:
 * - checks if the proposal state could be moved to queued, executed or cancelled
 * - moves the proposal to queued/executed/cancelled if all the conditions are met
 */
contract EthRobotKeeper is Ownable, IEthRobotKeeper {
  /// @inheritdoc IEthRobotKeeper
  address public immutable GOVERNANCE_V2;

  /// @inheritdoc IEthRobotKeeper
  uint256 public constant MAX_ACTIONS = 25;

  /// @inheritdoc IEthRobotKeeper
  uint256 public constant MAX_SKIP = 20;

  mapping(uint256 => bool) internal _disabledProposals;

  error NoActionCanBePerformed();

  /**
   * @param governanceV2 address of the governance contract.
   */
  constructor(address governanceV2) {
    GOVERNANCE_V2 = governanceV2;
  }

  /**
   * @inheritdoc AutomationCompatibleInterface
   * @dev run off-chain, checks if proposals should be moved to queued, executed or cancelled state
   */
  function checkUpkeep(bytes calldata) external view override returns (bool, bytes memory) {
    ActionWithId[] memory actionsWithIds = new ActionWithId[](MAX_ACTIONS);

    uint256 index = IAaveGovernanceV2(GOVERNANCE_V2).getProposalsCount();
    uint256 skipCount = 0;
    uint256 actionsCount = 0;

    // loops from the last/latest proposalId until MAX_SKIP iterations. resets skipCount and checks more MAX_SKIP number
    // of proposals if any action could be performed. we only check proposals until MAX_SKIP iterations from the last/latest
    // proposalId or proposals where any action could be performed, and proposals before that will be not be checked by the keeper.
    while (index != 0 && skipCount <= MAX_SKIP && actionsCount < MAX_ACTIONS) {
      uint256 proposalId = index - 1;

      IAaveGovernanceV2.ProposalState proposalState = IAaveGovernanceV2(GOVERNANCE_V2)
        .getProposalState(proposalId);
      IAaveGovernanceV2.ProposalWithoutVotes memory proposal = IAaveGovernanceV2(GOVERNANCE_V2)
        .getProposalById(proposalId);

      if (!isDisabled(proposalId)) {
        if (_isProposalInFinalState(proposalState)) {
          skipCount++;
        } else {
          if (_canProposalBeCancelled(proposalState, proposal)) {
            actionsWithIds[actionsCount].id = proposalId;
            actionsWithIds[actionsCount].action = ProposalAction.PerformCancel;
            actionsCount++;
          } else if (_canProposalBeQueued(proposalState)) {
            actionsWithIds[actionsCount].id = proposalId;
            actionsWithIds[actionsCount].action = ProposalAction.PerformQueue;
            actionsCount++;
          } else if (_canProposalBeExecuted(proposalState, proposal)) {
            actionsWithIds[actionsCount].id = proposalId;
            actionsWithIds[actionsCount].action = ProposalAction.PerformExecute;
            actionsCount++;
          }
          skipCount = 0;
        }
      }

      index--;
    }

    if (actionsCount > 0) {
      // we do not know the length in advance, so we init arrays with MAX_ACTIONS
      // and then squeeze the array using mstore
      assembly {
        mstore(actionsWithIds, actionsCount)
      }
      bytes memory performData = abi.encode(actionsWithIds);
      return (true, performData);
    }

    return (false, '');
  }

  /**
   * @inheritdoc AutomationCompatibleInterface
   * @dev if proposal could be queued/executed/cancelled - executes queue/cancel/execute action on the governance contract
   * @param performData array of proposal ids, array of actions whether to queue, execute or cancel
   */
  function performUpkeep(bytes calldata performData) external override {
    ActionWithId[] memory actionsWithIds = abi.decode(performData, (ActionWithId[]));
    bool isActionPerformed;

    // executes action on proposalIds in order from first to last
    for (uint256 i = actionsWithIds.length; i > 0; i--) {
      uint256 proposalId = actionsWithIds[i - 1].id;
      ProposalAction action = actionsWithIds[i - 1].action;

      IAaveGovernanceV2.ProposalWithoutVotes memory proposal = IAaveGovernanceV2(GOVERNANCE_V2)
        .getProposalById(proposalId);
      IAaveGovernanceV2.ProposalState proposalState = IAaveGovernanceV2(GOVERNANCE_V2)
        .getProposalState(proposalId);

      if (
        action == ProposalAction.PerformCancel && _canProposalBeCancelled(proposalState, proposal)
      ) {
        try IAaveGovernanceV2(GOVERNANCE_V2).cancel(proposalId) {
          isActionPerformed = true;
          emit ActionSucceeded(proposalId, action);
        } catch Error(string memory reason) {
          emit ActionFailed(proposalId, action, reason);
        }
      } else if (action == ProposalAction.PerformQueue && _canProposalBeQueued(proposalState)) {
        try IAaveGovernanceV2(GOVERNANCE_V2).queue(proposalId) {
          isActionPerformed = true;
          emit ActionSucceeded(proposalId, action);
        } catch Error(string memory reason) {
          emit ActionFailed(proposalId, action, reason);
        }
      } else if (
        action == ProposalAction.PerformExecute && _canProposalBeExecuted(proposalState, proposal)
      ) {
        try IAaveGovernanceV2(GOVERNANCE_V2).execute(proposalId) {
          isActionPerformed = true;
          emit ActionSucceeded(proposalId, action);
        } catch Error(string memory reason) {
          emit ActionFailed(proposalId, action, reason);
        }
      }
    }

    if (!isActionPerformed) revert NoActionCanBePerformed();
  }

  /// @inheritdoc IEthRobotKeeper
  function toggleDisableAutomationById(
    uint256 proposalId
  ) external onlyOwner {
    _disabledProposals[proposalId] = !_disabledProposals[proposalId];
  }

  /// @inheritdoc IEthRobotKeeper
  function isDisabled(uint256 proposalId) public view returns (bool) {
    return _disabledProposals[proposalId];
  }

  /**
   * @notice method to check if the proposal state is in final state.
   * @param proposalState the current state the proposal is in.
   * @return true if the proposal state is final state, false otherwise.
   */
  function _isProposalInFinalState(
    IAaveGovernanceV2.ProposalState proposalState
  ) internal pure returns (bool) {
    if (
      proposalState == IAaveGovernanceV2.ProposalState.Executed ||
      proposalState == IAaveGovernanceV2.ProposalState.Canceled ||
      proposalState == IAaveGovernanceV2.ProposalState.Expired ||
      proposalState == IAaveGovernanceV2.ProposalState.Failed
    ) {
      return true;
    }
    return false;
  }

  /**
   * @notice method to check if proposal could be queued.
   * @param proposalState the current state the proposal is in.
   * @return true if the proposal could be queued, false otherwise.
   */
  function _canProposalBeQueued(
    IAaveGovernanceV2.ProposalState proposalState
  ) internal pure returns (bool) {
    return proposalState == IAaveGovernanceV2.ProposalState.Succeeded;
  }

  /**
   * @notice method to check if proposal could be executed.
   * @param proposalState the current state the proposal is in.
   * @param proposal the proposal to check if it can be executed.
   * @return true if the proposal could be executed, false otherwise.
   */
  function _canProposalBeExecuted(
    IAaveGovernanceV2.ProposalState proposalState,
    IAaveGovernanceV2.ProposalWithoutVotes memory proposal
  ) internal view returns (bool) {
    if (
      proposalState == IAaveGovernanceV2.ProposalState.Queued &&
      block.timestamp >= proposal.executionTime
    ) {
      return true;
    }
    return false;
  }

  /**
   * @notice method to check if proposal could be cancelled.
   * @param proposalState the current state the proposal is in.
   * @param proposal the proposal to check if it can be cancelled.
   * @return true if the proposal could be cancelled, false otherwise.
   */
  function _canProposalBeCancelled(
    IAaveGovernanceV2.ProposalState proposalState,
    IAaveGovernanceV2.ProposalWithoutVotes memory proposal
  ) internal view returns (bool) {
    IProposalValidator proposalValidator = IProposalValidator(address(proposal.executor));
    if (
      proposalState == IAaveGovernanceV2.ProposalState.Expired ||
      proposalState == IAaveGovernanceV2.ProposalState.Canceled ||
      proposalState == IAaveGovernanceV2.ProposalState.Executed
    ) {
      return false;
    }
    return
      proposalValidator.validateProposalCancellation(
        IAaveGovernanceV2(GOVERNANCE_V2),
        proposal.creator,
        block.number - 1
      );
  }
}

File 2 of 8 : AaveGovernanceV2.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.6.0;
pragma abicoder v2;

interface IGovernanceStrategy {
  /**
   * @dev Returns the Proposition Power of a user at a specific block number.
   * @param user Address of the user.
   * @param blockNumber Blocknumber at which to fetch Proposition Power
   * @return Power number
   **/
  function getPropositionPowerAt(address user, uint256 blockNumber) external view returns (uint256);

  /**
   * @dev Returns the total supply of Outstanding Proposition Tokens
   * @param blockNumber Blocknumber at which to evaluate
   * @return total supply at blockNumber
   **/
  function getTotalPropositionSupplyAt(uint256 blockNumber) external view returns (uint256);

  /**
   * @dev Returns the total supply of Outstanding Voting Tokens
   * @param blockNumber Blocknumber at which to evaluate
   * @return total supply at blockNumber
   **/
  function getTotalVotingSupplyAt(uint256 blockNumber) external view returns (uint256);

  /**
   * @dev Returns the Vote Power of a user at a specific block number.
   * @param user Address of the user.
   * @param blockNumber Blocknumber at which to fetch Vote Power
   * @return Vote number
   **/
  function getVotingPowerAt(address user, uint256 blockNumber) external view returns (uint256);
}

interface IExecutorWithTimelock {
  /**
   * @dev emitted when a new pending admin is set
   * @param newPendingAdmin address of the new pending admin
   **/
  event NewPendingAdmin(address newPendingAdmin);

  /**
   * @dev emitted when a new admin is set
   * @param newAdmin address of the new admin
   **/
  event NewAdmin(address newAdmin);

  /**
   * @dev emitted when a new delay (between queueing and execution) is set
   * @param delay new delay
   **/
  event NewDelay(uint256 delay);

  /**
   * @dev emitted when a new (trans)action is Queued.
   * @param actionHash hash of the action
   * @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
   **/
  event QueuedAction(
    bytes32 actionHash,
    address indexed target,
    uint256 value,
    string signature,
    bytes data,
    uint256 executionTime,
    bool withDelegatecall
  );

  /**
   * @dev emitted when an action is Cancelled
   * @param actionHash hash of the action
   * @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
   **/
  event CancelledAction(
    bytes32 actionHash,
    address indexed target,
    uint256 value,
    string signature,
    bytes data,
    uint256 executionTime,
    bool withDelegatecall
  );

  /**
   * @dev emitted when an action is Cancelled
   * @param actionHash hash of the action
   * @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(
    bytes32 actionHash,
    address indexed target,
    uint256 value,
    string signature,
    bytes data,
    uint256 executionTime,
    bool withDelegatecall,
    bytes resultData
  );

  /**
   * @dev Getter of the current admin address (should be governance)
   * @return The address of the current admin
   **/
  function getAdmin() external view returns (address);

  /**
   * @dev Getter of the current pending admin address
   * @return The address of the pending admin
   **/
  function getPendingAdmin() external view returns (address);

  /**
   * @dev Getter of the delay between queuing and execution
   * @return The delay in seconds
   **/
  function getDelay() external view returns (uint256);

  /**
   * @dev Returns whether an action (via actionHash) is queued
   * @param actionHash hash of the action to be checked
   * keccak256(abi.encode(target, value, signature, data, executionTime, withDelegatecall))
   * @return true if underlying action of actionHash is queued
   **/
  function isActionQueued(bytes32 actionHash) external view returns (bool);

  /**
   * @dev Checks whether a proposal is over its grace period
   * @param governance Governance contract
   * @param proposalId Id of the proposal against which to test
   * @return true of proposal is over grace period
   **/
  function isProposalOverGracePeriod(
    IAaveGovernanceV2 governance,
    uint256 proposalId
  ) external view returns (bool);

  /**
   * @dev Getter of grace period constant
   * @return grace period in seconds
   **/
  function GRACE_PERIOD() external view returns (uint256);

  /**
   * @dev Getter of minimum delay constant
   * @return minimum delay in seconds
   **/
  function MINIMUM_DELAY() external view returns (uint256);

  /**
   * @dev Getter of maximum delay constant
   * @return maximum delay in seconds
   **/
  function MAXIMUM_DELAY() external view returns (uint256);

  /**
   * @dev Function, called by Governance, that queue a transaction, returns action hash
   * @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 executionTime time at which to execute the transaction
   * @param withDelegatecall boolean, true = transaction delegatecalls the target, else calls the target
   **/
  function queueTransaction(
    address target,
    uint256 value,
    string memory signature,
    bytes memory data,
    uint256 executionTime,
    bool withDelegatecall
  ) external returns (bytes32);

  /**
   * @dev Function, called by Governance, that cancels 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 executionTime time at which to execute the transaction
   * @param withDelegatecall boolean, true = transaction delegatecalls the target, else calls the target
   **/
  function executeTransaction(
    address target,
    uint256 value,
    string memory signature,
    bytes memory data,
    uint256 executionTime,
    bool withDelegatecall
  ) external payable returns (bytes memory);

  /**
   * @dev Function, called by Governance, that cancels a transaction, returns action hash
   * @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 executionTime time at which to execute the transaction
   * @param withDelegatecall boolean, true = transaction delegatecalls the target, else calls the target
   **/
  function cancelTransaction(
    address target,
    uint256 value,
    string memory signature,
    bytes memory data,
    uint256 executionTime,
    bool withDelegatecall
  ) external returns (bytes32);
}

interface IAaveGovernanceV2 {
  enum ProposalState {
    Pending,
    Canceled,
    Active,
    Failed,
    Succeeded,
    Queued,
    Expired,
    Executed
  }

  struct Vote {
    bool support;
    uint248 votingPower;
  }

  struct Proposal {
    uint256 id;
    address creator;
    IExecutorWithTimelock executor;
    address[] targets;
    uint256[] values;
    string[] signatures;
    bytes[] calldatas;
    bool[] withDelegatecalls;
    uint256 startBlock;
    uint256 endBlock;
    uint256 executionTime;
    uint256 forVotes;
    uint256 againstVotes;
    bool executed;
    bool canceled;
    address strategy;
    bytes32 ipfsHash;
    mapping(address => Vote) votes;
  }

  struct ProposalWithoutVotes {
    uint256 id;
    address creator;
    IExecutorWithTimelock executor;
    address[] targets;
    uint256[] values;
    string[] signatures;
    bytes[] calldatas;
    bool[] withDelegatecalls;
    uint256 startBlock;
    uint256 endBlock;
    uint256 executionTime;
    uint256 forVotes;
    uint256 againstVotes;
    bool executed;
    bool canceled;
    address strategy;
    bytes32 ipfsHash;
  }

  /**
   * @dev emitted when a new proposal is created
   * @param id Id of the proposal
   * @param creator address of the creator
   * @param executor The ExecutorWithTimelock contract that will execute the proposal
   * @param targets list of contracts called by proposal's associated transactions
   * @param values list of value in wei for each propoposal's associated transaction
   * @param signatures list of function signatures (can be empty) to be used when created the callData
   * @param calldatas list of calldatas: if associated signature empty, calldata ready, else calldata is arguments
   * @param withDelegatecalls boolean, true = transaction delegatecalls the taget, else calls the target
   * @param startBlock block number when vote starts
   * @param endBlock block number when vote ends
   * @param strategy address of the governanceStrategy contract
   * @param ipfsHash IPFS hash of the proposal
   **/
  event ProposalCreated(
    uint256 id,
    address indexed creator,
    IExecutorWithTimelock indexed executor,
    address[] targets,
    uint256[] values,
    string[] signatures,
    bytes[] calldatas,
    bool[] withDelegatecalls,
    uint256 startBlock,
    uint256 endBlock,
    address strategy,
    bytes32 ipfsHash
  );

  /**
   * @dev emitted when a proposal is canceled
   * @param id Id of the proposal
   **/
  event ProposalCanceled(uint256 id);

  /**
   * @dev emitted when a proposal is queued
   * @param id Id of the proposal
   * @param executionTime time when proposal underlying transactions can be executed
   * @param initiatorQueueing address of the initiator of the queuing transaction
   **/
  event ProposalQueued(uint256 id, uint256 executionTime, address indexed initiatorQueueing);
  /**
   * @dev emitted when a proposal is executed
   * @param id Id of the proposal
   * @param initiatorExecution address of the initiator of the execution transaction
   **/
  event ProposalExecuted(uint256 id, address indexed initiatorExecution);
  /**
   * @dev emitted when a vote is registered
   * @param id Id of the proposal
   * @param voter address of the voter
   * @param support boolean, true = vote for, false = vote against
   * @param votingPower Power of the voter/vote
   **/
  event VoteEmitted(uint256 id, address indexed voter, bool support, uint256 votingPower);

  event GovernanceStrategyChanged(address indexed newStrategy, address indexed initiatorChange);

  event VotingDelayChanged(uint256 newVotingDelay, address indexed initiatorChange);

  event ExecutorAuthorized(address executor);

  event ExecutorUnauthorized(address executor);

  /**
   * @dev Creates a Proposal (needs Proposition Power of creator > Threshold)
   * @param executor The ExecutorWithTimelock contract that will execute the proposal
   * @param targets list of contracts called by proposal's associated transactions
   * @param values list of value in wei for each propoposal's associated transaction
   * @param signatures list of function signatures (can be empty) to be used when created the callData
   * @param calldatas list of calldatas: if associated signature empty, calldata ready, else calldata is arguments
   * @param withDelegatecalls if true, transaction delegatecalls the taget, else calls the target
   * @param ipfsHash IPFS hash of the proposal
   **/
  function create(
    IExecutorWithTimelock executor,
    address[] memory targets,
    uint256[] memory values,
    string[] memory signatures,
    bytes[] memory calldatas,
    bool[] memory withDelegatecalls,
    bytes32 ipfsHash
  ) external returns (uint256);

  /**
   * @dev Cancels a Proposal,
   * either at anytime by guardian
   * or when proposal is Pending/Active and threshold no longer reached
   * @param proposalId id of the proposal
   **/
  function cancel(uint256 proposalId) external;

  /**
   * @dev Queue the proposal (If Proposal Succeeded)
   * @param proposalId id of the proposal to queue
   **/
  function queue(uint256 proposalId) external;

  /**
   * @dev Execute the proposal (If Proposal Queued)
   * @param proposalId id of the proposal to execute
   **/
  function execute(uint256 proposalId) external payable;

  /**
   * @dev Function allowing msg.sender to vote for/against a proposal
   * @param proposalId id of the proposal
   * @param support boolean, true = vote for, false = vote against
   **/
  function submitVote(uint256 proposalId, bool support) external;

  /**
   * @dev Function to register the vote of user that has voted offchain via signature
   * @param proposalId id of the proposal
   * @param support boolean, true = vote for, false = vote against
   * @param v v part of the voter signature
   * @param r r part of the voter signature
   * @param s s part of the voter signature
   **/
  function submitVoteBySignature(
    uint256 proposalId,
    bool support,
    uint8 v,
    bytes32 r,
    bytes32 s
  ) external;

  /**
   * @dev Set new GovernanceStrategy
   * Note: owner should be a timelocked executor, so needs to make a proposal
   * @param governanceStrategy new Address of the GovernanceStrategy contract
   **/
  function setGovernanceStrategy(address governanceStrategy) external;

  /**
   * @dev Set new Voting Delay (delay before a newly created proposal can be voted on)
   * Note: owner should be a timelocked executor, so needs to make a proposal
   * @param votingDelay new voting delay in seconds
   **/
  function setVotingDelay(uint256 votingDelay) external;

  /**
   * @dev Add new addresses to the list of authorized executors
   * @param executors list of new addresses to be authorized executors
   **/
  function authorizeExecutors(address[] memory executors) external;

  /**
   * @dev Remove addresses to the list of authorized executors
   * @param executors list of addresses to be removed as authorized executors
   **/
  function unauthorizeExecutors(address[] memory executors) external;

  /**
   * @dev Let the guardian abdicate from its priviledged rights
   **/
  function __abdicate() external;

  /**
   * @dev Getter of the current GovernanceStrategy address
   * @return The address of the current GovernanceStrategy contracts
   **/
  function getGovernanceStrategy() external view returns (address);

  /**
   * @dev Getter of the current Voting Delay (delay before a created proposal can be voted on)
   * Different from the voting duration
   * @return The voting delay in seconds
   **/
  function getVotingDelay() external view returns (uint256);

  /**
   * @dev Returns whether an address is an authorized executor
   * @param executor address to evaluate as authorized executor
   * @return true if authorized
   **/
  function isExecutorAuthorized(address executor) external view returns (bool);

  /**
   * @dev Getter the address of the guardian, that can mainly cancel proposals
   * @return The address of the guardian
   **/
  function getGuardian() external view returns (address);

  /**
   * @dev Getter of the proposal count (the current number of proposals ever created)
   * @return the proposal count
   **/
  function getProposalsCount() external view returns (uint256);

  /**
   * @dev Getter of a proposal by id
   * @param proposalId id of the proposal to get
   * @return the proposal as ProposalWithoutVotes memory object
   **/
  function getProposalById(uint256 proposalId) external view returns (ProposalWithoutVotes memory);

  /**
   * @dev Getter of the Vote of a voter about a proposal
   * Note: Vote is a struct: ({bool support, uint248 votingPower})
   * @param proposalId id of the proposal
   * @param voter address of the voter
   * @return The associated Vote memory object
   **/
  function getVoteOnProposal(uint256 proposalId, address voter) external view returns (Vote memory);

  /**
   * @dev Get the current state of a proposal
   * @param proposalId id of the proposal
   * @return The current state if the proposal
   **/
  function getProposalState(uint256 proposalId) external view returns (ProposalState);
}

library AaveGovernanceV2 {
  IAaveGovernanceV2 internal constant GOV =
    IAaveGovernanceV2(0xEC568fffba86c094cf06b22134B23074DFE2252c);

  IGovernanceStrategy public constant GOV_STRATEGY =
    IGovernanceStrategy(0xb7e383ef9B1E9189Fc0F71fb30af8aa14377429e);

  address public constant SHORT_EXECUTOR = 0xEE56e2B3D491590B5b31738cC34d5232F378a8D5;

  address public constant LONG_EXECUTOR = 0x79426A1c24B2978D90d7A5070a46C65B07bC4299;

  address public constant ARC_TIMELOCK = 0xAce1d11d836cb3F51Ef658FD4D353fFb3c301218;

  // https://github.com/aave/governance-crosschain-bridges
  address internal constant POLYGON_BRIDGE_EXECUTOR = 0xdc9A35B16DB4e126cFeDC41322b3a36454B1F772;

  address internal constant OPTIMISM_BRIDGE_EXECUTOR = 0x7d9103572bE58FfE99dc390E8246f02dcAe6f611;

  address internal constant ARBITRUM_BRIDGE_EXECUTOR = 0x7d9103572bE58FfE99dc390E8246f02dcAe6f611;

  address internal constant METIS_BRIDGE_EXECUTOR = 0x8EC77963068474a45016938Deb95E603Ca82a029;

  // https://github.com/bgd-labs/aave-v3-crosschain-listing-template/tree/master/src/contracts
  address internal constant CROSSCHAIN_FORWARDER_POLYGON =
    0x158a6bC04F0828318821baE797f50B0A1299d45b;

  address internal constant CROSSCHAIN_FORWARDER_OPTIMISM =
    0x5f5C02875a8e9B5A26fbd09040ABCfDeb2AA6711;

  address internal constant CROSSCHAIN_FORWARDER_ARBITRUM =
    0xd1B3E25fD7C8AE7CADDC6F71b461b79CD4ddcFa3;

  address internal constant CROSSCHAIN_FORWARDER_METIS = 0x2fE52eF191F0BE1D98459BdaD2F1d3160336C08f;
}

File 3 of 8 : IProposalValidator.sol
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.8.0;
pragma abicoder v2;

import {IAaveGovernanceV2} from 'aave-address-book/AaveGovernanceV2.sol';

interface IProposalValidator {
  /**
   * @dev Called to validate the cancellation of a proposal
   * @param governance Governance Contract
   * @param user Address of the proposal creator
   * @param blockNumber Block Number against which to make the test (e.g proposal creation block -1).
   * @return boolean, true if can be cancelled
   **/
  function validateProposalCancellation(
    IAaveGovernanceV2 governance,
    address user,
    uint256 blockNumber
  ) external view returns (bool);
}

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

import {AutomationCompatibleInterface} from 'chainlink-brownie-contracts/interfaces/AutomationCompatibleInterface.sol';

/**
 * @title IEthRobotKeeper
 * @author BGD Labs
 * @notice Defines the interface for the contract to automate actions on aave governance v2 proposals Eth Mainnet.
 */
interface IEthRobotKeeper is AutomationCompatibleInterface {
  /**
   * @dev Emitted when performUpkeep is called and no actions are executed.
   * @param id proposal id of failed action.
   * @param action action performed on the proposal which faled.
   * @param reason reason of the failed action.
   */
  event ActionFailed(uint256 indexed id, ProposalAction indexed action, string reason);

  /**
   * @dev Emitted when performUpkeep is called and actions are executed.
   * @param id proposal id of successful action.
   * @param action successful action performed on the proposal.
   */
  event ActionSucceeded(uint256 indexed id, ProposalAction indexed action);

  /**
   * @notice Actions that can be performed by the robot on the governance v2.
   * @param PerformQueue: performs queue action on the governance contract.
   * @param PerformExecute: performs execute action on the governance contract.
   * @param PerformCancel: performs cancel action on the governance contract.
   */
  enum ProposalAction {
    PerformQueue,
    PerformExecute,
    PerformCancel
  }

  /**
   * @notice holds action to be performed for a given proposalId.
   * @param id proposal id for which action needs to be performed.
   * @param action action to be perfomed for the proposalId.
   */
  struct ActionWithId {
    uint256 id;
    ProposalAction action;
  }

  /**
   * @notice method called by owner / robot guardian to disable/enabled automation on a specific proposalId.
   * @param proposalId proposalId for which we need to disable/enable automation.
   */
  function toggleDisableAutomationById(uint256 proposalId) external;

  /**
   * @notice method to check if automation for the proposalId is disabled/enabled.
   * @param proposalId proposalId to check if automation is disabled or not.
   * @return bool if automation for proposalId is disabled or not.
   */
  function isDisabled(uint256 proposalId) external view returns (bool);

  /**
   * @notice method to get the address of the aave governance v2 contract.
   * @return governance v2 contract address.
   */
  function GOVERNANCE_V2() external returns (address);

  /**
   * @notice method to get the maximum number of actions that can be performed by the keeper in one performUpkeep.
   * @return max number of actions.
   */
  function MAX_ACTIONS() external returns (uint256);

  /**
   * @notice method to get maximum number of proposals to check before the latest proposal, if an action could be performed upon.
   * @return max number of skips.
   */
  function MAX_SKIP() external returns (uint256);
}

File 5 of 8 : IAaveCLRobotOperator.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

/**
 * @title IAaveCLRobotOperator
 * @author BGD Labs
 * @notice Defines the interface for the robot operator contract to perform admin actions on the automation keepers.
 **/
interface IAaveCLRobotOperator {
  /**
   * @dev Emitted when a keeper is registered using the operator contract.
   * @param id id of the keeper registered.
   * @param upkeep address of the keeper contract.
   * @param amount amount of link the keeper has been registered with.
   */
  event KeeperRegistered(uint256 indexed id, address indexed upkeep, uint96 indexed amount);

  /**
   * @dev Emitted when a keeper is cancelled using the operator contract.
   * @param id id of the keeper cancelled.
   * @param upkeep address of the keeper contract.
   */
  event KeeperCancelled(uint256 indexed id, address indexed upkeep);

  /**
   * @dev Emitted when a keeper is already cancelled, and link is being withdrawn using the operator contract.
   * @param id id of the keeper to withdraw link from.
   * @param upkeep address of the keeper contract.
   * @param to address where link needs to be withdrawn to.
   */
  event LinkWithdrawn(uint256 indexed id, address indexed upkeep, address indexed to);

  /**
   * @dev Emitted when a keeper is refilled using the operator contract.
   * @param id id of the keeper which has been refilled.
   * @param from address which refilled the keeper.
   * @param amount amount of link which has been refilled for the keeper.
   */
  event KeeperRefilled(uint256 indexed id, address indexed from, uint96 indexed amount);

  /**
   * @dev Emitted when the link withdraw address has been changed of the keeper.
   * @param newWithdrawAddress address of the new withdraw address where link will be withdrawn to.
   */
  event WithdrawAddressSet(address indexed newWithdrawAddress);

  /**
   * @dev Emitted when gas limit is configured using the operator contract.
   * @param id id of the keeper which gas limit has been configured.
   * @param upkeep address of the keeper contract.
   * @param gasLimit max gas limit which has been configured for the keeper.
   */
  event GasLimitSet(uint256 indexed id, address indexed upkeep, uint32 indexed gasLimit);

  /**
   * @notice holds the keeper info registered via the operator.
   * @param upkeep address of the keeper contract registered.
   * @param name name of the registered keeper.
   */
  struct KeeperInfo {
    address upkeep;
    string name;
  }

  /**
   * @notice method called by owner to register the automation robot keeper.
   * @param name - name of keeper.
   * @param upkeepContract - upkeepContract of the keeper.
   * @param gasLimit - max gasLimit which the chainlink automation node can execute for the automation.
   * @param amountToFund - amount of link to fund the keeper with.
   * @return chainlink id for the registered keeper.
   **/
  function register(
    string memory name,
    address upkeepContract,
    uint32 gasLimit,
    uint96 amountToFund
  ) external returns (uint256);

  /**
   * @notice method called to refill the keeper.
   * @param id - id of the chainlink registered keeper to refill.
   * @param amount - amount of LINK to refill the keeper with.
   **/
  function refillKeeper(uint256 id, uint96 amount) external;

  /**
   * @notice method called by the owner to cancel the automation robot keeper.
   * @param id - id of the chainlink registered keeper to cancel.
   **/
  function cancel(uint256 id) external;

  /**
   * @notice method called permissionlessly to withdraw link of automation robot keeper to the withdraw address.
   *         this method should only be called after the automation robot keeper is cancelled.
   * @param id - id of the chainlink registered keeper to withdraw funds of.
   **/
  function withdrawLink(uint256 id) external;

  /**
   * @notice method called by owner / robot guardian to set the max gasLimit of upkeep robot keeper.
   * @param id - id of the chainlink registered keeper to set the gasLimit.
   * @param gasLimit max gasLimit which the chainlink automation node can execute.
   **/
  function setGasLimit(uint256 id, uint32 gasLimit) external;

  /**
   * @notice method called by owner to set the withdraw address when withdrawing excess link from the automation robot keeeper.
   * @param withdrawAddress withdraw address to withdaw link to.
   **/
  function setWithdrawAddress(address withdrawAddress) external;

  /**
   * @notice method to get the withdraw address for the robot operator contract.
   * @return withdraw address to send excess link to.
   **/
  function getWithdrawAddress() external view returns (address);

  /**
   * @notice method to get the keeper information registered via the operator.
   * @param id - id of the chainlink registered keeper.
   * @return Struct containing the following information about the keeper:
   *         - uint256 chainlink id of the registered keeper.
   *         - string name of the registered keeper.
   *         - address chainlink registry of the registered keeper.
   **/
  function getKeeperInfo(uint256 id) external view returns (KeeperInfo memory);

  /**
   * @notice method to get the address of ERC-677 link token.
   * @return link token address.
   */
  function LINK_TOKEN() external returns (address);

  /**
   * @notice method to get the address of chainlink keeper registry contract.
   * @return keeper registry address.
   */
  function KEEPER_REGISTRY() external returns (address);

  /**
   * @notice method to get the address of chainlink keeper registrar contract.
   * @return keeper registrar address.
   */
  function KEEPER_REGISTRAR() external returns (address);
}

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

pragma solidity ^0.8.0;

import './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.
 *
 * By default, the owner account will be the one that deploys the contract. This
 * can later be changed with {transferOwnership}.
 *
 * This module is used through inheritance. It will make available the modifier
 * `onlyOwner`, which can be applied to your functions to restrict their use to
 * the owner.
 */
abstract contract Ownable is Context {
  address private _owner;

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

  /**
   * @dev Initializes the contract setting the deployer as the initial owner.
   */
  constructor() {
    _transferOwnership(_msgSender());
  }

  /**
   * @dev Throws if called by any account other than the owner.
   */
  modifier onlyOwner() {
    _checkOwner();
    _;
  }

  /**
   * @dev Returns the address of the current owner.
   */
  function owner() public view virtual returns (address) {
    return _owner;
  }

  /**
   * @dev Throws if the sender is not the owner.
   */
  function _checkOwner() internal view virtual {
    require(owner() == _msgSender(), 'Ownable: caller is not the owner');
  }

  /**
   * @dev Leaves the contract without owner. It will not be possible to call
   * `onlyOwner` functions anymore. Can only be called by the current owner.
   *
   * NOTE: Renouncing ownership will leave the contract without an owner,
   * thereby removing any functionality that is only available to the owner.
   */
  function renounceOwnership() public virtual onlyOwner {
    _transferOwnership(address(0));
  }

  /**
   * @dev Transfers ownership of the contract to a new account (`newOwner`).
   * Can only be called by the current owner.
   */
  function transferOwnership(address newOwner) public virtual onlyOwner {
    require(newOwner != address(0), 'Ownable: new owner is the zero address');
    _transferOwnership(newOwner);
  }

  /**
   * @dev Transfers ownership of the contract to a new account (`newOwner`).
   * Internal function without access restriction.
   */
  function _transferOwnership(address newOwner) internal virtual {
    address oldOwner = _owner;
    _owner = newOwner;
    emit OwnershipTransferred(oldOwner, newOwner);
  }
}

File 7 of 8 : AutomationCompatibleInterface.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

interface AutomationCompatibleInterface {
  /**
   * @notice method that is simulated by the keepers to see if any work actually
   * needs to be performed. This method does does not actually need to be
   * executable, and since it is only ever simulated it can consume lots of gas.
   * @dev To ensure that it is never called, you may want to add the
   * cannotExecute modifier from KeeperBase to your implementation of this
   * method.
   * @param checkData specified in the upkeep registration so it is always the
   * same for a registered upkeep. This can easily be broken down into specific
   * arguments using `abi.decode`, so multiple upkeeps can be registered on the
   * same contract and easily differentiated by the contract.
   * @return upkeepNeeded boolean to indicate whether the keeper should call
   * performUpkeep or not.
   * @return performData bytes that the keeper should call performUpkeep with, if
   * upkeep is needed. If you would like to encode data to decode later, try
   * `abi.encode`.
   */
  function checkUpkeep(bytes calldata checkData) external returns (bool upkeepNeeded, bytes memory performData);

  /**
   * @notice method that is actually executed by the keepers, via the registry.
   * The data returned by the checkUpkeep simulation will be passed into
   * this method to actually be executed.
   * @dev The input to this method should not be trusted, and the caller of the
   * method should not even be restricted to any single registry. Anyone should
   * be able call it, and the input should be validated, there is no guarantee
   * that the data passed in is the performData returned from checkUpkeep. This
   * could happen due to malicious keepers, racing keepers, or simply a state
   * change while the performUpkeep transaction is waiting for confirmation.
   * Always validate the data passed in.
   * @param performData is the data which was passed back from the checkData
   * simulation. If it is encoded, it can easily be decoded into other types by
   * calling `abi.decode`. This data should not be trusted, and should be
   * validated against the contract's current state.
   */
  function performUpkeep(bytes calldata performData) external;
}

File 8 of 8 : Context.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)
// From commit https://github.com/OpenZeppelin/openzeppelin-contracts/commit/8b778fa20d6d76340c5fac1ed66c80273f05b95a

pragma solidity ^0.8.0;

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

Settings
{
  "remappings": [
    "@aave/core-v3/=lib/aave-address-book/lib/aave-v3-core/",
    "@aave/periphery-v3/=lib/aave-address-book/lib/aave-v3-periphery/",
    "aave-address-book/=lib/aave-address-book/src/",
    "aave-helpers/=lib/aave-helpers/src/",
    "aave-v3-core/=lib/aave-address-book/lib/aave-v3-core/",
    "aave-v3-periphery/=lib/aave-address-book/lib/aave-v3-periphery/",
    "chainlink-brownie-contracts/=lib/chainlink-brownie-contracts/contracts/src/v0.8/",
    "ds-test/=lib/forge-std/lib/ds-test/src/",
    "forge-std/=lib/forge-std/src/",
    "governance-crosschain-bridges/=lib/governance-crosschain-bridges/",
    "solidity-utils/=lib/solidity-utils/src/"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "metadata": {
    "bytecodeHash": "ipfs",
    "appendCBOR": true
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "evmVersion": "paris",
  "libraries": {}
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"governanceV2","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"NoActionCanBePerformed","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"enum IEthRobotKeeper.ProposalAction","name":"action","type":"uint8"},{"indexed":false,"internalType":"string","name":"reason","type":"string"}],"name":"ActionFailed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"enum IEthRobotKeeper.ProposalAction","name":"action","type":"uint8"}],"name":"ActionSucceeded","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"},{"inputs":[],"name":"GOVERNANCE_V2","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_ACTIONS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_SKIP","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"","type":"bytes"}],"name":"checkUpkeep","outputs":[{"internalType":"bool","name":"","type":"bool"},{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"}],"name":"isDisabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"performData","type":"bytes"}],"name":"performUpkeep","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"}],"name":"toggleDisableAutomationById","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}]

60a060405234801561001057600080fd5b5060405161181938038061181983398101604081905261002f91610099565b61003833610049565b6001600160a01b03166080526100c9565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000602082840312156100ab57600080fd5b81516001600160a01b03811681146100c257600080fd5b9392505050565b6080516116f66101236000396000818161017401528181610224015281816102d901528181610387015281816104f20152818161056a0152818161069c01528181610774015281816108030152610baa01526116f66000f3fe608060405234801561001057600080fd5b506004361061009e5760003560e01c806396def7091161006657806396def70914610121578063ad25ca2914610129578063dec367391461015c578063e9e579a11461016f578063f2fde38b1461019657600080fd5b80631f584c69146100a35780634585e33b146100be5780636e04ff0d146100d3578063715018a6146100f45780638da5cb5b146100fc575b600080fd5b6100ab601481565b6040519081526020015b60405180910390f35b6100d16100cc366004610de0565b6101a9565b005b6100e66100e1366004610de0565b610651565b6040516100b5929190610ea2565b6100d1610a7b565b6000546001600160a01b03165b6040516001600160a01b0390911681526020016100b5565b6100ab601981565b61014c610137366004610ec5565b60009081526001602052604090205460ff1690565b60405190151581526020016100b5565b6100d161016a366004610ec5565b610a8f565b6101097f000000000000000000000000000000000000000000000000000000000000000081565b6100d16101a4366004610ef3565b610ab7565b60006101b782840184610fce565b80519091506000905b801561062c576000836101d46001846110b5565b815181106101e4576101e46110c8565b602002602001015160000151905060008460018461020291906110b5565b81518110610212576102126110c8565b602002602001015160200151905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316633656de21846040518263ffffffff1660e01b815260040161027091815260200190565b600060405180830381865afa15801561028d573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526102b59190810190611353565b604051639080936f60e01b8152600481018590529091506000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690639080936f90602401602060405180830381865afa158015610320573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061034491906114ff565b9050600283600281111561035a5761035a611520565b14801561036c575061036c8183610b35565b156104b2576040516340e58ee560e01b8152600481018590527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906340e58ee5906024015b600060405180830381600087803b1580156103d457600080fd5b505af19250505080156103e5575060015b61046c576103f1611536565b806308c379a0036104605750610405611552565b806104105750610462565b83600281111561042257610422611520565b857f303225627d4799c73fd19f2bb5d7c14c9653ea7b7f14cd96817ac37dbe55a7848360405161045291906115dc565b60405180910390a350610615565b505b3d6000803e3d6000fd5b6001955082600281111561048257610482611520565b60405185907f1d356dc5da7bf4f74d415f1adff04022530e2418a8e8458e4fa0dca4cec1425090600090a3610615565b60008360028111156104c6576104c6611520565b1480156104d757506104d781610c5b565b156105295760405163ddf0b00960e01b8152600481018590527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063ddf0b009906024016103ba565b600183600281111561053d5761053d611520565b14801561054f575061054f8183610c78565b156106155760405163fe0d94c160e01b8152600481018590527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063fe0d94c190602401600060405180830381600087803b1580156105b657600080fd5b505af19250505080156105c7575060015b6105d3576103f1611536565b600195508260028111156105e9576105e9611520565b60405185907f1d356dc5da7bf4f74d415f1adff04022530e2418a8e8458e4fa0dca4cec1425090600090a35b505050508080610624906115ef565b9150506101c0565b508061064b57604051630e37ffa560e41b815260040160405180910390fd5b50505050565b60408051601980825261034082019092526000916060918391816020015b604080518082019091526000808252602082015281526020019060019003908161066f57905050905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166398e527d36040518163ffffffff1660e01b8152600401602060405180830381865afa1580156106f8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061071c9190611606565b90506000805b8215801590610732575060148211155b801561073e5750601981105b15610a1c5760006107506001856110b5565b604051639080936f60e01b8152600481018290529091506000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690639080936f90602401602060405180830381865afa1580156107bb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107df91906114ff565b604051633656de2160e01b8152600481018490529091506000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690633656de2190602401600060405180830381865afa15801561084a573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526108729190810190611353565b60008481526001602052604090205490915060ff16610a075761089482610cb6565b156108ab57846108a38161161f565b955050610a07565b6108b58282610b35565b1561093657828785815181106108cd576108cd6110c8565b6020026020010151600001818152505060028785815181106108f1576108f16110c8565b602002602001015160200190600281111561090e5761090e611520565b9081600281111561092157610921611520565b9052508361092e8161161f565b945050610a02565b61093f82610c5b565b1561097b5782878581518110610957576109576110c8565b6020026020010151600001818152505060008785815181106108f1576108f16110c8565b6109858282610c78565b15610a02578287858151811061099d5761099d6110c8565b6020026020010151600001818152505060018785815181106109c1576109c16110c8565b60200260200101516020019060028111156109de576109de611520565b908160028111156109f1576109f1611520565b905250836109fe8161161f565b9450505b600094505b85610a11816115ef565b965050505050610722565b8015610a5957808452600084604051602001610a389190611638565b60408051601f19818403018152919052600197509550610a74945050505050565b60006040518060200160405280600081525095509550505050505b9250929050565b610a83610d36565b610a8d6000610d90565b565b610a97610d36565b6000908152600160205260409020805460ff19811660ff90911615179055565b610abf610d36565b6001600160a01b038116610b295760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084015b60405180910390fd5b610b3281610d90565b50565b60408101516000906006846007811115610b5157610b51611520565b1480610b6e57506001846007811115610b6c57610b6c611520565b145b80610b8a57506007846007811115610b8857610b88611520565b145b15610b99576000915050610c55565b806001600160a01b03166331a7bc417f00000000000000000000000000000000000000000000000000000000000000008560200151600143610bdb91906110b5565b6040516001600160e01b031960e086901b1681526001600160a01b0393841660048201529290911660248301526044820152606401602060405180830381865afa158015610c2d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c5191906116a5565b9150505b92915050565b60006004826007811115610c7157610c71611520565b1492915050565b60006005836007811115610c8e57610c8e611520565b148015610ca057508161014001514210155b15610cad57506001610c55565b50600092915050565b60006007826007811115610ccc57610ccc611520565b1480610ce957506001826007811115610ce757610ce7611520565b145b80610d0557506006826007811115610d0357610d03611520565b145b80610d2157506003826007811115610d1f57610d1f611520565b145b15610d2e57506001919050565b506000919050565b6000546001600160a01b03163314610a8d5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610b20565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60008060208385031215610df357600080fd5b823567ffffffffffffffff80821115610e0b57600080fd5b818501915085601f830112610e1f57600080fd5b813581811115610e2e57600080fd5b866020828501011115610e4057600080fd5b60209290920196919550909350505050565b60005b83811015610e6d578181015183820152602001610e55565b50506000910152565b60008151808452610e8e816020860160208601610e52565b601f01601f19169290920160200192915050565b8215158152604060208201526000610ebd6040830184610e76565b949350505050565b600060208284031215610ed757600080fd5b5035919050565b6001600160a01b0381168114610b3257600080fd5b600060208284031215610f0557600080fd5b8135610f1081610ede565b9392505050565b634e487b7160e01b600052604160045260246000fd5b6040810181811067ffffffffffffffff82111715610f4d57610f4d610f17565b60405250565b601f8201601f1916810167ffffffffffffffff81118282101715610f7957610f79610f17565b6040525050565b604051610220810167ffffffffffffffff81118282101715610fa457610fa4610f17565b60405290565b600067ffffffffffffffff821115610fc457610fc4610f17565b5060051b60200190565b60006020808385031215610fe157600080fd5b823567ffffffffffffffff811115610ff857600080fd5b8301601f8101851361100957600080fd5b803561101481610faa565b604080516110228382610f53565b83815260069390931b840185019285810192508884111561104257600080fd5b938501935b838510156110935781858a03121561105f5760008081fd5b815161106a81610f2d565b8535815286860135600381106110805760008081fd5b8188015283529381019391850191611047565b98975050505050505050565b634e487b7160e01b600052601160045260246000fd5b81810381811115610c5557610c5561109f565b634e487b7160e01b600052603260045260246000fd5b80516110e981610ede565b919050565b600082601f8301126110ff57600080fd5b8151602061110c82610faa565b6040516111198282610f53565b83815260059390931b850182019282810191508684111561113957600080fd5b8286015b8481101561115d57805161115081610ede565b835291830191830161113d565b509695505050505050565b600082601f83011261117957600080fd5b8151602061118682610faa565b6040516111938282610f53565b83815260059390931b85018201928281019150868411156111b357600080fd5b8286015b8481101561115d57805183529183019183016111b7565b600067ffffffffffffffff8311156111e8576111e8610f17565b6040516111ff601f8501601f191660200182610f53565b80915083815284848401111561121457600080fd5b611222846020830185610e52565b509392505050565b600082601f83011261123b57600080fd5b8151602061124882610faa565b604080516112568382610f53565b84815260059490941b860183019383810192508785111561127657600080fd5b8387015b858110156112ca57805167ffffffffffffffff81111561129a5760008081fd5b8801603f81018a136112ac5760008081fd5b6112bc8a878301518684016111ce565b85525092840192840161127a565b50979650505050505050565b805180151581146110e957600080fd5b600082601f8301126112f757600080fd5b8151602061130482610faa565b6040516113118282610f53565b83815260059390931b850182019282810191508684111561133157600080fd5b8286015b8481101561115d57611346816112d6565b8352918301918301611335565b60006020828403121561136557600080fd5b815167ffffffffffffffff8082111561137d57600080fd5b90830190610220828603121561139257600080fd5b61139a610f80565b825181526113aa602084016110de565b60208201526113bb604084016110de565b60408201526060830151828111156113d257600080fd5b6113de878286016110ee565b6060830152506080830151828111156113f657600080fd5b61140287828601611168565b60808301525060a08301518281111561141a57600080fd5b6114268782860161122a565b60a08301525060c08301518281111561143e57600080fd5b61144a8782860161122a565b60c08301525060e08301518281111561146257600080fd5b61146e878286016112e6565b60e083015250610100838101519082015261012080840151908201526101408084015190820152610160808401519082015261018080840151908201526101a091506114bb8284016112d6565b828201526101c091506114cf8284016112d6565b828201526101e091506114e38284016110de565b9181019190915261020091820151918101919091529392505050565b60006020828403121561151157600080fd5b815160088110610f1057600080fd5b634e487b7160e01b600052602160045260246000fd5b600060033d111561154f5760046000803e5060005160e01c5b90565b600060443d10156115605790565b6040516003193d81016004833e81513d67ffffffffffffffff816024840111818411171561159057505050505090565b82850191508151818111156115a85750505050505090565b843d87010160208285010111156115c25750505050505090565b6115d160208286010187610f53565b509095945050505050565b602081526000610f106020830184610e76565b6000816115fe576115fe61109f565b506000190190565b60006020828403121561161857600080fd5b5051919050565b6000600182016116315761163161109f565b5060010190565b60208082528251828201819052600091906040908185019086840185805b83811015611697578251805186528701516003811061168357634e487b7160e01b83526021600452602483fd5b858801529385019391860191600101611656565b509298975050505050505050565b6000602082840312156116b757600080fd5b610f10826112d656fea26469706673582212207e54d80ec4d5a808043632a0fcafbb176ffdcd3812567627afb650d67b2126f264736f6c63430008120033000000000000000000000000ec568fffba86c094cf06b22134b23074dfe2252c

Deployed Bytecode

0x608060405234801561001057600080fd5b506004361061009e5760003560e01c806396def7091161006657806396def70914610121578063ad25ca2914610129578063dec367391461015c578063e9e579a11461016f578063f2fde38b1461019657600080fd5b80631f584c69146100a35780634585e33b146100be5780636e04ff0d146100d3578063715018a6146100f45780638da5cb5b146100fc575b600080fd5b6100ab601481565b6040519081526020015b60405180910390f35b6100d16100cc366004610de0565b6101a9565b005b6100e66100e1366004610de0565b610651565b6040516100b5929190610ea2565b6100d1610a7b565b6000546001600160a01b03165b6040516001600160a01b0390911681526020016100b5565b6100ab601981565b61014c610137366004610ec5565b60009081526001602052604090205460ff1690565b60405190151581526020016100b5565b6100d161016a366004610ec5565b610a8f565b6101097f000000000000000000000000ec568fffba86c094cf06b22134b23074dfe2252c81565b6100d16101a4366004610ef3565b610ab7565b60006101b782840184610fce565b80519091506000905b801561062c576000836101d46001846110b5565b815181106101e4576101e46110c8565b602002602001015160000151905060008460018461020291906110b5565b81518110610212576102126110c8565b602002602001015160200151905060007f000000000000000000000000ec568fffba86c094cf06b22134b23074dfe2252c6001600160a01b0316633656de21846040518263ffffffff1660e01b815260040161027091815260200190565b600060405180830381865afa15801561028d573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526102b59190810190611353565b604051639080936f60e01b8152600481018590529091506000906001600160a01b037f000000000000000000000000ec568fffba86c094cf06b22134b23074dfe2252c1690639080936f90602401602060405180830381865afa158015610320573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061034491906114ff565b9050600283600281111561035a5761035a611520565b14801561036c575061036c8183610b35565b156104b2576040516340e58ee560e01b8152600481018590527f000000000000000000000000ec568fffba86c094cf06b22134b23074dfe2252c6001600160a01b0316906340e58ee5906024015b600060405180830381600087803b1580156103d457600080fd5b505af19250505080156103e5575060015b61046c576103f1611536565b806308c379a0036104605750610405611552565b806104105750610462565b83600281111561042257610422611520565b857f303225627d4799c73fd19f2bb5d7c14c9653ea7b7f14cd96817ac37dbe55a7848360405161045291906115dc565b60405180910390a350610615565b505b3d6000803e3d6000fd5b6001955082600281111561048257610482611520565b60405185907f1d356dc5da7bf4f74d415f1adff04022530e2418a8e8458e4fa0dca4cec1425090600090a3610615565b60008360028111156104c6576104c6611520565b1480156104d757506104d781610c5b565b156105295760405163ddf0b00960e01b8152600481018590527f000000000000000000000000ec568fffba86c094cf06b22134b23074dfe2252c6001600160a01b03169063ddf0b009906024016103ba565b600183600281111561053d5761053d611520565b14801561054f575061054f8183610c78565b156106155760405163fe0d94c160e01b8152600481018590527f000000000000000000000000ec568fffba86c094cf06b22134b23074dfe2252c6001600160a01b03169063fe0d94c190602401600060405180830381600087803b1580156105b657600080fd5b505af19250505080156105c7575060015b6105d3576103f1611536565b600195508260028111156105e9576105e9611520565b60405185907f1d356dc5da7bf4f74d415f1adff04022530e2418a8e8458e4fa0dca4cec1425090600090a35b505050508080610624906115ef565b9150506101c0565b508061064b57604051630e37ffa560e41b815260040160405180910390fd5b50505050565b60408051601980825261034082019092526000916060918391816020015b604080518082019091526000808252602082015281526020019060019003908161066f57905050905060007f000000000000000000000000ec568fffba86c094cf06b22134b23074dfe2252c6001600160a01b03166398e527d36040518163ffffffff1660e01b8152600401602060405180830381865afa1580156106f8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061071c9190611606565b90506000805b8215801590610732575060148211155b801561073e5750601981105b15610a1c5760006107506001856110b5565b604051639080936f60e01b8152600481018290529091506000906001600160a01b037f000000000000000000000000ec568fffba86c094cf06b22134b23074dfe2252c1690639080936f90602401602060405180830381865afa1580156107bb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107df91906114ff565b604051633656de2160e01b8152600481018490529091506000906001600160a01b037f000000000000000000000000ec568fffba86c094cf06b22134b23074dfe2252c1690633656de2190602401600060405180830381865afa15801561084a573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526108729190810190611353565b60008481526001602052604090205490915060ff16610a075761089482610cb6565b156108ab57846108a38161161f565b955050610a07565b6108b58282610b35565b1561093657828785815181106108cd576108cd6110c8565b6020026020010151600001818152505060028785815181106108f1576108f16110c8565b602002602001015160200190600281111561090e5761090e611520565b9081600281111561092157610921611520565b9052508361092e8161161f565b945050610a02565b61093f82610c5b565b1561097b5782878581518110610957576109576110c8565b6020026020010151600001818152505060008785815181106108f1576108f16110c8565b6109858282610c78565b15610a02578287858151811061099d5761099d6110c8565b6020026020010151600001818152505060018785815181106109c1576109c16110c8565b60200260200101516020019060028111156109de576109de611520565b908160028111156109f1576109f1611520565b905250836109fe8161161f565b9450505b600094505b85610a11816115ef565b965050505050610722565b8015610a5957808452600084604051602001610a389190611638565b60408051601f19818403018152919052600197509550610a74945050505050565b60006040518060200160405280600081525095509550505050505b9250929050565b610a83610d36565b610a8d6000610d90565b565b610a97610d36565b6000908152600160205260409020805460ff19811660ff90911615179055565b610abf610d36565b6001600160a01b038116610b295760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084015b60405180910390fd5b610b3281610d90565b50565b60408101516000906006846007811115610b5157610b51611520565b1480610b6e57506001846007811115610b6c57610b6c611520565b145b80610b8a57506007846007811115610b8857610b88611520565b145b15610b99576000915050610c55565b806001600160a01b03166331a7bc417f000000000000000000000000ec568fffba86c094cf06b22134b23074dfe2252c8560200151600143610bdb91906110b5565b6040516001600160e01b031960e086901b1681526001600160a01b0393841660048201529290911660248301526044820152606401602060405180830381865afa158015610c2d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c5191906116a5565b9150505b92915050565b60006004826007811115610c7157610c71611520565b1492915050565b60006005836007811115610c8e57610c8e611520565b148015610ca057508161014001514210155b15610cad57506001610c55565b50600092915050565b60006007826007811115610ccc57610ccc611520565b1480610ce957506001826007811115610ce757610ce7611520565b145b80610d0557506006826007811115610d0357610d03611520565b145b80610d2157506003826007811115610d1f57610d1f611520565b145b15610d2e57506001919050565b506000919050565b6000546001600160a01b03163314610a8d5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610b20565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60008060208385031215610df357600080fd5b823567ffffffffffffffff80821115610e0b57600080fd5b818501915085601f830112610e1f57600080fd5b813581811115610e2e57600080fd5b866020828501011115610e4057600080fd5b60209290920196919550909350505050565b60005b83811015610e6d578181015183820152602001610e55565b50506000910152565b60008151808452610e8e816020860160208601610e52565b601f01601f19169290920160200192915050565b8215158152604060208201526000610ebd6040830184610e76565b949350505050565b600060208284031215610ed757600080fd5b5035919050565b6001600160a01b0381168114610b3257600080fd5b600060208284031215610f0557600080fd5b8135610f1081610ede565b9392505050565b634e487b7160e01b600052604160045260246000fd5b6040810181811067ffffffffffffffff82111715610f4d57610f4d610f17565b60405250565b601f8201601f1916810167ffffffffffffffff81118282101715610f7957610f79610f17565b6040525050565b604051610220810167ffffffffffffffff81118282101715610fa457610fa4610f17565b60405290565b600067ffffffffffffffff821115610fc457610fc4610f17565b5060051b60200190565b60006020808385031215610fe157600080fd5b823567ffffffffffffffff811115610ff857600080fd5b8301601f8101851361100957600080fd5b803561101481610faa565b604080516110228382610f53565b83815260069390931b840185019285810192508884111561104257600080fd5b938501935b838510156110935781858a03121561105f5760008081fd5b815161106a81610f2d565b8535815286860135600381106110805760008081fd5b8188015283529381019391850191611047565b98975050505050505050565b634e487b7160e01b600052601160045260246000fd5b81810381811115610c5557610c5561109f565b634e487b7160e01b600052603260045260246000fd5b80516110e981610ede565b919050565b600082601f8301126110ff57600080fd5b8151602061110c82610faa565b6040516111198282610f53565b83815260059390931b850182019282810191508684111561113957600080fd5b8286015b8481101561115d57805161115081610ede565b835291830191830161113d565b509695505050505050565b600082601f83011261117957600080fd5b8151602061118682610faa565b6040516111938282610f53565b83815260059390931b85018201928281019150868411156111b357600080fd5b8286015b8481101561115d57805183529183019183016111b7565b600067ffffffffffffffff8311156111e8576111e8610f17565b6040516111ff601f8501601f191660200182610f53565b80915083815284848401111561121457600080fd5b611222846020830185610e52565b509392505050565b600082601f83011261123b57600080fd5b8151602061124882610faa565b604080516112568382610f53565b84815260059490941b860183019383810192508785111561127657600080fd5b8387015b858110156112ca57805167ffffffffffffffff81111561129a5760008081fd5b8801603f81018a136112ac5760008081fd5b6112bc8a878301518684016111ce565b85525092840192840161127a565b50979650505050505050565b805180151581146110e957600080fd5b600082601f8301126112f757600080fd5b8151602061130482610faa565b6040516113118282610f53565b83815260059390931b850182019282810191508684111561133157600080fd5b8286015b8481101561115d57611346816112d6565b8352918301918301611335565b60006020828403121561136557600080fd5b815167ffffffffffffffff8082111561137d57600080fd5b90830190610220828603121561139257600080fd5b61139a610f80565b825181526113aa602084016110de565b60208201526113bb604084016110de565b60408201526060830151828111156113d257600080fd5b6113de878286016110ee565b6060830152506080830151828111156113f657600080fd5b61140287828601611168565b60808301525060a08301518281111561141a57600080fd5b6114268782860161122a565b60a08301525060c08301518281111561143e57600080fd5b61144a8782860161122a565b60c08301525060e08301518281111561146257600080fd5b61146e878286016112e6565b60e083015250610100838101519082015261012080840151908201526101408084015190820152610160808401519082015261018080840151908201526101a091506114bb8284016112d6565b828201526101c091506114cf8284016112d6565b828201526101e091506114e38284016110de565b9181019190915261020091820151918101919091529392505050565b60006020828403121561151157600080fd5b815160088110610f1057600080fd5b634e487b7160e01b600052602160045260246000fd5b600060033d111561154f5760046000803e5060005160e01c5b90565b600060443d10156115605790565b6040516003193d81016004833e81513d67ffffffffffffffff816024840111818411171561159057505050505090565b82850191508151818111156115a85750505050505090565b843d87010160208285010111156115c25750505050505090565b6115d160208286010187610f53565b509095945050505050565b602081526000610f106020830184610e76565b6000816115fe576115fe61109f565b506000190190565b60006020828403121561161857600080fd5b5051919050565b6000600182016116315761163161109f565b5060010190565b60208082528251828201819052600091906040908185019086840185805b83811015611697578251805186528701516003811061168357634e487b7160e01b83526021600452602483fd5b858801529385019391860191600101611656565b509298975050505050505050565b6000602082840312156116b757600080fd5b610f10826112d656fea26469706673582212207e54d80ec4d5a808043632a0fcafbb176ffdcd3812567627afb650d67b2126f264736f6c63430008120033

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

000000000000000000000000ec568fffba86c094cf06b22134b23074dfe2252c

-----Decoded View---------------
Arg [0] : governanceV2 (address): 0xEC568fffba86c094cf06b22134B23074DFE2252c

-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 000000000000000000000000ec568fffba86c094cf06b22134b23074dfe2252c


Block Transaction Difficulty 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
Loading...
Loading
[ Download: CSV Export  ]

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