ETH Price: $3,461.40 (+1.87%)
Gas: 11 Gwei

Contract

0xF909B6E74F8DF227b71AF79e79a3A6652ec32F2d
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To

There are no matching entries

Please try again later

Latest 1 internal transaction

Advanced mode:
Parent Transaction Hash Block From To
202190662024-07-02 13:15:2315 days ago1719926123  Contract Creation0 ETH
Loading...
Loading

Minimal Proxy Contract for 0x99137f260e50b48e68aefb2dc84082c862df47b2

Contract Name:
SwapOwnerModule

Compiler Version
v0.8.20+commit.a1b79de6

Optimization Enabled:
Yes with 1000 runs

Other Settings:
paris EvmVersion

Contract Source Code (Solidity Standard Json-Input format)

File 1 of 14 : SwapOwnerModule.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.18;

import {Module, Enum} from "@gnosis.pm/zodiac/contracts/core/Module.sol";
import {IOwnerManager} from "./interface/IOwnerManager.sol";
import {IDelay} from "./interface/IDelay.sol";

contract SwapOwnerModule is Module {
    event SwapOwnerSetup(
        address indexed initiator,
        address indexed owner,
        address indexed avatar,
        address target
    );
    event SwapOwner(address indexed oldOwner, address indexed newOwner);
    mapping(uint256 => uint256) public swapNonceToDelayQueueNonce;
    uint256 public swapTxNonce;

    /// @param _avatar Address of the avatar (e.g. a Gnosis Safe) Avatars must expose an interface like IAvatar.sol.
    /// @param _target Address of the contract that will call execTransactionFromModule function (Delay modifier)
    /// @param _owner Address of the owner
    constructor(address _target, address _avatar, address _owner) {
        bytes memory initParams = abi.encode(_target, _avatar, _owner);
        setUp(initParams);
    }

    /// @notice Public setup function to allow deployment via factory / proxy pattern
    /// @param initializeParams ABI encoded parameters (see constructor)
    function setUp(bytes memory initializeParams) public override initializer {
        (address _target, address _avatar, address _owner) = abi.decode(
            initializeParams,
            (address, address, address)
        );
        require(_avatar != address(0), "Avatar can not be zero address");
        require(_target != address(0), "Target can not be zero address");
        require(_owner != address(0), "Owner can not be zero address");
        __Ownable_init(_owner);
        avatar = _avatar;
        target = _target;

        emit SwapOwnerSetup(msg.sender, _target, _avatar, _owner);
        emit AvatarSet(address(0), _avatar);
        emit TargetSet(address(0), _target);
    }

    /**
     * @notice Craft a payload that will call the function swapOwner in the Safe contract which replaces the owner `oldOwner` in the Safe with `newOwner`.
     * @dev This can only be done via a Safe transaction.
     * @dev Validation is done
     * @dev https://github.com/safe-global/safe-contracts/blob/0acdd35a203299585438f53885df630f9d486a86/contracts/base/OwnerManager.sol#L99
     * @param prevOwner Owner that pointed to the owner to be replaced in the linked list
     * @param oldOwner Owner address to be replaced.
     * @param newOwner New owner address.
     */
    function startRecovery(
        address prevOwner,
        address oldOwner,
        address newOwner
    ) external onlyOwner {
        IDelay delay = IDelay(target);
        // Nonce given by the delay to the current recovery
        uint256 delayQueueNonce = delay.queueNonce();

        if (swapTxNonce > 0) {
            _checkLastQueuedTx(delay);
        }

        require(
            _swapOwner(prevOwner, oldOwner, newOwner),
            "Module transaction failed"
        );
        //Map the swapNonce to the delay nonce to be able to find the transaction in the delay contract
        swapNonceToDelayQueueNonce[swapTxNonce] = delayQueueNonce;
        swapTxNonce++;
        emit SwapOwner(oldOwner, newOwner);
    }

    function _checkLastQueuedTx(IDelay delay) internal view {
        // Current executable nonce from delay
        uint256 delayTxNonce = delay.txNonce();
        uint256 txCooldown = delay.txCooldown();
        uint256 txExpiration = delay.txExpiration();
        // Nonce given by the delay to the last recovery queued
        uint256 lastTxQueueNonce = swapNonceToDelayQueueNonce[swapTxNonce - 1];
        //Check if transaction has not been executed and if a tx has ever been queued
        if (lastTxQueueNonce >= delayTxNonce) {
            uint256 lastTxCreatedAt = delay.txCreatedAt(lastTxQueueNonce);
            //Require the cooldown period to have passed
            require(
                block.timestamp - lastTxCreatedAt > txCooldown,
                "Cooldown period has not passed"
            );
            //Check if transaction has an expiration
            if (txExpiration > 0) {
                //Require the transaction to be expired
                require(
                    lastTxCreatedAt + txCooldown + txExpiration <
                        block.timestamp,
                    "Transaction has not expired"
                );
            } else {
                revert("A recovery is pending execution");
            }
        }
    }

    function _swapOwner(
        address prevOwner,
        address oldOwner,
        address newOwner
    ) internal returns (bool) {
        return
            exec(
                // avatar, in our case the safe will execute the below function
                avatar,
                0,
                abi.encodeCall(
                    IOwnerManager.swapOwner,
                    (prevOwner, oldOwner, newOwner)
                ),
                Enum.Operation.Call
            );
    }
}

File 2 of 14 : Enum.sol
// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.7.0 <0.9.0;

/// @title Enum - Collection of enums
/// @author Richard Meissner - <[email protected]>
contract Enum {
    enum Operation {Call, DelegateCall}
}

File 3 of 14 : Modifier.sol
// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.7.0 <0.9.0;

import {Enum} from "@gnosis.pm/safe-contracts/contracts/common/Enum.sol";
import {ExecutionTracker} from "../signature/ExecutionTracker.sol";
import {IAvatar} from "../interfaces/IAvatar.sol";
import {Module} from "./Module.sol";
import {SignatureChecker} from "../signature/SignatureChecker.sol";

/// @title Modifier Interface - A contract that sits between a Module and an Avatar and enforce some additional logic.
abstract contract Modifier is
  Module,
  ExecutionTracker,
  SignatureChecker,
  IAvatar
{
  address internal constant SENTINEL_MODULES = address(0x1);
  /// Mapping of modules.
  mapping(address => address) internal modules;

  /// `sender` is not an authorized module.
  /// @param sender The address of the sender.
  error NotAuthorized(address sender);

  /// `module` is invalid.
  error InvalidModule(address module);

  /// `pageSize` is invalid.
  error InvalidPageSize();

  /// `module` is already disabled.
  error AlreadyDisabledModule(address module);

  /// `module` is already enabled.
  error AlreadyEnabledModule(address module);

  /// @dev `setModules()` was already called.
  error SetupModulesAlreadyCalled();

  /*
    --------------------------------------------------
    You must override both of the following virtual functions,
    execTransactionFromModule() and execTransactionFromModuleReturnData().
    It is recommended that implementations of both functions make use the 
    onlyModule modifier.
    */

  /// @dev Passes a transaction to the modifier.
  /// @notice Can only be called by enabled modules.
  /// @param to Destination address of module transaction.
  /// @param value Ether value of module transaction.
  /// @param data Data payload of module transaction.
  /// @param operation Operation type of module transaction.
  function execTransactionFromModule(
    address to,
    uint256 value,
    bytes calldata data,
    Enum.Operation operation
  ) public virtual returns (bool success);

  /// @dev Passes a transaction to the modifier, expects return data.
  /// @notice Can only be called by enabled modules.
  /// @param to Destination address of module transaction.
  /// @param value Ether value of module transaction.
  /// @param data Data payload of module transaction.
  /// @param operation Operation type of module transaction.
  function execTransactionFromModuleReturnData(
    address to,
    uint256 value,
    bytes calldata data,
    Enum.Operation operation
  ) public virtual returns (bool success, bytes memory returnData);

  /*
    --------------------------------------------------
    */

  modifier moduleOnly() {
    if (modules[msg.sender] == address(0)) {
      (bytes32 hash, address signer) = moduleTxSignedBy();

      // is the signer a module?
      if (modules[signer] == address(0)) {
        revert NotAuthorized(msg.sender);
      }

      // is the provided signature fresh?
      if (consumed[signer][hash]) {
        revert HashAlreadyConsumed(hash);
      }

      consumed[signer][hash] = true;
      emit HashExecuted(hash);
    }

    _;
  }

  function sentOrSignedByModule() internal view returns (address) {
    if (modules[msg.sender] != address(0)) {
      return msg.sender;
    }

    (, address signer) = moduleTxSignedBy();
    if (modules[signer] != address(0)) {
      return signer;
    }

    return address(0);
  }

  /// @dev Disables a module on the modifier.
  /// @notice This can only be called by the owner.
  /// @param prevModule Module that pointed to the module to be removed in the linked list.
  /// @param module Module to be removed.
  function disableModule(
    address prevModule,
    address module
  ) public override onlyOwner {
    if (module == address(0) || module == SENTINEL_MODULES)
      revert InvalidModule(module);
    if (modules[prevModule] != module) revert AlreadyDisabledModule(module);
    modules[prevModule] = modules[module];
    modules[module] = address(0);
    emit DisabledModule(module);
  }

  /// @dev Enables a module that can add transactions to the queue
  /// @param module Address of the module to be enabled
  /// @notice This can only be called by the owner
  function enableModule(address module) public override onlyOwner {
    if (module == address(0) || module == SENTINEL_MODULES)
      revert InvalidModule(module);
    if (modules[module] != address(0)) revert AlreadyEnabledModule(module);
    modules[module] = modules[SENTINEL_MODULES];
    modules[SENTINEL_MODULES] = module;
    emit EnabledModule(module);
  }

  /// @dev Returns if an module is enabled
  /// @return True if the module is enabled
  function isModuleEnabled(
    address _module
  ) public view override returns (bool) {
    return SENTINEL_MODULES != _module && modules[_module] != address(0);
  }

  /// @dev Returns array of modules.
  ///      If all entries fit into a single page, the next pointer will be 0x1.
  ///      If another page is present, next will be the last element of the returned array.
  /// @param start Start of the page. Has to be a module or start pointer (0x1 address)
  /// @param pageSize Maximum number of modules that should be returned. Has to be > 0
  /// @return array Array of modules.
  /// @return next Start of the next page.
  function getModulesPaginated(
    address start,
    uint256 pageSize
  ) external view override returns (address[] memory array, address next) {
    if (start != SENTINEL_MODULES && !isModuleEnabled(start)) {
      revert InvalidModule(start);
    }
    if (pageSize == 0) {
      revert InvalidPageSize();
    }

    // Init array with max page size
    array = new address[](pageSize);

    // Populate return array
    uint256 moduleCount = 0;
    next = modules[start];
    while (
      next != address(0) && next != SENTINEL_MODULES && moduleCount < pageSize
    ) {
      array[moduleCount] = next;
      next = modules[next];
      moduleCount++;
    }

    // Because of the argument validation we can assume that
    // the `currentModule` will always be either a module address
    // or sentinel address (aka the end). If we haven't reached the end
    // inside the loop, we need to set the next pointer to the last element
    // because it skipped over to the next module which is neither included
    // in the current page nor won't be included in the next one
    // if you pass it as a start.
    if (next != SENTINEL_MODULES) {
      next = array[moduleCount - 1];
    }
    // Set correct size of returned array
    // solhint-disable-next-line no-inline-assembly
    assembly {
      mstore(array, moduleCount)
    }
  }

  /// @dev Initializes the modules linked list.
  /// @notice Should be called as part of the `setUp` / initializing function and can only be called once.
  function setupModules() internal {
    if (modules[SENTINEL_MODULES] != address(0))
      revert SetupModulesAlreadyCalled();
    modules[SENTINEL_MODULES] = SENTINEL_MODULES;
  }
}

File 4 of 14 : Module.sol
// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.7.0 <0.9.0;

import {Enum} from "@gnosis.pm/safe-contracts/contracts/common/Enum.sol";

import {FactoryFriendly} from "../factory/FactoryFriendly.sol";
import {IAvatar} from "../interfaces/IAvatar.sol";

/// @title Module Interface - A contract that can pass messages to a Module Manager contract if enabled by that contract.
abstract contract Module is FactoryFriendly {
  /// @dev Address that will ultimately execute function calls.
  address public avatar;
  /// @dev Address that this module will pass transactions to.
  address public target;

  /// @dev Emitted each time the avatar is set.
  event AvatarSet(address indexed previousAvatar, address indexed newAvatar);
  /// @dev Emitted each time the Target is set.
  event TargetSet(address indexed previousTarget, address indexed newTarget);

  /// @dev Sets the avatar to a new avatar (`newAvatar`).
  /// @notice Can only be called by the current owner.
  function setAvatar(address _avatar) public onlyOwner {
    address previousAvatar = avatar;
    avatar = _avatar;
    emit AvatarSet(previousAvatar, _avatar);
  }

  /// @dev Sets the target to a new target (`newTarget`).
  /// @notice Can only be called by the current owner.
  function setTarget(address _target) public onlyOwner {
    address previousTarget = target;
    target = _target;
    emit TargetSet(previousTarget, _target);
  }

  /// @dev Passes a transaction to be executed by the avatar.
  /// @notice Can only be called by this contract.
  /// @param to Destination address of module transaction.
  /// @param value Ether value of module transaction.
  /// @param data Data payload of module transaction.
  /// @param operation Operation type of module transaction: 0 == call, 1 == delegate call.
  function exec(
    address to,
    uint256 value,
    bytes memory data,
    Enum.Operation operation
  ) internal virtual returns (bool success) {
    return
      IAvatar(target).execTransactionFromModule(to, value, data, operation);
  }

  /// @dev Passes a transaction to be executed by the target and returns data.
  /// @notice Can only be called by this contract.
  /// @param to Destination address of module transaction.
  /// @param value Ether value of module transaction.
  /// @param data Data payload of module transaction.
  /// @param operation Operation type of module transaction: 0 == call, 1 == delegate call.
  function execAndReturnData(
    address to,
    uint256 value,
    bytes memory data,
    Enum.Operation operation
  ) internal virtual returns (bool success, bytes memory returnData) {
    return
      IAvatar(target).execTransactionFromModuleReturnData(
        to,
        value,
        data,
        operation
      );
  }
}

File 5 of 14 : FactoryFriendly.sol
// SPDX-License-Identifier: LGPL-3.0-only

/// @title Zodiac FactoryFriendly - A contract that allows other contracts to be initializable and pass bytes as arguments to define contract state
pragma solidity >=0.7.0 <0.9.0;

import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";

abstract contract FactoryFriendly is OwnableUpgradeable {
  function setUp(bytes memory initializeParams) public virtual;
}

File 6 of 14 : IAvatar.sol
// SPDX-License-Identifier: LGPL-3.0-only

/// @title Zodiac Avatar - A contract that manages modules that can execute transactions via this contract.
pragma solidity >=0.7.0 <0.9.0;

import {Enum} from "@gnosis.pm/safe-contracts/contracts/common/Enum.sol";

interface IAvatar {
  event EnabledModule(address module);
  event DisabledModule(address module);
  event ExecutionFromModuleSuccess(address indexed module);
  event ExecutionFromModuleFailure(address indexed module);

  /// @dev Enables a module on the avatar.
  /// @notice Can only be called by the avatar.
  /// @notice Modules should be stored as a linked list.
  /// @notice Must emit EnabledModule(address module) if successful.
  /// @param module Module to be enabled.
  function enableModule(address module) external;

  /// @dev Disables a module on the avatar.
  /// @notice Can only be called by the avatar.
  /// @notice Must emit DisabledModule(address module) if successful.
  /// @param prevModule Address that pointed to the module to be removed in the linked list
  /// @param module Module to be removed.
  function disableModule(address prevModule, address module) external;

  /// @dev Allows a Module to execute a transaction.
  /// @notice Can only be called by an enabled module.
  /// @notice Must emit ExecutionFromModuleSuccess(address module) if successful.
  /// @notice Must emit ExecutionFromModuleFailure(address module) if unsuccessful.
  /// @param to Destination address of module transaction.
  /// @param value Ether value of module transaction.
  /// @param data Data payload of module transaction.
  /// @param operation Operation type of module transaction: 0 == call, 1 == delegate call.
  function execTransactionFromModule(
    address to,
    uint256 value,
    bytes memory data,
    Enum.Operation operation
  ) external returns (bool success);

  /// @dev Allows a Module to execute a transaction and return data
  /// @notice Can only be called by an enabled module.
  /// @notice Must emit ExecutionFromModuleSuccess(address module) if successful.
  /// @notice Must emit ExecutionFromModuleFailure(address module) if unsuccessful.
  /// @param to Destination address of module transaction.
  /// @param value Ether value of module transaction.
  /// @param data Data payload of module transaction.
  /// @param operation Operation type of module transaction: 0 == call, 1 == delegate call.
  function execTransactionFromModuleReturnData(
    address to,
    uint256 value,
    bytes memory data,
    Enum.Operation operation
  ) external returns (bool success, bytes memory returnData);

  /// @dev Returns if an module is enabled
  /// @return True if the module is enabled
  function isModuleEnabled(address module) external view returns (bool);

  /// @dev Returns array of modules.
  /// @param start Start of the page.
  /// @param pageSize Maximum number of modules that should be returned.
  /// @return array Array of modules.
  /// @return next Start of the next page.
  function getModulesPaginated(
    address start,
    uint256 pageSize
  ) external view returns (address[] memory array, address next);
}

File 7 of 14 : ExecutionTracker.sol
// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.8.0 <0.9.0;

/// @title ExecutionTracker - A contract that keeps track of executed and invalidated hashes
contract ExecutionTracker {
  error HashAlreadyConsumed(bytes32);

  event HashExecuted(bytes32);
  event HashInvalidated(bytes32);

  mapping(address => mapping(bytes32 => bool)) public consumed;

  function invalidate(bytes32 hash) external {
    consumed[msg.sender][hash] = true;
    emit HashInvalidated(hash);
  }
}

File 8 of 14 : IERC1271.sol
// SPDX-License-Identifier: LGPL-3.0-only
/* solhint-disable one-contract-per-file */
pragma solidity >=0.7.0 <0.9.0;

interface IERC1271 {
  /**
   * @notice EIP1271 method to validate a signature.
   * @param hash Hash of the data signed on the behalf of address(this).
   * @param signature Signature byte array associated with _data.
   *
   * MUST return the bytes4 magic value 0x1626ba7e when function passes.
   * MUST NOT modify state (using STATICCALL for solc < 0.5, view modifier for solc > 0.5)
   * MUST allow external calls
   */
  function isValidSignature(
    bytes32 hash,
    bytes memory signature
  ) external view returns (bytes4);
}

File 9 of 14 : SignatureChecker.sol
// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.8.0 <0.9.0;

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

/// @title SignatureChecker - A contract that retrieves and validates signatures appended to transaction calldata.
/// @dev currently supports eip-712 and eip-1271 signatures
abstract contract SignatureChecker {
  /**
   * @notice Searches for a signature, validates it, and returns the signer's address.
   * @dev When signature not found or invalid, zero address is returned
   * @return The address of the signer.
   */
  function moduleTxSignedBy() internal view returns (bytes32, address) {
    bytes calldata data = msg.data;

    /*
     * The idea is to extend `onlyModule` and provide signature checking
     * without code changes to inheriting contracts (Modifiers).
     *
     * Since it's a generic mechanism, there is no way to conclusively
     * identify the trailing bytes as a signature. We simply slice those
     * and recover signer.
     *
     * As a result, we impose a minimum calldata length equal to a function
     * selector plus salt, plus a signature (i.e., 4 + 32 + 65 bytes), any
     * shorter and calldata it guaranteed to not contain a signature.
     */
    if (data.length < 4 + 32 + 65) {
      return (bytes32(0), address(0));
    }

    (uint8 v, bytes32 r, bytes32 s) = _splitSignature(data);

    uint256 end = data.length - (32 + 65);
    bytes32 salt = bytes32(data[end:]);

    /*
     * When handling contract signatures:
     *  v - is zero
     *  r - contains the signer
     *  s - contains the offset within calldata where the signer specific
     *      signature is located
     *
     * We detect contract signatures by checking:
     *  1- `v` is zero
     *  2- `s` points within the buffer, is after selector, is before
     *      salt and delimits a non-zero length buffer
     */
    if (v == 0) {
      uint256 start = uint256(s);
      if (start < 4 || start > end) {
        return (bytes32(0), address(0));
      }
      address signer = address(uint160(uint256(r)));

      bytes32 hash = moduleTxHash(data[:start], salt);
      return
        _isValidContractSignature(signer, hash, data[start:end])
          ? (hash, signer)
          : (bytes32(0), address(0));
    } else {
      bytes32 hash = moduleTxHash(data[:end], salt);
      return (hash, ecrecover(hash, v, r, s));
    }
  }

  /**
   * @notice Hashes the transaction EIP-712 data structure.
   * @dev The produced hash is intended to be signed.
   * @param data The current transaction's calldata.
   * @param salt The salt value.
   * @return The 32-byte hash that is to be signed.
   */
  function moduleTxHash(
    bytes calldata data,
    bytes32 salt
  ) public view returns (bytes32) {
    bytes32 domainSeparator = keccak256(
      abi.encode(DOMAIN_SEPARATOR_TYPEHASH, block.chainid, this)
    );
    bytes memory moduleTxData = abi.encodePacked(
      bytes1(0x19),
      bytes1(0x01),
      domainSeparator,
      keccak256(abi.encode(MODULE_TX_TYPEHASH, keccak256(data), salt))
    );
    return keccak256(moduleTxData);
  }

  /**
   * @dev Extracts signature from calldata, and divides it into `uint8 v, bytes32 r, bytes32 s`.
   * @param data The current transaction's calldata.
   * @return v The ECDSA v value
   * @return r The ECDSA r value
   * @return s The ECDSA s value
   */
  function _splitSignature(
    bytes calldata data
  ) private pure returns (uint8 v, bytes32 r, bytes32 s) {
    v = uint8(bytes1(data[data.length - 1:]));
    r = bytes32(data[data.length - 65:]);
    s = bytes32(data[data.length - 33:]);
  }

  /**
   * @dev Calls the signer contract, and validates the contract signature.
   * @param signer The address of the signer contract.
   * @param hash Hash of the data signed
   * @param signature The contract signature.
   * @return result Indicates whether the signature is valid.
   */
  function _isValidContractSignature(
    address signer,
    bytes32 hash,
    bytes calldata signature
  ) internal view returns (bool result) {
    uint256 size;
    // eslint-disable-line no-inline-assembly
    assembly {
      size := extcodesize(signer)
    }
    if (size == 0) {
      return false;
    }

    (, bytes memory returnData) = signer.staticcall(
      abi.encodeWithSelector(
        IERC1271.isValidSignature.selector,
        hash,
        signature
      )
    );

    return bytes4(returnData) == EIP1271_MAGIC_VALUE;
  }

  // keccak256(
  //     "EIP712Domain(uint256 chainId,address verifyingContract)"
  // );
  bytes32 private constant DOMAIN_SEPARATOR_TYPEHASH =
    0x47e79534a245952e8b16893a336b85a3d9ea9fa8c573f3d803afb92a79469218;

  // keccak256(
  //     "ModuleTx(bytes data,bytes32 salt)"
  // );
  bytes32 private constant MODULE_TX_TYPEHASH =
    0x2939aeeda3ca260200c9f7b436b19e13207547ccc65cfedc857751c5ea6d91d4;

  // bytes4(keccak256(
  //     "isValidSignature(bytes32,bytes)"
  // ));
  bytes4 private constant EIP1271_MAGIC_VALUE = 0x1626ba7e;
}

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

pragma solidity ^0.8.20;

import {ContextUpgradeable} from "../utils/ContextUpgradeable.sol";
import {Initializable} from "../proxy/utils/Initializable.sol";

/**
 * @dev Contract module which provides a basic access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * 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 OwnableUpgradeable is Initializable, ContextUpgradeable {
    /// @custom:storage-location erc7201:openzeppelin.storage.Ownable
    struct OwnableStorage {
        address _owner;
    }

    // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Ownable")) - 1)) & ~bytes32(uint256(0xff))
    bytes32 private constant OwnableStorageLocation = 0x9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300;

    function _getOwnableStorage() private pure returns (OwnableStorage storage $) {
        assembly {
            $.slot := OwnableStorageLocation
        }
    }

    /**
     * @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.
     */
    function __Ownable_init(address initialOwner) internal onlyInitializing {
        __Ownable_init_unchained(initialOwner);
    }

    function __Ownable_init_unchained(address initialOwner) internal onlyInitializing {
        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) {
        OwnableStorage storage $ = _getOwnableStorage();
        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 {
        OwnableStorage storage $ = _getOwnableStorage();
        address oldOwner = $._owner;
        $._owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}

File 11 of 14 : Initializable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (proxy/utils/Initializable.sol)

pragma solidity ^0.8.20;

/**
 * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
 * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an
 * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
 * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
 *
 * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be
 * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in
 * case an upgrade adds a module that needs to be initialized.
 *
 * For example:
 *
 * [.hljs-theme-light.nopadding]
 * ```solidity
 * contract MyToken is ERC20Upgradeable {
 *     function initialize() initializer public {
 *         __ERC20_init("MyToken", "MTK");
 *     }
 * }
 *
 * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {
 *     function initializeV2() reinitializer(2) public {
 *         __ERC20Permit_init("MyToken");
 *     }
 * }
 * ```
 *
 * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
 * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.
 *
 * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
 * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
 *
 * [CAUTION]
 * ====
 * Avoid leaving a contract uninitialized.
 *
 * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation
 * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke
 * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:
 *
 * [.hljs-theme-light.nopadding]
 * ```
 * /// @custom:oz-upgrades-unsafe-allow constructor
 * constructor() {
 *     _disableInitializers();
 * }
 * ```
 * ====
 */
abstract contract Initializable {
    /**
     * @dev Storage of the initializable contract.
     *
     * It's implemented on a custom ERC-7201 namespace to reduce the risk of storage collisions
     * when using with upgradeable contracts.
     *
     * @custom:storage-location erc7201:openzeppelin.storage.Initializable
     */
    struct InitializableStorage {
        /**
         * @dev Indicates that the contract has been initialized.
         */
        uint64 _initialized;
        /**
         * @dev Indicates that the contract is in the process of being initialized.
         */
        bool _initializing;
    }

    // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Initializable")) - 1)) & ~bytes32(uint256(0xff))
    bytes32 private constant INITIALIZABLE_STORAGE = 0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00;

    /**
     * @dev The contract is already initialized.
     */
    error InvalidInitialization();

    /**
     * @dev The contract is not initializing.
     */
    error NotInitializing();

    /**
     * @dev Triggered when the contract has been initialized or reinitialized.
     */
    event Initialized(uint64 version);

    /**
     * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,
     * `onlyInitializing` functions can be used to initialize parent contracts.
     *
     * Similar to `reinitializer(1)`, except that in the context of a constructor an `initializer` may be invoked any
     * number of times. This behavior in the constructor can be useful during testing and is not expected to be used in
     * production.
     *
     * Emits an {Initialized} event.
     */
    modifier initializer() {
        // solhint-disable-next-line var-name-mixedcase
        InitializableStorage storage $ = _getInitializableStorage();

        // Cache values to avoid duplicated sloads
        bool isTopLevelCall = !$._initializing;
        uint64 initialized = $._initialized;

        // Allowed calls:
        // - initialSetup: the contract is not in the initializing state and no previous version was
        //                 initialized
        // - construction: the contract is initialized at version 1 (no reininitialization) and the
        //                 current contract is just being deployed
        bool initialSetup = initialized == 0 && isTopLevelCall;
        bool construction = initialized == 1 && address(this).code.length == 0;

        if (!initialSetup && !construction) {
            revert InvalidInitialization();
        }
        $._initialized = 1;
        if (isTopLevelCall) {
            $._initializing = true;
        }
        _;
        if (isTopLevelCall) {
            $._initializing = false;
            emit Initialized(1);
        }
    }

    /**
     * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the
     * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be
     * used to initialize parent contracts.
     *
     * A reinitializer may be used after the original initialization step. This is essential to configure modules that
     * are added through upgrades and that require initialization.
     *
     * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`
     * cannot be nested. If one is invoked in the context of another, execution will revert.
     *
     * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in
     * a contract, executing them in the right order is up to the developer or operator.
     *
     * WARNING: Setting the version to 2**64 - 1 will prevent any future reinitialization.
     *
     * Emits an {Initialized} event.
     */
    modifier reinitializer(uint64 version) {
        // solhint-disable-next-line var-name-mixedcase
        InitializableStorage storage $ = _getInitializableStorage();

        if ($._initializing || $._initialized >= version) {
            revert InvalidInitialization();
        }
        $._initialized = version;
        $._initializing = true;
        _;
        $._initializing = false;
        emit Initialized(version);
    }

    /**
     * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the
     * {initializer} and {reinitializer} modifiers, directly or indirectly.
     */
    modifier onlyInitializing() {
        _checkInitializing();
        _;
    }

    /**
     * @dev Reverts if the contract is not in an initializing state. See {onlyInitializing}.
     */
    function _checkInitializing() internal view virtual {
        if (!_isInitializing()) {
            revert NotInitializing();
        }
    }

    /**
     * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.
     * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized
     * to any version. It is recommended to use this to lock implementation contracts that are designed to be called
     * through proxies.
     *
     * Emits an {Initialized} event the first time it is successfully executed.
     */
    function _disableInitializers() internal virtual {
        // solhint-disable-next-line var-name-mixedcase
        InitializableStorage storage $ = _getInitializableStorage();

        if ($._initializing) {
            revert InvalidInitialization();
        }
        if ($._initialized != type(uint64).max) {
            $._initialized = type(uint64).max;
            emit Initialized(type(uint64).max);
        }
    }

    /**
     * @dev Returns the highest version that has been initialized. See {reinitializer}.
     */
    function _getInitializedVersion() internal view returns (uint64) {
        return _getInitializableStorage()._initialized;
    }

    /**
     * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.
     */
    function _isInitializing() internal view returns (bool) {
        return _getInitializableStorage()._initializing;
    }

    /**
     * @dev Returns a pointer to the storage namespace.
     */
    // solhint-disable-next-line var-name-mixedcase
    function _getInitializableStorage() private pure returns (InitializableStorage storage $) {
        assembly {
            $.slot := INITIALIZABLE_STORAGE
        }
    }
}

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

pragma solidity ^0.8.20;
import {Initializable} from "../proxy/utils/Initializable.sol";

/**
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
abstract contract ContextUpgradeable is Initializable {
    function __Context_init() internal onlyInitializing {
    }

    function __Context_init_unchained() internal onlyInitializing {
    }
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }

    function _contextSuffixLength() internal view virtual returns (uint256) {
        return 0;
    }
}

File 13 of 14 : IDelay.sol
// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.8.0;

import {Enum} from "@gnosis.pm/zodiac/contracts/core/Modifier.sol";

interface IDelay {
    event DelaySetup(
        address indexed initiator,
        address indexed owner,
        address indexed avatar,
        address target
    );
    event TxCooldownSet(uint256 cooldown);
    event TxExpirationSet(uint256 expiration);
    event TxNonceSet(uint256 nonce);
    event TransactionAdded(
        uint256 indexed queueNonce,
        bytes32 indexed txHash,
        address to,
        uint256 value,
        bytes data,
        Enum.Operation operation
    );

    function txCooldown() external view returns (uint256);
    function txExpiration() external view returns (uint256);
    function txNonce() external view returns (uint256);
    function queueNonce() external view returns (uint256);
    function txHash(uint256) external view returns (bytes32);
    function txCreatedAt(uint256) external view returns (uint256);

    function setTxCooldown(uint256 _txCooldown) external;
    function setTxExpiration(uint256 _txExpiration) external;
    function setTxNonce(uint256 _txNonce) external;
    function execTransactionFromModule(
        address to,
        uint256 value,
        bytes calldata data,
        Enum.Operation operation
    ) external returns (bool success);
    function execTransactionFromModuleReturnData(
        address to,
        uint256 value,
        bytes calldata data,
        Enum.Operation operation
    ) external returns (bool success, bytes memory returnData);
    function executeNextTx(
        address to,
        uint256 value,
        bytes calldata data,
        Enum.Operation operation
    ) external;
    function skipExpired() external;
    function getTransactionHash(
        address to,
        uint256 value,
        bytes memory data,
        Enum.Operation operation
    ) external pure returns (bytes32);
    function getTxHash(uint256 _nonce) external view returns (bytes32);
    function getTxCreatedAt(uint256 _nonce) external view returns (uint256);
}

File 14 of 14 : IOwnerManager.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.18;

interface IOwnerManager {
    function swapOwner(
        address prevOwner,
        address oldOwner,
        address newOwner
    ) external;
}

Settings
{
  "optimizer": {
    "enabled": true,
    "runs": 1000
  },
  "evmVersion": "paris",
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  }
}

Contract ABI

[{"inputs":[{"internalType":"address","name":"_target","type":"address"},{"internalType":"address","name":"_avatar","type":"address"},{"internalType":"address","name":"_owner","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"InvalidInitialization","type":"error"},{"inputs":[],"name":"NotInitializing","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousAvatar","type":"address"},{"indexed":true,"internalType":"address","name":"newAvatar","type":"address"}],"name":"AvatarSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"version","type":"uint64"}],"name":"Initialized","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":true,"internalType":"address","name":"oldOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"SwapOwner","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"initiator","type":"address"},{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"avatar","type":"address"},{"indexed":false,"internalType":"address","name":"target","type":"address"}],"name":"SwapOwnerSetup","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousTarget","type":"address"},{"indexed":true,"internalType":"address","name":"newTarget","type":"address"}],"name":"TargetSet","type":"event"},{"inputs":[],"name":"avatar","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_avatar","type":"address"}],"name":"setAvatar","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_target","type":"address"}],"name":"setTarget","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"initializeParams","type":"bytes"}],"name":"setUp","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"prevOwner","type":"address"},{"internalType":"address","name":"oldOwner","type":"address"},{"internalType":"address","name":"newOwner","type":"address"}],"name":"startRecovery","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"swapNonceToDelayQueueNonce","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"swapTxNonce","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"target","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}]

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
[ 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.