ETH Price: $2,716.26 (+0.85%)
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Sub Delegate171314892023-04-26 16:07:11650 days ago1682525231IN
0x57aa7DeD...1cD97b2A3
0 ETH0.0027632248.05447785
Sub Delegate171258142023-04-25 21:01:59651 days ago1682456519IN
0x57aa7DeD...1cD97b2A3
0 ETH0.0029729451.65851612
Sub Delegate171254542023-04-25 19:49:11651 days ago1682452151IN
0x57aa7DeD...1cD97b2A3
0 ETH0.0019545433.99089089
Sub Delegate171182392023-04-24 19:31:35652 days ago1682364695IN
0x57aa7DeD...1cD97b2A3
0 ETH0.0189959962.71540019
Sub Delegate170786482023-04-19 5:40:59657 days ago1681882859IN
0x57aa7DeD...1cD97b2A3
0 ETH0.0141285646.64740895
Sub Delegate170683962023-04-17 18:54:59659 days ago1681757699IN
0x57aa7DeD...1cD97b2A3
0 ETH0.0096104531.7264764
Sub Delegate170488042023-04-15 0:06:35662 days ago1681517195IN
0x57aa7DeD...1cD97b2A3
0 ETH0.0014838125.78838923
Sub Delegate170317742023-04-12 11:56:23664 days ago1681300583IN
0x57aa7DeD...1cD97b2A3
0 ETH0.0061157320.19407442
Create169363442023-03-29 23:56:35678 days ago1680134195IN
0x57aa7DeD...1cD97b2A3
0 ETH0.0201165227.04248591
Create168011962023-03-11 0:10:35697 days ago1678493435IN
0x57aa7DeD...1cD97b2A3
0 ETH0.0250694550.15927057
Transfer Ownersh...168011052023-03-10 23:51:59697 days ago1678492319IN
0x57aa7DeD...1cD97b2A3
0 ETH0.0011442440

Latest 6 internal transactions

Advanced mode:
Parent Transaction Hash Block
From
To
171182392023-04-24 19:31:35652 days ago1682364695
0x57aa7DeD...1cD97b2A3
 Contract Creation0 ETH
170979942023-04-21 23:23:59655 days ago1682119439
0x57aa7DeD...1cD97b2A3
 Contract Creation0 ETH
170786482023-04-19 5:40:59657 days ago1681882859
0x57aa7DeD...1cD97b2A3
 Contract Creation0 ETH
170683962023-04-17 18:54:59659 days ago1681757699
0x57aa7DeD...1cD97b2A3
 Contract Creation0 ETH
170317742023-04-12 11:56:23664 days ago1681300583
0x57aa7DeD...1cD97b2A3
 Contract Creation0 ETH
168011962023-03-11 0:10:35697 days ago1678493435
0x57aa7DeD...1cD97b2A3
 Contract Creation0 ETH
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
Alligator

Compiler Version
v0.8.19+commit.7dd6d404

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion
File 1 of 19 : Alligator.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;

import {Proxy} from "./Proxy.sol";
import {ENSHelper} from "./utils/ENSHelper.sol";
import {ECDSA} from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
import {INounsDAOV2} from "./interfaces/INounsDAOV2.sol";
import {IRule} from "./interfaces/IRule.sol";
import {IERC1271} from "@openzeppelin/contracts/interfaces/IERC1271.sol";
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
import {Pausable} from "@openzeppelin/contracts/security/Pausable.sol";
import "./interfaces/IAlligator.sol";

contract Alligator is IAlligator, ENSHelper, Ownable, Pausable {
    // =============================================================
    //                             ERRORS
    // =============================================================

    error BadSignature();
    error NotDelegated(address from, address to, uint256 requiredPermissions);
    error TooManyRedelegations(address from, address to);
    error NotValidYet(address from, address to, uint256 willBeValidFrom);
    error NotValidAnymore(address from, address to, uint256 wasValidUntil);
    error TooEarly(address from, address to, uint256 blocksBeforeVoteCloses);
    error InvalidCustomRule(address from, address to, address customRule);

    // =============================================================
    //                       IMMUTABLE STORAGE
    // =============================================================

    INounsDAOV2 public immutable governor;

    uint8 internal constant PERMISSION_VOTE = 1;
    uint8 internal constant PERMISSION_SIGN = 1 << 1;
    uint8 internal constant PERMISSION_PROPOSE = 1 << 2;

    bytes32 internal constant DOMAIN_TYPEHASH =
        keccak256("EIP712Domain(string name,uint256 chainId,address verifyingContract)");

    bytes32 internal constant BALLOT_TYPEHASH = keccak256("Ballot(uint256 proposalId,uint8 support)");

    /// @notice The maximum priority fee used to cap gas refunds in `castRefundableVote`
    uint256 public constant MAX_REFUND_PRIORITY_FEE = 2 gwei;

    /// @notice The vote refund gas overhead, including 7K for ETH transfer and 29K for general transaction overhead
    uint256 public constant REFUND_BASE_GAS = 36000;

    /// @notice The maximum gas units the DAO will refund voters on; supports about 9,190 characters
    uint256 public constant MAX_REFUND_GAS_USED = 200_000;

    /// @notice The maximum basefee the DAO will refund voters on
    uint256 public constant MAX_REFUND_BASE_FEE = 200 gwei;

    // =============================================================
    //                        MUTABLE STORAGE
    // =============================================================

    // From => To => Rules
    mapping(address => mapping(address => Rules)) public subDelegations;
    // Proxy address => hash => valid boolean
    mapping(address => mapping(bytes32 => bool)) internal validSignatures;

    // =============================================================
    //                         CONSTRUCTOR
    // =============================================================

    constructor(INounsDAOV2 _governor, string memory _ensName, bytes32 _ensNameHash) ENSHelper(_ensName, _ensNameHash) {
        governor = _governor;
    }

    // =============================================================
    //                       WRITE FUNCTIONS
    // =============================================================

    /**
     * @notice Deploy a new Proxy for an owner deterministically.
     *
     * @param owner The owner of the Proxy.
     * @param registerEnsName Whether to register the ENS name for the Proxy.
     *
     * @return endpoint Address of the Proxy
     */
    function create(address owner, bool registerEnsName) public returns (address endpoint) {
        endpoint = address(new Proxy{salt: bytes32(uint256(uint160(owner)))}(address(governor)));
        emit ProxyDeployed(owner, endpoint);

        if (registerEnsName) {
            if (ensNameHash != 0) {
                string memory reverseName = registerDeployment(endpoint);
                Proxy(payable(endpoint)).setENSReverseRecord(reverseName);
            }
        }
    }

    /**
     * @notice Register ENS name for an already deployed Proxy.
     *
     * @param owner The owner of the Proxy.
     *
     * @dev Reverts if the ENS name is already set.
     */
    function registerProxyDeployment(address owner) public {
        if (ensNameHash != 0) {
            address proxy = proxyAddress(owner);
            string memory reverseName = registerDeployment(proxy);
            Proxy(payable(proxy)).setENSReverseRecord(reverseName);
        }
    }

    /**
     * @notice Validate subdelegation rules and make a proposal to the governor.
     *
     * @param authority The authority chain to validate against.
     * @param targets Target addresses for proposal calls
     * @param values Eth values for proposal calls
     * @param signatures Function signatures for proposal calls
     * @param calldatas Calldatas for proposal calls
     * @param description String description of the proposal
     *
     * @return proposalId Proposal id of new proposal
     */
    function propose(
        address[] calldata authority,
        address[] calldata targets,
        uint256[] calldata values,
        string[] calldata signatures,
        bytes[] calldata calldatas,
        string calldata description
    ) external whenNotPaused returns (uint256 proposalId) {
        address proxy = proxyAddress(authority[0]);
        // Create a proposal first so the custom rules can validate it
        proposalId = INounsDAOV2(proxy).propose(targets, values, signatures, calldatas, description);
        validate(msg.sender, authority, PERMISSION_PROPOSE, proposalId, 0xFF);
    }

    /**
     * @notice Validate subdelegation rules and cast a vote on the governor.
     *
     * @param authority The authority chain to validate against.
     * @param proposalId The id of the proposal to vote on
     * @param support The support value for the vote. 0=against, 1=for, 2=abstain
     */
    function castVote(address[] calldata authority, uint256 proposalId, uint8 support) external whenNotPaused {
        validate(msg.sender, authority, PERMISSION_VOTE, proposalId, support);

        address proxy = proxyAddress(authority[0]);
        INounsDAOV2(proxy).castVote(proposalId, support);
        emit VoteCast(proxy, msg.sender, authority, proposalId, support);
    }

    /**
     * @notice Validate subdelegation rules and cast a vote with reason on the governor.
     *
     * @param authority The authority chain to validate against.
     * @param proposalId The id of the proposal to vote on
     * @param support The support value for the vote. 0=against, 1=for, 2=abstain
     * @param reason The reason given for the vote by the voter
     */
    function castVoteWithReason(
        address[] calldata authority,
        uint256 proposalId,
        uint8 support,
        string calldata reason
    ) public whenNotPaused {
        validate(msg.sender, authority, PERMISSION_VOTE, proposalId, support);

        address proxy = proxyAddress(authority[0]);
        INounsDAOV2(proxy).castVoteWithReason(proposalId, support, reason);
        emit VoteCast(proxy, msg.sender, authority, proposalId, support);
    }

    /**
     * @notice Validate subdelegation rules and cast multiple votes with reason on the governor.
     *
     * @param authorities The authority chains to validate against.
     * @param proposalId The id of the proposal to vote on
     * @param support The support value for the vote. 0=against, 1=for, 2=abstain
     * @param reason The reason given for the vote by the voter
     */
    function castVotesWithReasonBatched(
        address[][] calldata authorities,
        uint256 proposalId,
        uint8 support,
        string calldata reason
    ) public whenNotPaused {
        address[] memory proxies = new address[](authorities.length);
        address[] memory authority;
        for (uint256 i; i < authorities.length; ) {
            authority = authorities[i];
            validate(msg.sender, authority, PERMISSION_VOTE, proposalId, support);
            proxies[i] = proxyAddress(authority[0]);
            INounsDAOV2(proxies[i]).castVoteWithReason(proposalId, support, reason);

            unchecked {
                ++i;
            }
        }

        emit VotesCast(proxies, msg.sender, authorities, proposalId, support);
    }

    /**
     * @notice Validate subdelegation rules and cast multiple votes with reason on the governor.
     * Refunds the gas used to cast the votes, if possible.
     *
     * @param authorities The authority chains to validate against.
     * @param proposalId The id of the proposal to vote on
     * @param support The support value for the vote. 0=against, 1=for, 2=abstain
     * @param reason The reason given for the vote by the voter
     */
    function castRefundableVotesWithReasonBatched(
        address[][] calldata authorities,
        uint256 proposalId,
        uint8 support,
        string calldata reason
    ) external whenNotPaused {
        uint256 startGas = gasleft();
        castVotesWithReasonBatched(authorities, proposalId, support, reason);
        _refundGas(startGas);
    }

    /**
     * @notice Validate subdelegation rules and cast a vote by signature on the governor.
     *
     * @param authority The authority chain to validate against.
     * @param proposalId The id of the proposal to vote on
     * @param support The support value for the vote. 0=against, 1=for, 2=abstain
     */
    function castVoteBySig(
        address[] calldata authority,
        uint256 proposalId,
        uint8 support,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external whenNotPaused {
        bytes32 domainSeparator = keccak256(
            abi.encode(DOMAIN_TYPEHASH, keccak256("Alligator"), block.chainid, address(this))
        );
        bytes32 structHash = keccak256(abi.encode(BALLOT_TYPEHASH, proposalId, support));
        bytes32 digest = keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash));
        address signatory = ecrecover(digest, v, r, s);

        if (signatory == address(0)) {
            revert BadSignature();
        }

        validate(signatory, authority, PERMISSION_VOTE, proposalId, support);

        address proxy = proxyAddress(authority[0]);
        INounsDAOV2(proxy).castVote(proposalId, support);
        emit VoteCast(proxy, signatory, authority, proposalId, support);
    }

    /**
     * @notice Validate subdelegation rules and sign a hash.
     *
     * @param authority The authority chain to validate against.
     * @param hash The hash to sign.
     */
    function sign(address[] calldata authority, bytes32 hash) external whenNotPaused {
        validate(msg.sender, authority, PERMISSION_SIGN, 0, 0xFE);

        address proxy = proxyAddress(authority[0]);
        validSignatures[proxy][hash] = true;
        emit Signed(proxy, authority, hash);
    }

    /**
     * @notice Subdelegate an address with rules.
     *
     * @param to The address to subdelegate to.
     * @param rules The rules to apply to the subdelegation.
     * @param createProxy Whether to create a Proxy for the sender, if one doesn't exist.
     */
    function subDelegate(address to, Rules calldata rules, bool createProxy) external {
        if (createProxy) {
            if (proxyAddress(msg.sender).code.length == 0) {
                create(msg.sender, false);
            }
        }

        subDelegations[msg.sender][to] = rules;
        emit SubDelegation(msg.sender, to, rules);
    }

    /**
     * @notice Subdelegate multiple addresses with rules.
     *
     * @param targets The addresses to subdelegate to.
     * @param rules The rules to apply to the subdelegations.
     * @param createProxy Whether to create a Proxy for the sender, if one doesn't exist.
     */
    function subDelegateBatched(address[] calldata targets, Rules[] calldata rules, bool createProxy) external {
        require(targets.length == rules.length);

        if (createProxy) {
            if (proxyAddress(msg.sender).code.length == 0) {
                create(msg.sender, false);
            }
        }

        for (uint256 i; i < targets.length; ) {
            subDelegations[msg.sender][targets[i]] = rules[i];

            unchecked {
                ++i;
            }
        }

        emit SubDelegations(msg.sender, targets, rules);
    }

    /**
     * @notice Pauses and unpauses propose, vote and sign operations.
     *
     * @dev Only contract owner can toggle pause.
     */
    function _togglePause() external onlyOwner {
        if (!paused()) {
            _pause();
        } else {
            _unpause();
        }
    }

    // Refill Alligator's balance for gas refunds
    receive() external payable {}

    // =============================================================
    //                         VIEW FUNCTIONS
    // =============================================================

    /**
     * @notice Validate subdelegation rules.
     *
     * @param sender The sender address to validate.
     * @param authority The authority chain to validate against.
     * @param permissions The permissions to validate.
     * @param proposalId The id of the proposal for which validation is being performed.
     * @param support The support value for the vote. 0=against, 1=for, 2=abstain, 0xFF=proposal
     */
    function validate(
        address sender,
        address[] memory authority,
        uint256 permissions,
        uint256 proposalId,
        uint256 support
    ) public view {
        address from = authority[0];

        if (from == sender) {
            return;
        }

        uint256 authorityLength = authority.length;
        address to;
        Rules memory rules;

        /// @dev maxRedelegations would hit block size limit before overflowing
        /// @dev block.number + rules.blocksBeforeVoteCloses fits in uint256
        unchecked {
            for (uint256 i = 1; i < authorityLength; ++i) {
                to = authority[i];
                rules = subDelegations[from][to];

                if ((rules.permissions & permissions) != permissions) {
                    revert NotDelegated(from, to, permissions);
                }
                if (rules.maxRedelegations + i + 1 < authorityLength) {
                    revert TooManyRedelegations(from, to);
                }
                if (block.timestamp < rules.notValidBefore) {
                    revert NotValidYet(from, to, rules.notValidBefore);
                }
                if (rules.notValidAfter != 0) {
                    if (block.timestamp > rules.notValidAfter) revert NotValidAnymore(from, to, rules.notValidAfter);
                }
                if (rules.blocksBeforeVoteCloses != 0) {
                    INounsDAOV2.ProposalCondensed memory proposal = governor.proposals(proposalId);
                    if (proposal.endBlock > block.number + rules.blocksBeforeVoteCloses) {
                        revert TooEarly(from, to, rules.blocksBeforeVoteCloses);
                    }
                }
                if (rules.customRule != address(0)) {
                    if (
                        IRule(rules.customRule).validate(address(governor), sender, proposalId, uint8(support)) !=
                        IRule.validate.selector
                    ) {
                        revert InvalidCustomRule(from, to, rules.customRule);
                    }
                }

                from = to;
            }
        }

        if (from == sender) {
            return;
        }

        revert NotDelegated(from, sender, permissions);
    }

    /**
     * @notice Checks if proxy signature is valid.
     *
     * @param proxy The address of the proxy contract.
     * @param hash The hash to validate.
     * @param data The data to validate.
     *
     * @return magicValue `IERC1271.isValidSignature` if signature is valid, or 0 if not.
     */
    function isValidProxySignature(
        address proxy,
        bytes32 hash,
        bytes calldata data
    ) public view returns (bytes4 magicValue) {
        if (data.length > 0) {
            (address[] memory authority, bytes memory signature) = abi.decode(data, (address[], bytes));
            address signer = ECDSA.recover(hash, signature);
            validate(signer, authority, PERMISSION_SIGN, 0, 0xFE);
            return IERC1271.isValidSignature.selector;
        }
        return validSignatures[proxy][hash] ? IERC1271.isValidSignature.selector : bytes4(0);
    }

    /**
     * @notice Returns the address of the proxy contract for a given owner
     *
     * @param owner The owner of the Proxy.
     *
     * @return endpoint The address of the Proxy.
     */
    function proxyAddress(address owner) public view returns (address endpoint) {
        endpoint = address(
            uint160(
                uint256(
                    keccak256(
                        abi.encodePacked(
                            bytes1(0xff),
                            address(this),
                            bytes32(uint256(uint160(owner))), // salt
                            keccak256(abi.encodePacked(type(Proxy).creationCode, abi.encode(address(governor))))
                        )
                    )
                )
            )
        );
    }

    // =============================================================
    //                       INTERNAL FUNCTIONS
    // =============================================================

    function _refundGas(uint256 startGas) internal {
        unchecked {
            uint256 balance = address(this).balance;
            if (balance == 0) {
                return;
            }
            uint256 basefee = min(block.basefee, MAX_REFUND_BASE_FEE);
            uint256 gasPrice = min(tx.gasprice, basefee + MAX_REFUND_PRIORITY_FEE);
            uint256 gasUsed = min(startGas - gasleft() + REFUND_BASE_GAS, MAX_REFUND_GAS_USED);
            uint256 refundAmount = min(gasPrice * gasUsed, balance);
            (bool refundSent, ) = msg.sender.call{value: refundAmount}("");
            emit RefundableVote(msg.sender, refundAmount, refundSent);
        }
    }

    function min(uint256 a, uint256 b) internal pure returns (uint256) {
        return a < b ? a : b;
    }
}

File 2 of 19 : ENS.sol
pragma solidity >=0.8.4;

interface ENS {
    // Logged when the owner of a node assigns a new owner to a subnode.
    event NewOwner(bytes32 indexed node, bytes32 indexed label, address owner);

    // Logged when the owner of a node transfers ownership to a new account.
    event Transfer(bytes32 indexed node, address owner);

    // Logged when the resolver for a node changes.
    event NewResolver(bytes32 indexed node, address resolver);

    // Logged when the TTL of a node changes
    event NewTTL(bytes32 indexed node, uint64 ttl);

    // Logged when an operator is added or removed.
    event ApprovalForAll(
        address indexed owner,
        address indexed operator,
        bool approved
    );

    function setRecord(
        bytes32 node,
        address owner,
        address resolver,
        uint64 ttl
    ) external;

    function setSubnodeRecord(
        bytes32 node,
        bytes32 label,
        address owner,
        address resolver,
        uint64 ttl
    ) external;

    function setSubnodeOwner(
        bytes32 node,
        bytes32 label,
        address owner
    ) external returns (bytes32);

    function setResolver(bytes32 node, address resolver) external;

    function setOwner(bytes32 node, address owner) external;

    function setTTL(bytes32 node, uint64 ttl) external;

    function setApprovalForAll(address operator, bool approved) external;

    function owner(bytes32 node) external view returns (address);

    function resolver(bytes32 node) external view returns (address);

    function ttl(bytes32 node) external view returns (uint64);

    function recordExists(bytes32 node) external view returns (bool);

    function isApprovedForAll(
        address owner,
        address operator
    ) external view returns (bool);
}

File 3 of 19 : IAddrResolver.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.4;

/**
 * Interface for the legacy (ETH-only) addr function.
 */
interface IAddrResolver {
    event AddrChanged(bytes32 indexed node, address a);

    /**
     * Returns the address associated with an ENS node.
     * @param node The ENS node to query.
     * @return The associated address.
     */
    function addr(bytes32 node) external view returns (address payable);
}

File 4 of 19 : Ownable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)

pragma solidity ^0.8.0;

import "../utils/Context.sol";

/**
 * @dev Contract module which provides a basic access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * 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 5 of 19 : IERC1271.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (interfaces/IERC1271.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC1271 standard signature validation method for
 * contracts as defined in https://eips.ethereum.org/EIPS/eip-1271[ERC-1271].
 *
 * _Available since v4.1._
 */
interface IERC1271 {
    /**
     * @dev Should return whether the signature provided is valid for the provided data
     * @param hash      Hash of the data to be signed
     * @param signature Signature byte array associated with _data
     */
    function isValidSignature(bytes32 hash, bytes memory signature) external view returns (bytes4 magicValue);
}

File 6 of 19 : Pausable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol)

pragma solidity ^0.8.0;

import "../utils/Context.sol";

/**
 * @dev Contract module which allows children to implement an emergency stop
 * mechanism that can be triggered by an authorized account.
 *
 * This module is used through inheritance. It will make available the
 * modifiers `whenNotPaused` and `whenPaused`, which can be applied to
 * the functions of your contract. Note that they will not be pausable by
 * simply including this module, only once the modifiers are put in place.
 */
abstract contract Pausable is Context {
    /**
     * @dev Emitted when the pause is triggered by `account`.
     */
    event Paused(address account);

    /**
     * @dev Emitted when the pause is lifted by `account`.
     */
    event Unpaused(address account);

    bool private _paused;

    /**
     * @dev Initializes the contract in unpaused state.
     */
    constructor() {
        _paused = false;
    }

    /**
     * @dev Modifier to make a function callable only when the contract is not paused.
     *
     * Requirements:
     *
     * - The contract must not be paused.
     */
    modifier whenNotPaused() {
        _requireNotPaused();
        _;
    }

    /**
     * @dev Modifier to make a function callable only when the contract is paused.
     *
     * Requirements:
     *
     * - The contract must be paused.
     */
    modifier whenPaused() {
        _requirePaused();
        _;
    }

    /**
     * @dev Returns true if the contract is paused, and false otherwise.
     */
    function paused() public view virtual returns (bool) {
        return _paused;
    }

    /**
     * @dev Throws if the contract is paused.
     */
    function _requireNotPaused() internal view virtual {
        require(!paused(), "Pausable: paused");
    }

    /**
     * @dev Throws if the contract is not paused.
     */
    function _requirePaused() internal view virtual {
        require(paused(), "Pausable: not paused");
    }

    /**
     * @dev Triggers stopped state.
     *
     * Requirements:
     *
     * - The contract must not be paused.
     */
    function _pause() internal virtual whenNotPaused {
        _paused = true;
        emit Paused(_msgSender());
    }

    /**
     * @dev Returns to normal state.
     *
     * Requirements:
     *
     * - The contract must be paused.
     */
    function _unpause() internal virtual whenPaused {
        _paused = false;
        emit Unpaused(_msgSender());
    }
}

File 7 of 19 : Context.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)

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;
    }
}

File 8 of 19 : Strings.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)

pragma solidity ^0.8.0;

import "./math/Math.sol";

/**
 * @dev String operations.
 */
library Strings {
    bytes16 private constant _SYMBOLS = "0123456789abcdef";
    uint8 private constant _ADDRESS_LENGTH = 20;

    /**
     * @dev Converts a `uint256` to its ASCII `string` decimal representation.
     */
    function toString(uint256 value) internal pure returns (string memory) {
        unchecked {
            uint256 length = Math.log10(value) + 1;
            string memory buffer = new string(length);
            uint256 ptr;
            /// @solidity memory-safe-assembly
            assembly {
                ptr := add(buffer, add(32, length))
            }
            while (true) {
                ptr--;
                /// @solidity memory-safe-assembly
                assembly {
                    mstore8(ptr, byte(mod(value, 10), _SYMBOLS))
                }
                value /= 10;
                if (value == 0) break;
            }
            return buffer;
        }
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
     */
    function toHexString(uint256 value) internal pure returns (string memory) {
        unchecked {
            return toHexString(value, Math.log256(value) + 1);
        }
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
     */
    function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
        bytes memory buffer = new bytes(2 * length + 2);
        buffer[0] = "0";
        buffer[1] = "x";
        for (uint256 i = 2 * length + 1; i > 1; --i) {
            buffer[i] = _SYMBOLS[value & 0xf];
            value >>= 4;
        }
        require(value == 0, "Strings: hex length insufficient");
        return string(buffer);
    }

    /**
     * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.
     */
    function toHexString(address addr) internal pure returns (string memory) {
        return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);
    }
}

File 9 of 19 : ECDSA.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/ECDSA.sol)

pragma solidity ^0.8.0;

import "../Strings.sol";

/**
 * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.
 *
 * These functions can be used to verify that a message was signed by the holder
 * of the private keys of a given address.
 */
library ECDSA {
    enum RecoverError {
        NoError,
        InvalidSignature,
        InvalidSignatureLength,
        InvalidSignatureS,
        InvalidSignatureV // Deprecated in v4.8
    }

    function _throwError(RecoverError error) private pure {
        if (error == RecoverError.NoError) {
            return; // no error: do nothing
        } else if (error == RecoverError.InvalidSignature) {
            revert("ECDSA: invalid signature");
        } else if (error == RecoverError.InvalidSignatureLength) {
            revert("ECDSA: invalid signature length");
        } else if (error == RecoverError.InvalidSignatureS) {
            revert("ECDSA: invalid signature 's' value");
        }
    }

    /**
     * @dev Returns the address that signed a hashed message (`hash`) with
     * `signature` or error string. This address can then be used for verification purposes.
     *
     * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
     * this function rejects them by requiring the `s` value to be in the lower
     * half order, and the `v` value to be either 27 or 28.
     *
     * IMPORTANT: `hash` _must_ be the result of a hash operation for the
     * verification to be secure: it is possible to craft signatures that
     * recover to arbitrary addresses for non-hashed data. A safe way to ensure
     * this is by receiving a hash of the original message (which may otherwise
     * be too long), and then calling {toEthSignedMessageHash} on it.
     *
     * Documentation for signature generation:
     * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]
     * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]
     *
     * _Available since v4.3._
     */
    function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {
        if (signature.length == 65) {
            bytes32 r;
            bytes32 s;
            uint8 v;
            // ecrecover takes the signature parameters, and the only way to get them
            // currently is to use assembly.
            /// @solidity memory-safe-assembly
            assembly {
                r := mload(add(signature, 0x20))
                s := mload(add(signature, 0x40))
                v := byte(0, mload(add(signature, 0x60)))
            }
            return tryRecover(hash, v, r, s);
        } else {
            return (address(0), RecoverError.InvalidSignatureLength);
        }
    }

    /**
     * @dev Returns the address that signed a hashed message (`hash`) with
     * `signature`. This address can then be used for verification purposes.
     *
     * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
     * this function rejects them by requiring the `s` value to be in the lower
     * half order, and the `v` value to be either 27 or 28.
     *
     * IMPORTANT: `hash` _must_ be the result of a hash operation for the
     * verification to be secure: it is possible to craft signatures that
     * recover to arbitrary addresses for non-hashed data. A safe way to ensure
     * this is by receiving a hash of the original message (which may otherwise
     * be too long), and then calling {toEthSignedMessageHash} on it.
     */
    function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {
        (address recovered, RecoverError error) = tryRecover(hash, signature);
        _throwError(error);
        return recovered;
    }

    /**
     * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.
     *
     * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]
     *
     * _Available since v4.3._
     */
    function tryRecover(
        bytes32 hash,
        bytes32 r,
        bytes32 vs
    ) internal pure returns (address, RecoverError) {
        bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);
        uint8 v = uint8((uint256(vs) >> 255) + 27);
        return tryRecover(hash, v, r, s);
    }

    /**
     * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.
     *
     * _Available since v4.2._
     */
    function recover(
        bytes32 hash,
        bytes32 r,
        bytes32 vs
    ) internal pure returns (address) {
        (address recovered, RecoverError error) = tryRecover(hash, r, vs);
        _throwError(error);
        return recovered;
    }

    /**
     * @dev Overload of {ECDSA-tryRecover} that receives the `v`,
     * `r` and `s` signature fields separately.
     *
     * _Available since v4.3._
     */
    function tryRecover(
        bytes32 hash,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) internal pure returns (address, RecoverError) {
        // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature
        // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines
        // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most
        // signatures from current libraries generate a unique signature with an s-value in the lower half order.
        //
        // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value
        // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or
        // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept
        // these malleable signatures as well.
        if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {
            return (address(0), RecoverError.InvalidSignatureS);
        }

        // If the signature is valid (and not malleable), return the signer address
        address signer = ecrecover(hash, v, r, s);
        if (signer == address(0)) {
            return (address(0), RecoverError.InvalidSignature);
        }

        return (signer, RecoverError.NoError);
    }

    /**
     * @dev Overload of {ECDSA-recover} that receives the `v`,
     * `r` and `s` signature fields separately.
     */
    function recover(
        bytes32 hash,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) internal pure returns (address) {
        (address recovered, RecoverError error) = tryRecover(hash, v, r, s);
        _throwError(error);
        return recovered;
    }

    /**
     * @dev Returns an Ethereum Signed Message, created from a `hash`. This
     * produces hash corresponding to the one signed with the
     * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]
     * JSON-RPC method as part of EIP-191.
     *
     * See {recover}.
     */
    function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {
        // 32 is the length in bytes of hash,
        // enforced by the type signature above
        return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash));
    }

    /**
     * @dev Returns an Ethereum Signed Message, created from `s`. This
     * produces hash corresponding to the one signed with the
     * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]
     * JSON-RPC method as part of EIP-191.
     *
     * See {recover}.
     */
    function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {
        return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n", Strings.toString(s.length), s));
    }

    /**
     * @dev Returns an Ethereum Signed Typed Data, created from a
     * `domainSeparator` and a `structHash`. This produces hash corresponding
     * to the one signed with the
     * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]
     * JSON-RPC method as part of EIP-712.
     *
     * See {recover}.
     */
    function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {
        return keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash));
    }
}

File 10 of 19 : IERC165.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)

pragma solidity ^0.8.0;

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

File 11 of 19 : Math.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)

pragma solidity ^0.8.0;

/**
 * @dev Standard math utilities missing in the Solidity language.
 */
library Math {
    enum Rounding {
        Down, // Toward negative infinity
        Up, // Toward infinity
        Zero // Toward zero
    }

    /**
     * @dev Returns the largest of two numbers.
     */
    function max(uint256 a, uint256 b) internal pure returns (uint256) {
        return a > b ? a : b;
    }

    /**
     * @dev Returns the smallest of two numbers.
     */
    function min(uint256 a, uint256 b) internal pure returns (uint256) {
        return a < b ? a : b;
    }

    /**
     * @dev Returns the average of two numbers. The result is rounded towards
     * zero.
     */
    function average(uint256 a, uint256 b) internal pure returns (uint256) {
        // (a + b) / 2 can overflow.
        return (a & b) + (a ^ b) / 2;
    }

    /**
     * @dev Returns the ceiling of the division of two numbers.
     *
     * This differs from standard division with `/` in that it rounds up instead
     * of rounding down.
     */
    function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
        // (a + b - 1) / b can overflow on addition, so we distribute.
        return a == 0 ? 0 : (a - 1) / b + 1;
    }

    /**
     * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
     * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)
     * with further edits by Uniswap Labs also under MIT license.
     */
    function mulDiv(
        uint256 x,
        uint256 y,
        uint256 denominator
    ) internal pure returns (uint256 result) {
        unchecked {
            // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use
            // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
            // variables such that product = prod1 * 2^256 + prod0.
            uint256 prod0; // Least significant 256 bits of the product
            uint256 prod1; // Most significant 256 bits of the product
            assembly {
                let mm := mulmod(x, y, not(0))
                prod0 := mul(x, y)
                prod1 := sub(sub(mm, prod0), lt(mm, prod0))
            }

            // Handle non-overflow cases, 256 by 256 division.
            if (prod1 == 0) {
                return prod0 / denominator;
            }

            // Make sure the result is less than 2^256. Also prevents denominator == 0.
            require(denominator > prod1);

            ///////////////////////////////////////////////
            // 512 by 256 division.
            ///////////////////////////////////////////////

            // Make division exact by subtracting the remainder from [prod1 prod0].
            uint256 remainder;
            assembly {
                // Compute remainder using mulmod.
                remainder := mulmod(x, y, denominator)

                // Subtract 256 bit number from 512 bit number.
                prod1 := sub(prod1, gt(remainder, prod0))
                prod0 := sub(prod0, remainder)
            }

            // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.
            // See https://cs.stackexchange.com/q/138556/92363.

            // Does not overflow because the denominator cannot be zero at this stage in the function.
            uint256 twos = denominator & (~denominator + 1);
            assembly {
                // Divide denominator by twos.
                denominator := div(denominator, twos)

                // Divide [prod1 prod0] by twos.
                prod0 := div(prod0, twos)

                // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.
                twos := add(div(sub(0, twos), twos), 1)
            }

            // Shift in bits from prod1 into prod0.
            prod0 |= prod1 * twos;

            // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such
            // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for
            // four bits. That is, denominator * inv = 1 mod 2^4.
            uint256 inverse = (3 * denominator) ^ 2;

            // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works
            // in modular arithmetic, doubling the correct bits in each step.
            inverse *= 2 - denominator * inverse; // inverse mod 2^8
            inverse *= 2 - denominator * inverse; // inverse mod 2^16
            inverse *= 2 - denominator * inverse; // inverse mod 2^32
            inverse *= 2 - denominator * inverse; // inverse mod 2^64
            inverse *= 2 - denominator * inverse; // inverse mod 2^128
            inverse *= 2 - denominator * inverse; // inverse mod 2^256

            // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
            // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is
            // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1
            // is no longer required.
            result = prod0 * inverse;
            return result;
        }
    }

    /**
     * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.
     */
    function mulDiv(
        uint256 x,
        uint256 y,
        uint256 denominator,
        Rounding rounding
    ) internal pure returns (uint256) {
        uint256 result = mulDiv(x, y, denominator);
        if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {
            result += 1;
        }
        return result;
    }

    /**
     * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.
     *
     * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11).
     */
    function sqrt(uint256 a) internal pure returns (uint256) {
        if (a == 0) {
            return 0;
        }

        // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.
        //
        // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have
        // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.
        //
        // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`
        // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`
        // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`
        //
        // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.
        uint256 result = 1 << (log2(a) >> 1);

        // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,
        // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at
        // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision
        // into the expected uint128 result.
        unchecked {
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            return min(result, a / result);
        }
    }

    /**
     * @notice Calculates sqrt(a), following the selected rounding direction.
     */
    function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = sqrt(a);
            return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 2, rounded down, of a positive value.
     * Returns 0 if given 0.
     */
    function log2(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >> 128 > 0) {
                value >>= 128;
                result += 128;
            }
            if (value >> 64 > 0) {
                value >>= 64;
                result += 64;
            }
            if (value >> 32 > 0) {
                value >>= 32;
                result += 32;
            }
            if (value >> 16 > 0) {
                value >>= 16;
                result += 16;
            }
            if (value >> 8 > 0) {
                value >>= 8;
                result += 8;
            }
            if (value >> 4 > 0) {
                value >>= 4;
                result += 4;
            }
            if (value >> 2 > 0) {
                value >>= 2;
                result += 2;
            }
            if (value >> 1 > 0) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 2, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log2(value);
            return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 10, rounded down, of a positive value.
     * Returns 0 if given 0.
     */
    function log10(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >= 10**64) {
                value /= 10**64;
                result += 64;
            }
            if (value >= 10**32) {
                value /= 10**32;
                result += 32;
            }
            if (value >= 10**16) {
                value /= 10**16;
                result += 16;
            }
            if (value >= 10**8) {
                value /= 10**8;
                result += 8;
            }
            if (value >= 10**4) {
                value /= 10**4;
                result += 4;
            }
            if (value >= 10**2) {
                value /= 10**2;
                result += 2;
            }
            if (value >= 10**1) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 10, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log10(value);
            return result + (rounding == Rounding.Up && 10**result < value ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 256, rounded down, of a positive value.
     * Returns 0 if given 0.
     *
     * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
     */
    function log256(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >> 128 > 0) {
                value >>= 128;
                result += 16;
            }
            if (value >> 64 > 0) {
                value >>= 64;
                result += 8;
            }
            if (value >> 32 > 0) {
                value >>= 32;
                result += 4;
            }
            if (value >> 16 > 0) {
                value >>= 16;
                result += 2;
            }
            if (value >> 8 > 0) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 10, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log256(value);
            return result + (rounding == Rounding.Up && 1 << (result * 8) < value ? 1 : 0);
        }
    }
}

File 12 of 19 : Proxy.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;

import {IAlligator} from "./interfaces/IAlligator.sol";
import {IENSReverseRegistrar} from "./interfaces/IENSReverseRegistrar.sol";
import {IERC1271} from "@openzeppelin/contracts/interfaces/IERC1271.sol";

contract Proxy is IERC1271 {
    address internal immutable alligator;
    address internal immutable governor;

    constructor(address _governor) {
        alligator = msg.sender;
        governor = _governor;
    }

    function isValidSignature(bytes32 hash, bytes calldata signature) external view override returns (bytes4) {
        return IAlligator(alligator).isValidProxySignature(address(this), hash, signature);
    }

    function setENSReverseRecord(string calldata name) external {
        require(msg.sender == alligator);
        IENSReverseRegistrar(0x084b1c3C81545d370f3634392De611CaaBFf8148).setName(name);
    }

    fallback() external payable {
        require(msg.sender == alligator);
        address addr = governor;

        assembly {
            calldatacopy(0, 0, calldatasize())
            let result := call(gas(), addr, callvalue(), 0, calldatasize(), 0, 0)
            returndatacopy(0, 0, returndatasize())
            switch result
            case 0 {
                revert(0, returndatasize())
            }
            default {
                return(0, returndatasize())
            }
        }
    }

    // `receive` is omitted to minimize contract size
}

File 13 of 19 : IAlligator.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;

import "../structs/Rules.sol";

interface IAlligator {
    // =============================================================
    //                             EVENTS
    // =============================================================

    event ProxyDeployed(address indexed owner, address proxy);
    event SubDelegation(address indexed from, address indexed to, Rules rules);
    event SubDelegations(address indexed from, address[] to, Rules[] rules);
    event VoteCast(
        address indexed proxy,
        address indexed voter,
        address[] authority,
        uint256 proposalId,
        uint8 support
    );
    event VotesCast(
        address[] proxies,
        address indexed voter,
        address[][] authorities,
        uint256 proposalId,
        uint8 support
    );
    event Signed(address indexed proxy, address[] authority, bytes32 messageHash);
    event RefundableVote(address indexed voter, uint256 refundAmount, bool refundSent);

    // =============================================================
    //                       WRITE FUNCTIONS
    // =============================================================

    function create(address owner, bool registerEnsName) external returns (address endpoint);

    function registerProxyDeployment(address owner) external;

    function propose(
        address[] calldata authority,
        address[] calldata targets,
        uint256[] calldata values,
        string[] calldata signatures,
        bytes[] calldata calldatas,
        string calldata description
    ) external returns (uint256 proposalId);

    function castVote(address[] calldata authority, uint256 proposalId, uint8 support) external;

    function castVoteWithReason(
        address[] calldata authority,
        uint256 proposalId,
        uint8 support,
        string calldata reason
    ) external;

    function castVotesWithReasonBatched(
        address[][] calldata authorities,
        uint256 proposalId,
        uint8 support,
        string calldata reason
    ) external;

    function castRefundableVotesWithReasonBatched(
        address[][] calldata authorities,
        uint256 proposalId,
        uint8 support,
        string calldata reason
    ) external;

    function castVoteBySig(
        address[] calldata authority,
        uint256 proposalId,
        uint8 support,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external;

    function sign(address[] calldata authority, bytes32 hash) external;

    function subDelegate(address to, Rules calldata rules, bool createProxy) external;

    function subDelegateBatched(address[] calldata targets, Rules[] calldata rules, bool createProxy) external;

    function _togglePause() external;

    // // =============================================================
    // //                         VIEW FUNCTIONS
    // // =============================================================

    function validate(
        address sender,
        address[] memory authority,
        uint256 permissions,
        uint256 proposalId,
        uint256 support
    ) external view;

    function isValidProxySignature(
        address proxy,
        bytes32 hash,
        bytes calldata data
    ) external view returns (bytes4 magicValue);

    function proxyAddress(address owner) external view returns (address endpoint);
}

File 14 of 19 : IENSReverseRegistrar.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;

interface IENSReverseRegistrar {
    function setName(string memory name) external returns (bytes32 node);
}

File 15 of 19 : IGovernorBravo.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;

interface IGovernorBravo {
    function quorumVotes() external view returns (uint256);

    function votingDelay() external view returns (uint256);

    function votingPeriod() external view returns (uint256);

    function propose(
        address[] memory targets,
        uint256[] memory values,
        string[] memory signatures,
        bytes[] memory calldatas,
        string memory description
    ) external returns (uint256);

    function castVote(uint256 proposalId, uint8 support) external;

    function queue(uint256 proposalId) external;

    function execute(uint256 proposalId) external;
}

File 16 of 19 : INounsDAOV2.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;

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

interface INounsDAOV2 is IGovernorBravo {
    struct ProposalCondensed {
        /// @notice Unique id for looking up a proposal
        uint256 id;
        /// @notice Creator of the proposal
        address proposer;
        /// @notice The number of votes needed to create a proposal at the time of proposal creation. *DIFFERS from GovernerBravo
        uint256 proposalThreshold;
        /// @notice The minimum number of votes in support of a proposal required in order for a quorum to be reached and for a vote to succeed at the time of proposal creation. *DIFFERS from GovernerBravo
        uint256 quorumVotes;
        /// @notice The timestamp that the proposal will be available for execution, set once the vote succeeds
        uint256 eta;
        /// @notice The block at which voting begins: holders must delegate their votes prior to this block
        uint256 startBlock;
        /// @notice The block at which voting ends: votes must be cast prior to this block
        uint256 endBlock;
        /// @notice Current number of votes in favor of this proposal
        uint256 forVotes;
        /// @notice Current number of votes in opposition to this proposal
        uint256 againstVotes;
        /// @notice Current number of votes for abstaining for this proposal
        uint256 abstainVotes;
        /// @notice Flag marking whether the proposal has been canceled
        bool canceled;
        /// @notice Flag marking whether the proposal has been vetoed
        bool vetoed;
        /// @notice Flag marking whether the proposal has been executed
        bool executed;
        /// @notice The total supply at the time of proposal creation
        uint256 totalSupply;
        /// @notice The block at which this proposal was created
        uint256 creationBlock;
    }

    function castRefundableVote(uint256 proposalId, uint8 support) external;

    function castRefundableVoteWithReason(uint256 proposalId, uint8 support, string calldata reason) external;

    function castVoteWithReason(uint256 proposalId, uint8 support, string calldata reason) external;

    function castVoteBySig(uint256 proposalId, uint8 support, uint8 v, bytes32 r, bytes32 s) external;

    function proposals(uint256 proposalId) external view returns (ProposalCondensed memory);

    function getActions(
        uint256 proposalId
    )
        external
        view
        returns (
            address[] memory targets,
            uint256[] memory values,
            string[] memory signatures,
            bytes[] memory calldatas
        );
}

File 17 of 19 : IRule.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;

interface IRule {
    /**
     * @notice A custom rule that validates that the voter can cast a vote or propose a proposal
     * @param governor The address of the GovernorBravo contract
     * @param voter The final delegatee that's casting the vote
     * @param proposalId The id of the proposal to vote on
     * @param support The support value for the vote. 0=against, 1=for, 2=abstain, 0xff=propose
     * @return IRule.validate.selector
     */
    function validate(
        address governor,
        address voter,
        uint256 proposalId,
        uint8 support
    ) external view returns (bytes4);
}

File 18 of 19 : Rules.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;

struct Rules {
    uint8 permissions;
    uint8 maxRedelegations;
    uint32 notValidBefore;
    uint32 notValidAfter;
    uint16 blocksBeforeVoteCloses;
    address customRule;
}

File 19 of 19 : ENSHelper.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;

import {Strings} from "@openzeppelin/contracts/utils/Strings.sol";
import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol";
import {IAddrResolver} from "ens-contracts/resolvers/profiles/IAddrResolver.sol";
import {ENS} from "ens-contracts/registry/ENS.sol";

contract ENSHelper is IERC165, IAddrResolver {
    error AlreadyRegistered();

    string public ensName;
    bytes32 internal immutable ensNameHash;
    uint256 internal numberOfProxiesDeployed;
    mapping(bytes32 => address) public nodehashToAddress;
    mapping(address => bool) public registeredProxyAddresses;

    constructor(string memory _ensName, bytes32 _ensNameHash) {
        ensNameHash = _ensNameHash;
        ensName = _ensName;
    }

    function registerDeployment(address _addr) internal returns (string memory reverseENSName) {
        if (registeredProxyAddresses[_addr]) {
            revert AlreadyRegistered();
        }

        /// @dev Cannot overflow uint256 counter by incrementing 1 at a time
        unchecked {
            ++numberOfProxiesDeployed;
        }

        string memory subdomain = Strings.toString(numberOfProxiesDeployed);
        reverseENSName = string.concat(subdomain, ".", ensName);

        bytes32 label = keccak256(abi.encodePacked(subdomain));
        bytes32 namehash = keccak256(abi.encodePacked(ensNameHash, label));
        nodehashToAddress[namehash] = _addr;
        registeredProxyAddresses[_addr] = true;

        ENS(0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e).setSubnodeRecord(
            ensNameHash,
            label,
            address(this),
            address(this),
            0
        );
    }

    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
        return interfaceId == type(IAddrResolver).interfaceId || interfaceId == type(IERC165).interfaceId;
    }

    function addr(bytes32 node) public view virtual override returns (address payable) {
        return payable(nodehashToAddress[node]);
    }
}

Settings
{
  "remappings": [
    "@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/",
    "base64-sol/=lib/base64/",
    "base64/=lib/base64/",
    "ds-test/=lib/forge-std/lib/ds-test/src/",
    "ens-contracts/=lib/ens-contracts/contracts/",
    "forge-std/=lib/forge-std/src/",
    "noun-contracts/=lib/nouns-monorepo/packages/nouns-contracts/contracts/",
    "nouns-monorepo/=lib/nouns-monorepo/",
    "openzeppelin-contracts/=lib/openzeppelin-contracts/"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "metadata": {
    "bytecodeHash": "ipfs",
    "appendCBOR": true
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "evmVersion": "london",
  "libraries": {}
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"contract INounsDAOV2","name":"_governor","type":"address"},{"internalType":"string","name":"_ensName","type":"string"},{"internalType":"bytes32","name":"_ensNameHash","type":"bytes32"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AlreadyRegistered","type":"error"},{"inputs":[],"name":"BadSignature","type":"error"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"address","name":"customRule","type":"address"}],"name":"InvalidCustomRule","type":"error"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"requiredPermissions","type":"uint256"}],"name":"NotDelegated","type":"error"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"wasValidUntil","type":"uint256"}],"name":"NotValidAnymore","type":"error"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"willBeValidFrom","type":"uint256"}],"name":"NotValidYet","type":"error"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"blocksBeforeVoteCloses","type":"uint256"}],"name":"TooEarly","type":"error"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"}],"name":"TooManyRedelegations","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":false,"internalType":"address","name":"a","type":"address"}],"name":"AddrChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"address","name":"proxy","type":"address"}],"name":"ProxyDeployed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"voter","type":"address"},{"indexed":false,"internalType":"uint256","name":"refundAmount","type":"uint256"},{"indexed":false,"internalType":"bool","name":"refundSent","type":"bool"}],"name":"RefundableVote","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"proxy","type":"address"},{"indexed":false,"internalType":"address[]","name":"authority","type":"address[]"},{"indexed":false,"internalType":"bytes32","name":"messageHash","type":"bytes32"}],"name":"Signed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"components":[{"internalType":"uint8","name":"permissions","type":"uint8"},{"internalType":"uint8","name":"maxRedelegations","type":"uint8"},{"internalType":"uint32","name":"notValidBefore","type":"uint32"},{"internalType":"uint32","name":"notValidAfter","type":"uint32"},{"internalType":"uint16","name":"blocksBeforeVoteCloses","type":"uint16"},{"internalType":"address","name":"customRule","type":"address"}],"indexed":false,"internalType":"struct Rules","name":"rules","type":"tuple"}],"name":"SubDelegation","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"address[]","name":"to","type":"address[]"},{"components":[{"internalType":"uint8","name":"permissions","type":"uint8"},{"internalType":"uint8","name":"maxRedelegations","type":"uint8"},{"internalType":"uint32","name":"notValidBefore","type":"uint32"},{"internalType":"uint32","name":"notValidAfter","type":"uint32"},{"internalType":"uint16","name":"blocksBeforeVoteCloses","type":"uint16"},{"internalType":"address","name":"customRule","type":"address"}],"indexed":false,"internalType":"struct Rules[]","name":"rules","type":"tuple[]"}],"name":"SubDelegations","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"proxy","type":"address"},{"indexed":true,"internalType":"address","name":"voter","type":"address"},{"indexed":false,"internalType":"address[]","name":"authority","type":"address[]"},{"indexed":false,"internalType":"uint256","name":"proposalId","type":"uint256"},{"indexed":false,"internalType":"uint8","name":"support","type":"uint8"}],"name":"VoteCast","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address[]","name":"proxies","type":"address[]"},{"indexed":true,"internalType":"address","name":"voter","type":"address"},{"indexed":false,"internalType":"address[][]","name":"authorities","type":"address[][]"},{"indexed":false,"internalType":"uint256","name":"proposalId","type":"uint256"},{"indexed":false,"internalType":"uint8","name":"support","type":"uint8"}],"name":"VotesCast","type":"event"},{"inputs":[],"name":"MAX_REFUND_BASE_FEE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_REFUND_GAS_USED","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_REFUND_PRIORITY_FEE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"REFUND_BASE_GAS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_togglePause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"addr","outputs":[{"internalType":"address payable","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[][]","name":"authorities","type":"address[][]"},{"internalType":"uint256","name":"proposalId","type":"uint256"},{"internalType":"uint8","name":"support","type":"uint8"},{"internalType":"string","name":"reason","type":"string"}],"name":"castRefundableVotesWithReasonBatched","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"authority","type":"address[]"},{"internalType":"uint256","name":"proposalId","type":"uint256"},{"internalType":"uint8","name":"support","type":"uint8"}],"name":"castVote","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"authority","type":"address[]"},{"internalType":"uint256","name":"proposalId","type":"uint256"},{"internalType":"uint8","name":"support","type":"uint8"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"castVoteBySig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"authority","type":"address[]"},{"internalType":"uint256","name":"proposalId","type":"uint256"},{"internalType":"uint8","name":"support","type":"uint8"},{"internalType":"string","name":"reason","type":"string"}],"name":"castVoteWithReason","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[][]","name":"authorities","type":"address[][]"},{"internalType":"uint256","name":"proposalId","type":"uint256"},{"internalType":"uint8","name":"support","type":"uint8"},{"internalType":"string","name":"reason","type":"string"}],"name":"castVotesWithReasonBatched","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"bool","name":"registerEnsName","type":"bool"}],"name":"create","outputs":[{"internalType":"address","name":"endpoint","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"ensName","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"governor","outputs":[{"internalType":"contract INounsDAOV2","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"proxy","type":"address"},{"internalType":"bytes32","name":"hash","type":"bytes32"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"isValidProxySignature","outputs":[{"internalType":"bytes4","name":"magicValue","type":"bytes4"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"nodehashToAddress","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":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"authority","type":"address[]"},{"internalType":"address[]","name":"targets","type":"address[]"},{"internalType":"uint256[]","name":"values","type":"uint256[]"},{"internalType":"string[]","name":"signatures","type":"string[]"},{"internalType":"bytes[]","name":"calldatas","type":"bytes[]"},{"internalType":"string","name":"description","type":"string"}],"name":"propose","outputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"proxyAddress","outputs":[{"internalType":"address","name":"endpoint","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"registerProxyDeployment","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"registeredProxyAddresses","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"authority","type":"address[]"},{"internalType":"bytes32","name":"hash","type":"bytes32"}],"name":"sign","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"components":[{"internalType":"uint8","name":"permissions","type":"uint8"},{"internalType":"uint8","name":"maxRedelegations","type":"uint8"},{"internalType":"uint32","name":"notValidBefore","type":"uint32"},{"internalType":"uint32","name":"notValidAfter","type":"uint32"},{"internalType":"uint16","name":"blocksBeforeVoteCloses","type":"uint16"},{"internalType":"address","name":"customRule","type":"address"}],"internalType":"struct Rules","name":"rules","type":"tuple"},{"internalType":"bool","name":"createProxy","type":"bool"}],"name":"subDelegate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"targets","type":"address[]"},{"components":[{"internalType":"uint8","name":"permissions","type":"uint8"},{"internalType":"uint8","name":"maxRedelegations","type":"uint8"},{"internalType":"uint32","name":"notValidBefore","type":"uint32"},{"internalType":"uint32","name":"notValidAfter","type":"uint32"},{"internalType":"uint16","name":"blocksBeforeVoteCloses","type":"uint16"},{"internalType":"address","name":"customRule","type":"address"}],"internalType":"struct Rules[]","name":"rules","type":"tuple[]"},{"internalType":"bool","name":"createProxy","type":"bool"}],"name":"subDelegateBatched","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"subDelegations","outputs":[{"internalType":"uint8","name":"permissions","type":"uint8"},{"internalType":"uint8","name":"maxRedelegations","type":"uint8"},{"internalType":"uint32","name":"notValidBefore","type":"uint32"},{"internalType":"uint32","name":"notValidAfter","type":"uint32"},{"internalType":"uint16","name":"blocksBeforeVoteCloses","type":"uint16"},{"internalType":"address","name":"customRule","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address[]","name":"authority","type":"address[]"},{"internalType":"uint256","name":"permissions","type":"uint256"},{"internalType":"uint256","name":"proposalId","type":"uint256"},{"internalType":"uint256","name":"support","type":"uint256"}],"name":"validate","outputs":[],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]

60c06040523480156200001157600080fd5b5060405162004065380380620040658339810160408190526200003491620000f3565b60808190528181600062000049838262000281565b50505062000066620000606200008760201b60201c565b6200008b565b50506004805460ff60a01b191690556001600160a01b031660a0526200034d565b3390565b600480546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b634e487b7160e01b600052604160045260246000fd5b6000806000606084860312156200010957600080fd5b83516001600160a01b03811681146200012157600080fd5b602085810151919450906001600160401b03808211156200014157600080fd5b818701915087601f8301126200015657600080fd5b8151818111156200016b576200016b620000dd565b604051601f8201601f19908116603f01168101908382118183101715620001965762000196620000dd565b816040528281528a86848701011115620001af57600080fd5b600093505b82841015620001d35784840186015181850187015292850192620001b4565b6000868483010152809750505050505050604084015190509250925092565b600181811c908216806200020757607f821691505b6020821081036200022857634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200027c57600081815260208120601f850160051c81016020861015620002575750805b601f850160051c820191505b81811015620002785782815560010162000263565b5050505b505050565b81516001600160401b038111156200029d576200029d620000dd565b620002b581620002ae8454620001f2565b846200022e565b602080601f831160018114620002ed5760008415620002d45750858301515b600019600386901b1c1916600185901b17855562000278565b600085815260208120601f198616915b828110156200031e57888601518255948401946001909101908401620002fd565b50858210156200033d5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60805160a051613cc1620003a4600039600081816102a1015281816108eb01528181610cc601528181610dc60152611ad30152600081816109970152818161172d01528181611dc60152611e620152613cc16000f3fe608060405260043610620001f75760003560e01c80635c975abb116200010b578063bc4cd08411620000a1578063f2fde38b116200006c578063f2fde38b14620006ce578063faa9efe314620006f3578063fbfee8761462000718578063fe5f8fce146200073257600080fd5b8063bc4cd084146200062a578063bd7abaf51462000645578063df827947146200066a578063e2f57fb0146200068f57600080fd5b8063763dc22011620000e2578063763dc22014620005845780638da5cb5b14620005a95780638ef71b8d14620005c9578063b9ffe88e14620005f057600080fd5b80635c975abb1462000526578063715018a61462000547578063730f05b4146200055f57600080fd5b80633b3b57de116200018d5780633dff8de211620001585780633dff8de2146200049f578063405b4c3614620004c45780634ad3822214620004dc578063510e318a146200050157600080fd5b80633b3b57de14620003f45780633b75f7ba146200042e5780633be8ef3f14620004535780633d2d1fa3146200046b57600080fd5b80630c340a2411620001ce5780630c340a24146200028d5780630d6384d014620002dc578063319e909014620003aa578063375d02fa14620003cf57600080fd5b806301ffc9a7146200020457806303a3e6fb146200023e578063042bc3de146200026557600080fd5b36620001ff57005b600080fd5b3480156200021157600080fd5b506200022962000223366004620025e0565b62000757565b60405190151581526020015b60405180910390f35b3480156200024b57600080fd5b50620002636200025d3660046200269b565b6200078f565b005b3480156200027257600080fd5b506200027e62030d4081565b60405190815260200162000235565b3480156200029a57600080fd5b50620002c37f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b03909116815260200162000235565b348015620002e957600080fd5b5062000360620002fb36600462002747565b600560209081526000928352604080842090915290825290205460ff8082169161010081049091169063ffffffff620100008204811691660100000000000081049091169061ffff600160501b820416906001600160a01b03600160601b9091041686565b6040805160ff978816815296909516602087015263ffffffff938416948601949094529116606084015261ffff1660808301526001600160a01b031660a082015260c00162000235565b348015620003b757600080fd5b50620002c3620003c9366004620027a6565b620008da565b348015620003dc57600080fd5b5062000263620003ee366004620028e1565b62000a35565b3480156200040157600080fd5b50620002c36200041336600462002951565b6000908152600260205260409020546001600160a01b031690565b3480156200043b57600080fd5b50620002636200044d3660046200296b565b62000f0e565b3480156200046057600080fd5b506200027e618ca081565b3480156200047857600080fd5b50620002296200048a366004620029cf565b60036020526000908152604090205460ff1681565b348015620004ac57600080fd5b5062000263620004be3660046200269b565b6200103d565b348015620004d157600080fd5b506200026362001255565b348015620004e957600080fd5b5062000263620004fb366004620029ef565b62001287565b3480156200050e57600080fd5b50620002636200052036600462002a7c565b62001552565b3480156200053357600080fd5b50600454600160a01b900460ff1662000229565b3480156200055457600080fd5b50620002636200160b565b3480156200056c57600080fd5b506200027e6200057e36600462002ad8565b62001621565b3480156200059157600080fd5b5062000263620005a3366004620029cf565b6200172b565b348015620005b657600080fd5b506004546001600160a01b0316620002c3565b348015620005d657600080fd5b50620005e1620017d9565b60405162000235919062002c4e565b348015620005fd57600080fd5b50620002c36200060f36600462002951565b6002602052600090815260409020546001600160a01b031681565b3480156200063757600080fd5b506200027e642e90edd00081565b3480156200065257600080fd5b5062000263620006643660046200269b565b6200186f565b3480156200067757600080fd5b50620002636200068936600462002c83565b62001899565b3480156200069c57600080fd5b50620006b4620006ae36600462002cd2565b62001979565b6040516001600160e01b0319909116815260200162000235565b348015620006db57600080fd5b5062000263620006ed366004620029cf565b62001a15565b3480156200070057600080fd5b50620002c362000712366004620029cf565b62001a91565b3480156200072557600080fd5b506200027e637735940081565b3480156200073f57600080fd5b50620002636200075136600462002d33565b62001b9d565b60006001600160e01b03198216631d9dabef60e11b14806200078957506001600160e01b031982166301ffc9a760e01b145b92915050565b6200079962001cc7565b620007e033878780806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250600192508991505060ff881662000a35565b60006200081387876000818110620007fc57620007fc62002ded565b9050602002016020810190620007129190620029cf565b604051637b3c71d360e01b81529091506001600160a01b03821690637b3c71d3906200084a90889088908890889060040162002e2c565b600060405180830381600087803b1580156200086557600080fd5b505af11580156200087a573d6000803e3d6000fd5b50505050336001600160a01b0316816001600160a01b03167f06ef67f52c465c176e4d3ee623ffe1051cdb317e1604d4726aa8b6b332236d5b89898989604051620008c9949392919062002ea8565b60405180910390a350505050505050565b6000826001600160a01b031660001b7f00000000000000000000000000000000000000000000000000000000000000006040516200091890620025bb565b6001600160a01b0390911681526020018190604051809103906000f590508015801562000949573d6000803e3d6000fd5b506040516001600160a01b038083168252919250908416907f3d2489efb661e8b1c3679865db649ca1de61d76a71184a1234de2e55786a6aad9060200160405180910390a2811562000789577f00000000000000000000000000000000000000000000000000000000000000001562000789576000620009c98262001d16565b60405163a2c0625b60e01b81529091506001600160a01b0383169063a2c0625b90620009fa90849060040162002c4e565b600060405180830381600087803b15801562000a1557600080fd5b505af115801562000a2a573d6000803e3d6000fd5b505050505092915050565b60008460008151811062000a4d5762000a4d62002ded565b60200260200101519050856001600160a01b0316816001600160a01b03160362000a78575062000f07565b84516040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260015b8381101562000eae5788818151811062000acc5762000acc62002ded565b6020908102919091018101516001600160a01b0380881660009081526005845260408082208385168352855290819020815160c081018352905460ff8082168352610100820481169683019690965263ffffffff62010000820481169383019390935266010000000000008104909216606082015261ffff600160501b8304166080820152600160601b820490921660a08301529195509350891616881462000ba75760405163171d38a560e31b81526001600160a01b03808716600483015284166024820152604481018990526064015b60405180910390fd5b8381836020015160ff1601600101101562000be957604051635b58eeaf60e11b81526001600160a01b0380871660048301528416602482015260440162000b9e565b816040015163ffffffff1642101562000c3b576040808301519051633a7fae6b60e21b81526001600160a01b0380881660048301528516602482015263ffffffff909116604482015260640162000b9e565b606082015163ffffffff161562000c9e57816060015163ffffffff1642111562000c9e57606082015160405163345761bb60e21b81526001600160a01b0380881660048301528516602482015263ffffffff909116604482015260640162000b9e565b608082015161ffff161562000d955760405163013cf08b60e01b8152600481018890526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063013cf08b906024016101e060405180830381865afa15801562000d17573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000d3d919062002ef2565b9050826080015161ffff1643018160c00151111562000d935760808301516040516307672a3160e11b81526001600160a01b0380891660048301528616602482015261ffff909116604482015260640162000b9e565b505b60a08201516001600160a01b03161562000ea05760a082015160405163c6306e0960e01b8082526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660048401528d81166024840152604483018b905260ff8a1660648401529092169063c6306e0990608401602060405180830381865afa15801562000e2f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000e55919062002fd6565b6001600160e01b0319161462000ea05760a082015160405163b8ec230160e01b81526001600160a01b0380881660048301528086166024830152909116604482015260640162000b9e565b919350839160010162000aae565b50886001600160a01b0316846001600160a01b03160362000ed3575050505062000f07565b60405163171d38a560e31b81526001600160a01b0380861660048301528a1660248201526044810188905260640162000b9e565b5050505050565b62000f1862001cc7565b62000f5f33858580806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250600192508791505060ff861662000a35565b600062000f7b85856000818110620007fc57620007fc62002ded565b604051630acf027160e31b81526004810185905260ff841660248201529091506001600160a01b03821690635678138890604401600060405180830381600087803b15801562000fca57600080fd5b505af115801562000fdf573d6000803e3d6000fd5b50505050336001600160a01b0316816001600160a01b03167f06ef67f52c465c176e4d3ee623ffe1051cdb317e1604d4726aa8b6b332236d5b878787876040516200102e949392919062002ea8565b60405180910390a35050505050565b6200104762001cc7565b6000856001600160401b03811115620010645762001064620027d9565b6040519080825280602002602001820160405280156200108e578160200160208202803683370190505b509050606060005b87811015620011ff57888882818110620010b457620010b462002ded565b9050602002810190620010c8919062002ff6565b8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525092945062001112925033915084905060018a60ff8b1662000a35565b6200113a826000815181106200112c576200112c62002ded565b602002602001015162001a91565b8382815181106200114f576200114f62002ded565b60200260200101906001600160a01b031690816001600160a01b03168152505082818151811062001184576200118462002ded565b60200260200101516001600160a01b0316637b3c71d3888888886040518563ffffffff1660e01b8152600401620011bf949392919062002e2c565b600060405180830381600087803b158015620011da57600080fd5b505af1158015620011ef573d6000803e3d6000fd5b5050505080600101905062001096565b50336001600160a01b03167ff155d545bf480c6d3cdc5d24c9f9364e30d161c58059bcced24aa6e5e3738eb8838a8a8a8a6040516200124395949392919062003042565b60405180910390a25050505050505050565b6200125f62001ef7565b600454600160a01b900460ff166200127d576200127b62001f53565b565b6200127b62001fb6565b6200129162001cc7565b604080517f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a8666020808301919091527f862db59105a1338741f3c46ee49a3dc764d93a40b2bbba404e37282178ba316382840152466060830152306080808401919091528351808403909101815260a0830184528051908201207f150214d74d59b7d1e90c73fc22ef3d991dd0a76b046543d4d80ab92d2a50328f60c084015260e0830189905260ff8816610100808501919091528451808503909101815261012084019094528351939091019290922061190160f01b61014083015261014282018390526101628201819052906000906101820160408051601f198184030181528282528051602091820120600080855291840180845281905260ff8a169284019290925260608301889052608083018790529092509060019060a0016020604051602081039080840390855afa158015620013f1573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166200142657604051635cd5d23360e01b815260040160405180910390fd5b6200146d818c8c80806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250600192508e91505060ff8d1662000a35565b6000620014898c8c6000818110620007fc57620007fc62002ded565b604051630acf027160e31b8152600481018c905260ff8b1660248201529091506001600160a01b03821690635678138890604401600060405180830381600087803b158015620014d857600080fd5b505af1158015620014ed573d6000803e3d6000fd5b50505050816001600160a01b0316816001600160a01b03167f06ef67f52c465c176e4d3ee623ffe1051cdb317e1604d4726aa8b6b332236d5b8e8e8e8e6040516200153c949392919062002ea8565b60405180910390a3505050505050505050505050565b80156200158557620015643362001a91565b6001600160a01b03163b600003620015855762001583336000620008da565b505b3360009081526005602090815260408083206001600160a01b038716845290915290208290620015b682826200318b565b905050826001600160a01b0316336001600160a01b03167f5a522316a2409724571357d08b150ddc1b9788dfb0171301e40591e9b4f8b09084604051620015fe919062003347565b60405180910390a3505050565b6200161562001ef7565b6200127b600062001ff5565b60006200162d62001cc7565b6000620016498e8e6000818110620007fc57620007fc62002ded565b604051636d4ab48d60e11b81529091506001600160a01b0382169063da95691a906200168c908f908f908f908f908f908f908f908f908f908f9060040162003405565b6020604051808303816000875af1158015620016ac573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620016d29190620034f7565b91506200171a338f8f808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152506004925087915060ff905062000a35565b509c9b505050505050505050505050565b7f000000000000000000000000000000000000000000000000000000000000000015620017d65760006200175f8262001a91565b905060006200176e8262001d16565b60405163a2c0625b60e01b81529091506001600160a01b0383169063a2c0625b906200179f90849060040162002c4e565b600060405180830381600087803b158015620017ba57600080fd5b505af1158015620017cf573d6000803e3d6000fd5b5050505050505b50565b60008054620017e89062003511565b80601f0160208091040260200160405190810160405280929190818152602001828054620018169062003511565b8015620018675780601f106200183b5761010080835404028352916020019162001867565b820191906000526020600020905b8154815290600101906020018083116200184957829003601f168201915b505050505081565b6200187962001cc7565b60005a90506200188e8787878787876200103d565b620017cf8162002047565b620018a362001cc7565b620018e733848480806020026020016040519081016040528093929190818152602001838360200280828437600092018290525060029350915060fe905062000a35565b60006200190384846000818110620007fc57620007fc62002ded565b6001600160a01b038116600081815260066020908152604080832087845290915290819020805460ff1916600117905551919250907f98686f9e3e1d53509f68f7099a7561989e030ede5d7a4f89e63d50b859da9e38906200196b908790879087906200354d565b60405180910390a250505050565b60008115620019cd57600080620019938486018662003573565b915091506000620019a5878362002140565b9050620019b981846002600060fe62000a35565b50630b135d3f60e11b925062001a0d915050565b6001600160a01b038516600090815260066020908152604080832087845290915290205460ff1662001a0157600062001a0a565b630b135d3f60e11b5b90505b949350505050565b62001a1f62001ef7565b6001600160a01b03811662001a865760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b606482015260840162000b9e565b620017d68162001ff5565b6040516000906001600160f81b03199030906001600160a01b0385169062001abc60208201620025bb565b601f1982820381018352601f9091011660408181527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031660208301520160408051601f198184030181529082905262001b21929160200162003635565b6040516020818303038152906040528051906020012060405160200162001b7f94939291906001600160f81b031994909416845260609290921b6bffffffffffffffffffffffff191660018401526015830152603582015260550190565b60408051601f19818403018152919052805160209091012092915050565b83821462001baa57600080fd5b801562001bdd5762001bbc3362001a91565b6001600160a01b03163b60000362001bdd5762001bdb336000620008da565b505b60005b8481101562001c765783838281811062001bfe5762001bfe62002ded565b33600090815260056020526040812060c0909202939093019290915088888581811062001c2f5762001c2f62002ded565b905060200201602081019062001c469190620029cf565b6001600160a01b03168152602081019190915260400160002062001c6b82826200318b565b505060010162001be0565b50336001600160a01b03167f9c0c1ce513ac44df340d0f04a9c6044a96f1509d359a48b5da21992b72d568a48686868660405162001cb8949392919062003668565b60405180910390a25050505050565b600454600160a01b900460ff16156200127b5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b604482015260640162000b9e565b6001600160a01b03811660009081526003602052604090205460609060ff161562001d5457604051630ea075bf60e21b815260040160405180910390fd5b6001805481019081905560009062001d6c9062002168565b905080600060405160200162001d84929190620036c8565b604051602081830303815290604052915060008160405160200162001daa919062003795565b60405160208183030381529060405280519060200120905060007f00000000000000000000000000000000000000000000000000000000000000008260405160200162001e01929190918252602082015260400190565b60408051808303601f19018152828252805160209182012060008181526002835283812080546001600160a01b0319166001600160a01b038c1690811790915581526003909252918120805460ff191660011790556305ef2c7f60e41b83527f000000000000000000000000000000000000000000000000000000000000000060048401526024830185905230604484018190526064840152608483015291506e0c2e074ec69a0dfb2997ba6c7d2e1e90635ef2c7f09060a401600060405180830381600087803b15801562001ed657600080fd5b505af115801562001eeb573d6000803e3d6000fd5b50505050505050919050565b6004546001600160a01b031633146200127b5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640162000b9e565b62001f5d62001cc7565b6004805460ff60a01b1916600160a01b1790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a25862001f993390565b6040516001600160a01b03909116815260200160405180910390a1565b62001fc062002201565b6004805460ff60a01b191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa3362001f99565b600480546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b47600081900362002056575050565b60006200206948642e90edd00062002253565b905060006200207f3a6377359400840162002253565b9050600062002098618ca05a87030162030d4062002253565b90506000620020aa8284028662002253565b604051909150600090339083908381818185875af1925050503d8060008114620020f1576040519150601f19603f3d011682016040523d82523d6000602084013e620020f6565b606091505b505060408051848152821515602082015291925033917ffabef36fd46c4c3a6ad676521be5367a4dfdbf3faa68d8e826003b1752d68f4f910160405180910390a250505050505050565b60008060006200215185856200226d565b915091506200216081620022b6565b509392505050565b60606000620021778362002413565b60010190506000816001600160401b03811115620021995762002199620027d9565b6040519080825280601f01601f191660200182016040528015620021c4576020820181803683370190505b5090508181016020015b600019016f181899199a1a9b1b9c1cb0b131b232b360811b600a86061a8153600a8504945084620021ce57509392505050565b600454600160a01b900460ff166200127b5760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b604482015260640162000b9e565b600081831062002264578162002266565b825b9392505050565b6000808251604103620022a75760208301516040840151606085015160001a6200229a87828585620024f2565b94509450505050620022af565b506000905060025b9250929050565b6000816004811115620022cd57620022cd620037b3565b03620022d65750565b6001816004811115620022ed57620022ed620037b3565b036200233c5760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e61747572650000000000000000604482015260640162000b9e565b6002816004811115620023535762002353620037b3565b03620023a25760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e67746800604482015260640162000b9e565b6003816004811115620023b957620023b9620037b3565b03620017d65760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b606482015260840162000b9e565b60008072184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b8310620024535772184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b830492506040015b6d04ee2d6d415b85acef8100000000831062002480576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc1000083106200249f57662386f26fc10000830492506010015b6305f5e1008310620024b8576305f5e100830492506008015b6127108310620024cd57612710830492506004015b60648310620024e0576064830492506002015b600a8310620007895760010192915050565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08311156200252b5750600090506003620025b2565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa15801562002580573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116620025ab57600060019250925050620025b2565b9150600090505b94509492505050565b6104c280620037ca83390190565b6001600160e01b031981168114620017d657600080fd5b600060208284031215620025f357600080fd5b81356200226681620025c9565b60008083601f8401126200261357600080fd5b5081356001600160401b038111156200262b57600080fd5b6020830191508360208260051b8501011115620022af57600080fd5b60ff81168114620017d657600080fd5b60008083601f8401126200266a57600080fd5b5081356001600160401b038111156200268257600080fd5b602083019150836020828501011115620022af57600080fd5b60008060008060008060808789031215620026b557600080fd5b86356001600160401b0380821115620026cd57600080fd5b620026db8a838b0162002600565b90985096506020890135955060408901359150620026f98262002647565b909350606088013590808211156200271057600080fd5b506200271f89828a0162002657565b979a9699509497509295939492505050565b6001600160a01b0381168114620017d657600080fd5b600080604083850312156200275b57600080fd5b8235620027688162002731565b915060208301356200277a8162002731565b809150509250929050565b8015158114620017d657600080fd5b8035620027a18162002785565b919050565b60008060408385031215620027ba57600080fd5b8235620027c78162002731565b915060208301356200277a8162002785565b634e487b7160e01b600052604160045260246000fd5b6040516101e081016001600160401b0381118282101715620028155762002815620027d9565b60405290565b604051601f8201601f191681016001600160401b0381118282101715620028465762002846620027d9565b604052919050565b600082601f8301126200286057600080fd5b813560206001600160401b038211156200287e576200287e620027d9565b8160051b6200288f8282016200281b565b9283528481018201928281019087851115620028aa57600080fd5b83870192505b84831015620028d6578235620028c68162002731565b82529183019190830190620028b0565b979650505050505050565b600080600080600060a08688031215620028fa57600080fd5b8535620029078162002731565b945060208601356001600160401b038111156200292357600080fd5b62002931888289016200284e565b959895975050505060408401359360608101359360809091013592509050565b6000602082840312156200296457600080fd5b5035919050565b600080600080606085870312156200298257600080fd5b84356001600160401b038111156200299957600080fd5b620029a78782880162002600565b909550935050602085013591506040850135620029c48162002647565b939692955090935050565b600060208284031215620029e257600080fd5b8135620022668162002731565b600080600080600080600060c0888a03121562002a0b57600080fd5b87356001600160401b0381111562002a2257600080fd5b62002a308a828b0162002600565b90985096505060208801359450604088013562002a4d8162002647565b9350606088013562002a5f8162002647565b969995985093969295946080840135945060a09093013592915050565b600080600083850361010081121562002a9457600080fd5b843562002aa18162002731565b935060c0601f198201121562002ab657600080fd5b5060208401915060e084013562002acd8162002785565b809150509250925092565b60008060008060008060008060008060008060c08d8f03121562002afb57600080fd5b6001600160401b038d35111562002b1157600080fd5b62002b208e8e358f0162002600565b909c509a506001600160401b0360208e0135111562002b3e57600080fd5b62002b508e60208f01358f0162002600565b909a5098506001600160401b0360408e0135111562002b6e57600080fd5b62002b808e60408f01358f0162002600565b90985096506001600160401b0360608e0135111562002b9e57600080fd5b62002bb08e60608f01358f0162002600565b90965094506001600160401b0360808e0135111562002bce57600080fd5b62002be08e60808f01358f0162002600565b90945092506001600160401b0360a08e0135111562002bfe57600080fd5b62002c108e60a08f01358f0162002657565b81935080925050509295989b509295989b509295989b565b60005b8381101562002c4557818101518382015260200162002c2b565b50506000910152565b602081526000825180602084015262002c6f81604085016020870162002c28565b601f01601f19169190910160400192915050565b60008060006040848603121562002c9957600080fd5b83356001600160401b0381111562002cb057600080fd5b62002cbe8682870162002600565b909790965060209590950135949350505050565b6000806000806060858703121562002ce957600080fd5b843562002cf68162002731565b93506020850135925060408501356001600160401b0381111562002d1957600080fd5b62002d278782880162002657565b95989497509550505050565b60008060008060006060868803121562002d4c57600080fd5b85356001600160401b038082111562002d6457600080fd5b62002d7289838a0162002600565b9097509550602088013591508082111562002d8c57600080fd5b818801915088601f83011262002da157600080fd5b81358181111562002db157600080fd5b89602060c08302850101111562002dc757600080fd5b60208301955080945050505062002de16040870162002794565b90509295509295909350565b634e487b7160e01b600052603260045260246000fd5b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b84815260ff8416602082015260606040820152600062002e5160608301848662002e03565b9695505050505050565b8183526000602080850194508260005b8581101562002e9d57813562002e818162002731565b6001600160a01b03168752958201959082019060010162002e6b565b509495945050505050565b60608152600062002ebe60608301868862002e5b565b905083602083015260ff8316604083015295945050505050565b8051620027a18162002731565b8051620027a18162002785565b60006101e0828403121562002f0657600080fd5b62002f10620027ef565b8251815262002f226020840162002ed8565b602082015260408301516040820152606083015160608201526080830151608082015260a083015160a082015260c083015160c082015260e083015160e082015261010080840151818301525061012080840151818301525061014062002f8b81850162002ee5565b9082015261016062002f9f84820162002ee5565b9082015261018062002fb384820162002ee5565b908201526101a083810151908201526101c0928301519281019290925250919050565b60006020828403121562002fe957600080fd5b81516200226681620025c9565b6000808335601e198436030181126200300e57600080fd5b8301803591506001600160401b038211156200302957600080fd5b6020019150600581901b3603821315620022af57600080fd5b6080808252865190820181905260009060209060a0840190828a01845b82811015620030865781516001600160a01b0316845292840192908401906001016200305f565b50505083810382850152868152818101600588811b830184018a60005b8b8110156200311b57858303601f190185528135368e9003601e19018112620030cb57600080fd5b8d0187810190356001600160401b03811115620030e757600080fd5b80861b3603821315620030f957600080fd5b6200310685828462002e5b565b968901969450505090860190600101620030a3565b50506040870189905260ff88166060880152945062002e519350505050565b63ffffffff81168114620017d657600080fd5b6000813562000789816200313a565b61ffff81168114620017d657600080fd5b6000813562000789816200315c565b60008135620007898162002731565b8135620031988162002647565b60ff8116905081548160ff1982161783556020840135620031b98162002647565b61ff008160081b169050808361ffff198416171784556040850135620031df816200313a565b65ffffffff00008160101b168465ffffffffffff198516178317178555505050506200323862003212606084016200314d565b825469ffffffff000000000000191660309190911b69ffffffff00000000000016178255565b6200326a6200324a608084016200316d565b82805461ffff60501b191660509290921b61ffff60501b16919091179055565b620032a66200327c60a084016200317c565b82546bffffffffffffffffffffffff1660609190911b6bffffffffffffffffffffffff1916178255565b5050565b8035620032b78162002647565b60ff1682526020810135620032cc8162002647565b60ff1660208301526040810135620032e4816200313a565b63ffffffff908116604084015260608201359062003302826200313a565b166060830152608081013562003318816200315c565b61ffff16608083015260a0810135620033318162002731565b6001600160a01b031660a0929092019190915250565b60c08101620007898284620032aa565b6000808335601e198436030181126200336f57600080fd5b83016020810192503590506001600160401b038111156200338f57600080fd5b803603821315620022af57600080fd5b60008383855260208086019550808560051b8301018460005b87811015620033f857848303601f19018952620033d6828862003357565b620033e385828462002e03565b9a86019a9450505090830190600101620033b8565b5090979650505050505050565b60a0815260006200341b60a083018c8e62002e5b565b8281036020848101919091528a82526001600160fb1b038b11156200343f57600080fd5b8a60051b808d8385013780830192505080820181858403016040860152808a825260408401905060408b60051b85010191508b60005b8c811015620034b557858403603f1901835262003493828f62003357565b620034a086828462002e03565b95505050918401919084019060010162003475565b5050508481036060860152620034cd81898b6200339f565b925050508281036080840152620034e681858762002e03565b9d9c50505050505050505050505050565b6000602082840312156200350a57600080fd5b5051919050565b600181811c908216806200352657607f821691505b6020821081036200354757634e487b7160e01b600052602260045260246000fd5b50919050565b6040815260006200356360408301858762002e5b565b9050826020830152949350505050565b600080604083850312156200358757600080fd5b82356001600160401b03808211156200359f57600080fd5b620035ad868387016200284e565b9350602091508185013581811115620035c557600080fd5b8501601f81018713620035d757600080fd5b803582811115620035ec57620035ec620027d9565b62003600601f8201601f191685016200281b565b925080835287848284010111156200361757600080fd5b80848301858501376000848285010152505080925050509250929050565b600083516200364981846020880162002c28565b8351908301906200365f81836020880162002c28565b01949350505050565b6040815260006200367e60408301868862002e5b565b82810360208085019190915284825285910160005b85811015620036bc57620036a88284620032aa565b60c092830192919091019060010162003693565b50979650505050505050565b600083516020620036dd828583890162002c28565b601760f91b918401918252845460019060009080831c818416806200370357607f821691505b85821081036200372157634e487b7160e01b84526022600452602484fd5b808015620037385760018114620037525762003785565b60ff19841688870152821515830288018601945062003785565b60008b81526020902060005b848110156200377b5781548a82018901529087019088016200375e565b5050858389010194505b50929a9950505050505050505050565b60008251620037a981846020870162002c28565b9190910192915050565b634e487b7160e01b600052602160045260246000fdfe60c060405234801561001057600080fd5b506040516104c23803806104c283398101604081905261002f91610044565b336080526001600160a01b031660a052610074565b60006020828403121561005657600080fd5b81516001600160a01b038116811461006d57600080fd5b9392505050565b60805160a05161041d6100a56000396000606001526000818160340152818161011d01526101ac015261041d6000f3fe6080604052600436106100295760003560e01c80631626ba7e146100a6578063a2c0625b146100e3575b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461005e57600080fd5b7f0000000000000000000000000000000000000000000000000000000000000000366000803760008036600034855af13d6000803e80801561009f573d6000f35b3d6000fd5b005b3480156100b257600080fd5b506100c66100c13660046102a0565b610103565b6040516001600160e01b0319909116815260200160405180910390f35b3480156100ef57600080fd5b506100a46100fe3660046102ec565b6101a1565b604051630e2f57fb60e41b81526000906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063e2f57fb090610158903090889088908890600401610357565b602060405180830381865afa158015610175573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101999190610389565b949350505050565b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146101d657600080fd5b60405163c47f002760e01b815273084b1c3c81545d370f3634392de611caabff81489063c47f00279061020f90859085906004016103ba565b6020604051808303816000875af115801561022e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061025291906103ce565b505050565b60008083601f84011261026957600080fd5b50813567ffffffffffffffff81111561028157600080fd5b60208301915083602082850101111561029957600080fd5b9250929050565b6000806000604084860312156102b557600080fd5b83359250602084013567ffffffffffffffff8111156102d357600080fd5b6102df86828701610257565b9497909650939450505050565b600080602083850312156102ff57600080fd5b823567ffffffffffffffff81111561031657600080fd5b61032285828601610257565b90969095509350505050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b60018060a01b038516815283602082015260606040820152600061037f60608301848661032e565b9695505050505050565b60006020828403121561039b57600080fd5b81516001600160e01b0319811681146103b357600080fd5b9392505050565b60208152600061019960208301848661032e565b6000602082840312156103e057600080fd5b505191905056fea2646970667358221220f713c761976839ac402290f1ee034e850f179aea67c3319fd22b579944fe7c0564736f6c63430008130033a2646970667358221220b623416f3cab1defcc1541d99e98a31dbabe9b006c764adb8b06e77d6250c60d64736f6c634300081300330000000000000000000000006f3e6272a167e8accb32072d08e0957f9c79223d0000000000000000000000000000000000000000000000000000000000000060b52b0c2d79e4e1940250202dea36651ff7f690bfef59e3077f41248e7b99299700000000000000000000000000000000000000000000000000000000000000136e6f756e732e766f746561676f72612e65746800000000000000000000000000

Deployed Bytecode

0x608060405260043610620001f75760003560e01c80635c975abb116200010b578063bc4cd08411620000a1578063f2fde38b116200006c578063f2fde38b14620006ce578063faa9efe314620006f3578063fbfee8761462000718578063fe5f8fce146200073257600080fd5b8063bc4cd084146200062a578063bd7abaf51462000645578063df827947146200066a578063e2f57fb0146200068f57600080fd5b8063763dc22011620000e2578063763dc22014620005845780638da5cb5b14620005a95780638ef71b8d14620005c9578063b9ffe88e14620005f057600080fd5b80635c975abb1462000526578063715018a61462000547578063730f05b4146200055f57600080fd5b80633b3b57de116200018d5780633dff8de211620001585780633dff8de2146200049f578063405b4c3614620004c45780634ad3822214620004dc578063510e318a146200050157600080fd5b80633b3b57de14620003f45780633b75f7ba146200042e5780633be8ef3f14620004535780633d2d1fa3146200046b57600080fd5b80630c340a2411620001ce5780630c340a24146200028d5780630d6384d014620002dc578063319e909014620003aa578063375d02fa14620003cf57600080fd5b806301ffc9a7146200020457806303a3e6fb146200023e578063042bc3de146200026557600080fd5b36620001ff57005b600080fd5b3480156200021157600080fd5b506200022962000223366004620025e0565b62000757565b60405190151581526020015b60405180910390f35b3480156200024b57600080fd5b50620002636200025d3660046200269b565b6200078f565b005b3480156200027257600080fd5b506200027e62030d4081565b60405190815260200162000235565b3480156200029a57600080fd5b50620002c37f0000000000000000000000006f3e6272a167e8accb32072d08e0957f9c79223d81565b6040516001600160a01b03909116815260200162000235565b348015620002e957600080fd5b5062000360620002fb36600462002747565b600560209081526000928352604080842090915290825290205460ff8082169161010081049091169063ffffffff620100008204811691660100000000000081049091169061ffff600160501b820416906001600160a01b03600160601b9091041686565b6040805160ff978816815296909516602087015263ffffffff938416948601949094529116606084015261ffff1660808301526001600160a01b031660a082015260c00162000235565b348015620003b757600080fd5b50620002c3620003c9366004620027a6565b620008da565b348015620003dc57600080fd5b5062000263620003ee366004620028e1565b62000a35565b3480156200040157600080fd5b50620002c36200041336600462002951565b6000908152600260205260409020546001600160a01b031690565b3480156200043b57600080fd5b50620002636200044d3660046200296b565b62000f0e565b3480156200046057600080fd5b506200027e618ca081565b3480156200047857600080fd5b50620002296200048a366004620029cf565b60036020526000908152604090205460ff1681565b348015620004ac57600080fd5b5062000263620004be3660046200269b565b6200103d565b348015620004d157600080fd5b506200026362001255565b348015620004e957600080fd5b5062000263620004fb366004620029ef565b62001287565b3480156200050e57600080fd5b50620002636200052036600462002a7c565b62001552565b3480156200053357600080fd5b50600454600160a01b900460ff1662000229565b3480156200055457600080fd5b50620002636200160b565b3480156200056c57600080fd5b506200027e6200057e36600462002ad8565b62001621565b3480156200059157600080fd5b5062000263620005a3366004620029cf565b6200172b565b348015620005b657600080fd5b506004546001600160a01b0316620002c3565b348015620005d657600080fd5b50620005e1620017d9565b60405162000235919062002c4e565b348015620005fd57600080fd5b50620002c36200060f36600462002951565b6002602052600090815260409020546001600160a01b031681565b3480156200063757600080fd5b506200027e642e90edd00081565b3480156200065257600080fd5b5062000263620006643660046200269b565b6200186f565b3480156200067757600080fd5b50620002636200068936600462002c83565b62001899565b3480156200069c57600080fd5b50620006b4620006ae36600462002cd2565b62001979565b6040516001600160e01b0319909116815260200162000235565b348015620006db57600080fd5b5062000263620006ed366004620029cf565b62001a15565b3480156200070057600080fd5b50620002c362000712366004620029cf565b62001a91565b3480156200072557600080fd5b506200027e637735940081565b3480156200073f57600080fd5b50620002636200075136600462002d33565b62001b9d565b60006001600160e01b03198216631d9dabef60e11b14806200078957506001600160e01b031982166301ffc9a760e01b145b92915050565b6200079962001cc7565b620007e033878780806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250600192508991505060ff881662000a35565b60006200081387876000818110620007fc57620007fc62002ded565b9050602002016020810190620007129190620029cf565b604051637b3c71d360e01b81529091506001600160a01b03821690637b3c71d3906200084a90889088908890889060040162002e2c565b600060405180830381600087803b1580156200086557600080fd5b505af11580156200087a573d6000803e3d6000fd5b50505050336001600160a01b0316816001600160a01b03167f06ef67f52c465c176e4d3ee623ffe1051cdb317e1604d4726aa8b6b332236d5b89898989604051620008c9949392919062002ea8565b60405180910390a350505050505050565b6000826001600160a01b031660001b7f0000000000000000000000006f3e6272a167e8accb32072d08e0957f9c79223d6040516200091890620025bb565b6001600160a01b0390911681526020018190604051809103906000f590508015801562000949573d6000803e3d6000fd5b506040516001600160a01b038083168252919250908416907f3d2489efb661e8b1c3679865db649ca1de61d76a71184a1234de2e55786a6aad9060200160405180910390a2811562000789577fb52b0c2d79e4e1940250202dea36651ff7f690bfef59e3077f41248e7b9929971562000789576000620009c98262001d16565b60405163a2c0625b60e01b81529091506001600160a01b0383169063a2c0625b90620009fa90849060040162002c4e565b600060405180830381600087803b15801562000a1557600080fd5b505af115801562000a2a573d6000803e3d6000fd5b505050505092915050565b60008460008151811062000a4d5762000a4d62002ded565b60200260200101519050856001600160a01b0316816001600160a01b03160362000a78575062000f07565b84516040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260015b8381101562000eae5788818151811062000acc5762000acc62002ded565b6020908102919091018101516001600160a01b0380881660009081526005845260408082208385168352855290819020815160c081018352905460ff8082168352610100820481169683019690965263ffffffff62010000820481169383019390935266010000000000008104909216606082015261ffff600160501b8304166080820152600160601b820490921660a08301529195509350891616881462000ba75760405163171d38a560e31b81526001600160a01b03808716600483015284166024820152604481018990526064015b60405180910390fd5b8381836020015160ff1601600101101562000be957604051635b58eeaf60e11b81526001600160a01b0380871660048301528416602482015260440162000b9e565b816040015163ffffffff1642101562000c3b576040808301519051633a7fae6b60e21b81526001600160a01b0380881660048301528516602482015263ffffffff909116604482015260640162000b9e565b606082015163ffffffff161562000c9e57816060015163ffffffff1642111562000c9e57606082015160405163345761bb60e21b81526001600160a01b0380881660048301528516602482015263ffffffff909116604482015260640162000b9e565b608082015161ffff161562000d955760405163013cf08b60e01b8152600481018890526000907f0000000000000000000000006f3e6272a167e8accb32072d08e0957f9c79223d6001600160a01b03169063013cf08b906024016101e060405180830381865afa15801562000d17573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000d3d919062002ef2565b9050826080015161ffff1643018160c00151111562000d935760808301516040516307672a3160e11b81526001600160a01b0380891660048301528616602482015261ffff909116604482015260640162000b9e565b505b60a08201516001600160a01b03161562000ea05760a082015160405163c6306e0960e01b8082526001600160a01b037f0000000000000000000000006f3e6272a167e8accb32072d08e0957f9c79223d811660048401528d81166024840152604483018b905260ff8a1660648401529092169063c6306e0990608401602060405180830381865afa15801562000e2f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000e55919062002fd6565b6001600160e01b0319161462000ea05760a082015160405163b8ec230160e01b81526001600160a01b0380881660048301528086166024830152909116604482015260640162000b9e565b919350839160010162000aae565b50886001600160a01b0316846001600160a01b03160362000ed3575050505062000f07565b60405163171d38a560e31b81526001600160a01b0380861660048301528a1660248201526044810188905260640162000b9e565b5050505050565b62000f1862001cc7565b62000f5f33858580806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250600192508791505060ff861662000a35565b600062000f7b85856000818110620007fc57620007fc62002ded565b604051630acf027160e31b81526004810185905260ff841660248201529091506001600160a01b03821690635678138890604401600060405180830381600087803b15801562000fca57600080fd5b505af115801562000fdf573d6000803e3d6000fd5b50505050336001600160a01b0316816001600160a01b03167f06ef67f52c465c176e4d3ee623ffe1051cdb317e1604d4726aa8b6b332236d5b878787876040516200102e949392919062002ea8565b60405180910390a35050505050565b6200104762001cc7565b6000856001600160401b03811115620010645762001064620027d9565b6040519080825280602002602001820160405280156200108e578160200160208202803683370190505b509050606060005b87811015620011ff57888882818110620010b457620010b462002ded565b9050602002810190620010c8919062002ff6565b8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525092945062001112925033915084905060018a60ff8b1662000a35565b6200113a826000815181106200112c576200112c62002ded565b602002602001015162001a91565b8382815181106200114f576200114f62002ded565b60200260200101906001600160a01b031690816001600160a01b03168152505082818151811062001184576200118462002ded565b60200260200101516001600160a01b0316637b3c71d3888888886040518563ffffffff1660e01b8152600401620011bf949392919062002e2c565b600060405180830381600087803b158015620011da57600080fd5b505af1158015620011ef573d6000803e3d6000fd5b5050505080600101905062001096565b50336001600160a01b03167ff155d545bf480c6d3cdc5d24c9f9364e30d161c58059bcced24aa6e5e3738eb8838a8a8a8a6040516200124395949392919062003042565b60405180910390a25050505050505050565b6200125f62001ef7565b600454600160a01b900460ff166200127d576200127b62001f53565b565b6200127b62001fb6565b6200129162001cc7565b604080517f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a8666020808301919091527f862db59105a1338741f3c46ee49a3dc764d93a40b2bbba404e37282178ba316382840152466060830152306080808401919091528351808403909101815260a0830184528051908201207f150214d74d59b7d1e90c73fc22ef3d991dd0a76b046543d4d80ab92d2a50328f60c084015260e0830189905260ff8816610100808501919091528451808503909101815261012084019094528351939091019290922061190160f01b61014083015261014282018390526101628201819052906000906101820160408051601f198184030181528282528051602091820120600080855291840180845281905260ff8a169284019290925260608301889052608083018790529092509060019060a0016020604051602081039080840390855afa158015620013f1573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166200142657604051635cd5d23360e01b815260040160405180910390fd5b6200146d818c8c80806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250600192508e91505060ff8d1662000a35565b6000620014898c8c6000818110620007fc57620007fc62002ded565b604051630acf027160e31b8152600481018c905260ff8b1660248201529091506001600160a01b03821690635678138890604401600060405180830381600087803b158015620014d857600080fd5b505af1158015620014ed573d6000803e3d6000fd5b50505050816001600160a01b0316816001600160a01b03167f06ef67f52c465c176e4d3ee623ffe1051cdb317e1604d4726aa8b6b332236d5b8e8e8e8e6040516200153c949392919062002ea8565b60405180910390a3505050505050505050505050565b80156200158557620015643362001a91565b6001600160a01b03163b600003620015855762001583336000620008da565b505b3360009081526005602090815260408083206001600160a01b038716845290915290208290620015b682826200318b565b905050826001600160a01b0316336001600160a01b03167f5a522316a2409724571357d08b150ddc1b9788dfb0171301e40591e9b4f8b09084604051620015fe919062003347565b60405180910390a3505050565b6200161562001ef7565b6200127b600062001ff5565b60006200162d62001cc7565b6000620016498e8e6000818110620007fc57620007fc62002ded565b604051636d4ab48d60e11b81529091506001600160a01b0382169063da95691a906200168c908f908f908f908f908f908f908f908f908f908f9060040162003405565b6020604051808303816000875af1158015620016ac573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620016d29190620034f7565b91506200171a338f8f808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152506004925087915060ff905062000a35565b509c9b505050505050505050505050565b7fb52b0c2d79e4e1940250202dea36651ff7f690bfef59e3077f41248e7b99299715620017d65760006200175f8262001a91565b905060006200176e8262001d16565b60405163a2c0625b60e01b81529091506001600160a01b0383169063a2c0625b906200179f90849060040162002c4e565b600060405180830381600087803b158015620017ba57600080fd5b505af1158015620017cf573d6000803e3d6000fd5b5050505050505b50565b60008054620017e89062003511565b80601f0160208091040260200160405190810160405280929190818152602001828054620018169062003511565b8015620018675780601f106200183b5761010080835404028352916020019162001867565b820191906000526020600020905b8154815290600101906020018083116200184957829003601f168201915b505050505081565b6200187962001cc7565b60005a90506200188e8787878787876200103d565b620017cf8162002047565b620018a362001cc7565b620018e733848480806020026020016040519081016040528093929190818152602001838360200280828437600092018290525060029350915060fe905062000a35565b60006200190384846000818110620007fc57620007fc62002ded565b6001600160a01b038116600081815260066020908152604080832087845290915290819020805460ff1916600117905551919250907f98686f9e3e1d53509f68f7099a7561989e030ede5d7a4f89e63d50b859da9e38906200196b908790879087906200354d565b60405180910390a250505050565b60008115620019cd57600080620019938486018662003573565b915091506000620019a5878362002140565b9050620019b981846002600060fe62000a35565b50630b135d3f60e11b925062001a0d915050565b6001600160a01b038516600090815260066020908152604080832087845290915290205460ff1662001a0157600062001a0a565b630b135d3f60e11b5b90505b949350505050565b62001a1f62001ef7565b6001600160a01b03811662001a865760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b606482015260840162000b9e565b620017d68162001ff5565b6040516000906001600160f81b03199030906001600160a01b0385169062001abc60208201620025bb565b601f1982820381018352601f9091011660408181527f0000000000000000000000006f3e6272a167e8accb32072d08e0957f9c79223d6001600160a01b031660208301520160408051601f198184030181529082905262001b21929160200162003635565b6040516020818303038152906040528051906020012060405160200162001b7f94939291906001600160f81b031994909416845260609290921b6bffffffffffffffffffffffff191660018401526015830152603582015260550190565b60408051601f19818403018152919052805160209091012092915050565b83821462001baa57600080fd5b801562001bdd5762001bbc3362001a91565b6001600160a01b03163b60000362001bdd5762001bdb336000620008da565b505b60005b8481101562001c765783838281811062001bfe5762001bfe62002ded565b33600090815260056020526040812060c0909202939093019290915088888581811062001c2f5762001c2f62002ded565b905060200201602081019062001c469190620029cf565b6001600160a01b03168152602081019190915260400160002062001c6b82826200318b565b505060010162001be0565b50336001600160a01b03167f9c0c1ce513ac44df340d0f04a9c6044a96f1509d359a48b5da21992b72d568a48686868660405162001cb8949392919062003668565b60405180910390a25050505050565b600454600160a01b900460ff16156200127b5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b604482015260640162000b9e565b6001600160a01b03811660009081526003602052604090205460609060ff161562001d5457604051630ea075bf60e21b815260040160405180910390fd5b6001805481019081905560009062001d6c9062002168565b905080600060405160200162001d84929190620036c8565b604051602081830303815290604052915060008160405160200162001daa919062003795565b60405160208183030381529060405280519060200120905060007fb52b0c2d79e4e1940250202dea36651ff7f690bfef59e3077f41248e7b9929978260405160200162001e01929190918252602082015260400190565b60408051808303601f19018152828252805160209182012060008181526002835283812080546001600160a01b0319166001600160a01b038c1690811790915581526003909252918120805460ff191660011790556305ef2c7f60e41b83527fb52b0c2d79e4e1940250202dea36651ff7f690bfef59e3077f41248e7b99299760048401526024830185905230604484018190526064840152608483015291506e0c2e074ec69a0dfb2997ba6c7d2e1e90635ef2c7f09060a401600060405180830381600087803b15801562001ed657600080fd5b505af115801562001eeb573d6000803e3d6000fd5b50505050505050919050565b6004546001600160a01b031633146200127b5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640162000b9e565b62001f5d62001cc7565b6004805460ff60a01b1916600160a01b1790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a25862001f993390565b6040516001600160a01b03909116815260200160405180910390a1565b62001fc062002201565b6004805460ff60a01b191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa3362001f99565b600480546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b47600081900362002056575050565b60006200206948642e90edd00062002253565b905060006200207f3a6377359400840162002253565b9050600062002098618ca05a87030162030d4062002253565b90506000620020aa8284028662002253565b604051909150600090339083908381818185875af1925050503d8060008114620020f1576040519150601f19603f3d011682016040523d82523d6000602084013e620020f6565b606091505b505060408051848152821515602082015291925033917ffabef36fd46c4c3a6ad676521be5367a4dfdbf3faa68d8e826003b1752d68f4f910160405180910390a250505050505050565b60008060006200215185856200226d565b915091506200216081620022b6565b509392505050565b60606000620021778362002413565b60010190506000816001600160401b03811115620021995762002199620027d9565b6040519080825280601f01601f191660200182016040528015620021c4576020820181803683370190505b5090508181016020015b600019016f181899199a1a9b1b9c1cb0b131b232b360811b600a86061a8153600a8504945084620021ce57509392505050565b600454600160a01b900460ff166200127b5760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b604482015260640162000b9e565b600081831062002264578162002266565b825b9392505050565b6000808251604103620022a75760208301516040840151606085015160001a6200229a87828585620024f2565b94509450505050620022af565b506000905060025b9250929050565b6000816004811115620022cd57620022cd620037b3565b03620022d65750565b6001816004811115620022ed57620022ed620037b3565b036200233c5760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e61747572650000000000000000604482015260640162000b9e565b6002816004811115620023535762002353620037b3565b03620023a25760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e67746800604482015260640162000b9e565b6003816004811115620023b957620023b9620037b3565b03620017d65760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b606482015260840162000b9e565b60008072184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b8310620024535772184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b830492506040015b6d04ee2d6d415b85acef8100000000831062002480576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc1000083106200249f57662386f26fc10000830492506010015b6305f5e1008310620024b8576305f5e100830492506008015b6127108310620024cd57612710830492506004015b60648310620024e0576064830492506002015b600a8310620007895760010192915050565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08311156200252b5750600090506003620025b2565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa15801562002580573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116620025ab57600060019250925050620025b2565b9150600090505b94509492505050565b6104c280620037ca83390190565b6001600160e01b031981168114620017d657600080fd5b600060208284031215620025f357600080fd5b81356200226681620025c9565b60008083601f8401126200261357600080fd5b5081356001600160401b038111156200262b57600080fd5b6020830191508360208260051b8501011115620022af57600080fd5b60ff81168114620017d657600080fd5b60008083601f8401126200266a57600080fd5b5081356001600160401b038111156200268257600080fd5b602083019150836020828501011115620022af57600080fd5b60008060008060008060808789031215620026b557600080fd5b86356001600160401b0380821115620026cd57600080fd5b620026db8a838b0162002600565b90985096506020890135955060408901359150620026f98262002647565b909350606088013590808211156200271057600080fd5b506200271f89828a0162002657565b979a9699509497509295939492505050565b6001600160a01b0381168114620017d657600080fd5b600080604083850312156200275b57600080fd5b8235620027688162002731565b915060208301356200277a8162002731565b809150509250929050565b8015158114620017d657600080fd5b8035620027a18162002785565b919050565b60008060408385031215620027ba57600080fd5b8235620027c78162002731565b915060208301356200277a8162002785565b634e487b7160e01b600052604160045260246000fd5b6040516101e081016001600160401b0381118282101715620028155762002815620027d9565b60405290565b604051601f8201601f191681016001600160401b0381118282101715620028465762002846620027d9565b604052919050565b600082601f8301126200286057600080fd5b813560206001600160401b038211156200287e576200287e620027d9565b8160051b6200288f8282016200281b565b9283528481018201928281019087851115620028aa57600080fd5b83870192505b84831015620028d6578235620028c68162002731565b82529183019190830190620028b0565b979650505050505050565b600080600080600060a08688031215620028fa57600080fd5b8535620029078162002731565b945060208601356001600160401b038111156200292357600080fd5b62002931888289016200284e565b959895975050505060408401359360608101359360809091013592509050565b6000602082840312156200296457600080fd5b5035919050565b600080600080606085870312156200298257600080fd5b84356001600160401b038111156200299957600080fd5b620029a78782880162002600565b909550935050602085013591506040850135620029c48162002647565b939692955090935050565b600060208284031215620029e257600080fd5b8135620022668162002731565b600080600080600080600060c0888a03121562002a0b57600080fd5b87356001600160401b0381111562002a2257600080fd5b62002a308a828b0162002600565b90985096505060208801359450604088013562002a4d8162002647565b9350606088013562002a5f8162002647565b969995985093969295946080840135945060a09093013592915050565b600080600083850361010081121562002a9457600080fd5b843562002aa18162002731565b935060c0601f198201121562002ab657600080fd5b5060208401915060e084013562002acd8162002785565b809150509250925092565b60008060008060008060008060008060008060c08d8f03121562002afb57600080fd5b6001600160401b038d35111562002b1157600080fd5b62002b208e8e358f0162002600565b909c509a506001600160401b0360208e0135111562002b3e57600080fd5b62002b508e60208f01358f0162002600565b909a5098506001600160401b0360408e0135111562002b6e57600080fd5b62002b808e60408f01358f0162002600565b90985096506001600160401b0360608e0135111562002b9e57600080fd5b62002bb08e60608f01358f0162002600565b90965094506001600160401b0360808e0135111562002bce57600080fd5b62002be08e60808f01358f0162002600565b90945092506001600160401b0360a08e0135111562002bfe57600080fd5b62002c108e60a08f01358f0162002657565b81935080925050509295989b509295989b509295989b565b60005b8381101562002c4557818101518382015260200162002c2b565b50506000910152565b602081526000825180602084015262002c6f81604085016020870162002c28565b601f01601f19169190910160400192915050565b60008060006040848603121562002c9957600080fd5b83356001600160401b0381111562002cb057600080fd5b62002cbe8682870162002600565b909790965060209590950135949350505050565b6000806000806060858703121562002ce957600080fd5b843562002cf68162002731565b93506020850135925060408501356001600160401b0381111562002d1957600080fd5b62002d278782880162002657565b95989497509550505050565b60008060008060006060868803121562002d4c57600080fd5b85356001600160401b038082111562002d6457600080fd5b62002d7289838a0162002600565b9097509550602088013591508082111562002d8c57600080fd5b818801915088601f83011262002da157600080fd5b81358181111562002db157600080fd5b89602060c08302850101111562002dc757600080fd5b60208301955080945050505062002de16040870162002794565b90509295509295909350565b634e487b7160e01b600052603260045260246000fd5b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b84815260ff8416602082015260606040820152600062002e5160608301848662002e03565b9695505050505050565b8183526000602080850194508260005b8581101562002e9d57813562002e818162002731565b6001600160a01b03168752958201959082019060010162002e6b565b509495945050505050565b60608152600062002ebe60608301868862002e5b565b905083602083015260ff8316604083015295945050505050565b8051620027a18162002731565b8051620027a18162002785565b60006101e0828403121562002f0657600080fd5b62002f10620027ef565b8251815262002f226020840162002ed8565b602082015260408301516040820152606083015160608201526080830151608082015260a083015160a082015260c083015160c082015260e083015160e082015261010080840151818301525061012080840151818301525061014062002f8b81850162002ee5565b9082015261016062002f9f84820162002ee5565b9082015261018062002fb384820162002ee5565b908201526101a083810151908201526101c0928301519281019290925250919050565b60006020828403121562002fe957600080fd5b81516200226681620025c9565b6000808335601e198436030181126200300e57600080fd5b8301803591506001600160401b038211156200302957600080fd5b6020019150600581901b3603821315620022af57600080fd5b6080808252865190820181905260009060209060a0840190828a01845b82811015620030865781516001600160a01b0316845292840192908401906001016200305f565b50505083810382850152868152818101600588811b830184018a60005b8b8110156200311b57858303601f190185528135368e9003601e19018112620030cb57600080fd5b8d0187810190356001600160401b03811115620030e757600080fd5b80861b3603821315620030f957600080fd5b6200310685828462002e5b565b968901969450505090860190600101620030a3565b50506040870189905260ff88166060880152945062002e519350505050565b63ffffffff81168114620017d657600080fd5b6000813562000789816200313a565b61ffff81168114620017d657600080fd5b6000813562000789816200315c565b60008135620007898162002731565b8135620031988162002647565b60ff8116905081548160ff1982161783556020840135620031b98162002647565b61ff008160081b169050808361ffff198416171784556040850135620031df816200313a565b65ffffffff00008160101b168465ffffffffffff198516178317178555505050506200323862003212606084016200314d565b825469ffffffff000000000000191660309190911b69ffffffff00000000000016178255565b6200326a6200324a608084016200316d565b82805461ffff60501b191660509290921b61ffff60501b16919091179055565b620032a66200327c60a084016200317c565b82546bffffffffffffffffffffffff1660609190911b6bffffffffffffffffffffffff1916178255565b5050565b8035620032b78162002647565b60ff1682526020810135620032cc8162002647565b60ff1660208301526040810135620032e4816200313a565b63ffffffff908116604084015260608201359062003302826200313a565b166060830152608081013562003318816200315c565b61ffff16608083015260a0810135620033318162002731565b6001600160a01b031660a0929092019190915250565b60c08101620007898284620032aa565b6000808335601e198436030181126200336f57600080fd5b83016020810192503590506001600160401b038111156200338f57600080fd5b803603821315620022af57600080fd5b60008383855260208086019550808560051b8301018460005b87811015620033f857848303601f19018952620033d6828862003357565b620033e385828462002e03565b9a86019a9450505090830190600101620033b8565b5090979650505050505050565b60a0815260006200341b60a083018c8e62002e5b565b8281036020848101919091528a82526001600160fb1b038b11156200343f57600080fd5b8a60051b808d8385013780830192505080820181858403016040860152808a825260408401905060408b60051b85010191508b60005b8c811015620034b557858403603f1901835262003493828f62003357565b620034a086828462002e03565b95505050918401919084019060010162003475565b5050508481036060860152620034cd81898b6200339f565b925050508281036080840152620034e681858762002e03565b9d9c50505050505050505050505050565b6000602082840312156200350a57600080fd5b5051919050565b600181811c908216806200352657607f821691505b6020821081036200354757634e487b7160e01b600052602260045260246000fd5b50919050565b6040815260006200356360408301858762002e5b565b9050826020830152949350505050565b600080604083850312156200358757600080fd5b82356001600160401b03808211156200359f57600080fd5b620035ad868387016200284e565b9350602091508185013581811115620035c557600080fd5b8501601f81018713620035d757600080fd5b803582811115620035ec57620035ec620027d9565b62003600601f8201601f191685016200281b565b925080835287848284010111156200361757600080fd5b80848301858501376000848285010152505080925050509250929050565b600083516200364981846020880162002c28565b8351908301906200365f81836020880162002c28565b01949350505050565b6040815260006200367e60408301868862002e5b565b82810360208085019190915284825285910160005b85811015620036bc57620036a88284620032aa565b60c092830192919091019060010162003693565b50979650505050505050565b600083516020620036dd828583890162002c28565b601760f91b918401918252845460019060009080831c818416806200370357607f821691505b85821081036200372157634e487b7160e01b84526022600452602484fd5b808015620037385760018114620037525762003785565b60ff19841688870152821515830288018601945062003785565b60008b81526020902060005b848110156200377b5781548a82018901529087019088016200375e565b5050858389010194505b50929a9950505050505050505050565b60008251620037a981846020870162002c28565b9190910192915050565b634e487b7160e01b600052602160045260246000fdfe60c060405234801561001057600080fd5b506040516104c23803806104c283398101604081905261002f91610044565b336080526001600160a01b031660a052610074565b60006020828403121561005657600080fd5b81516001600160a01b038116811461006d57600080fd5b9392505050565b60805160a05161041d6100a56000396000606001526000818160340152818161011d01526101ac015261041d6000f3fe6080604052600436106100295760003560e01c80631626ba7e146100a6578063a2c0625b146100e3575b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461005e57600080fd5b7f0000000000000000000000000000000000000000000000000000000000000000366000803760008036600034855af13d6000803e80801561009f573d6000f35b3d6000fd5b005b3480156100b257600080fd5b506100c66100c13660046102a0565b610103565b6040516001600160e01b0319909116815260200160405180910390f35b3480156100ef57600080fd5b506100a46100fe3660046102ec565b6101a1565b604051630e2f57fb60e41b81526000906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063e2f57fb090610158903090889088908890600401610357565b602060405180830381865afa158015610175573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101999190610389565b949350505050565b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146101d657600080fd5b60405163c47f002760e01b815273084b1c3c81545d370f3634392de611caabff81489063c47f00279061020f90859085906004016103ba565b6020604051808303816000875af115801561022e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061025291906103ce565b505050565b60008083601f84011261026957600080fd5b50813567ffffffffffffffff81111561028157600080fd5b60208301915083602082850101111561029957600080fd5b9250929050565b6000806000604084860312156102b557600080fd5b83359250602084013567ffffffffffffffff8111156102d357600080fd5b6102df86828701610257565b9497909650939450505050565b600080602083850312156102ff57600080fd5b823567ffffffffffffffff81111561031657600080fd5b61032285828601610257565b90969095509350505050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b60018060a01b038516815283602082015260606040820152600061037f60608301848661032e565b9695505050505050565b60006020828403121561039b57600080fd5b81516001600160e01b0319811681146103b357600080fd5b9392505050565b60208152600061019960208301848661032e565b6000602082840312156103e057600080fd5b505191905056fea2646970667358221220f713c761976839ac402290f1ee034e850f179aea67c3319fd22b579944fe7c0564736f6c63430008130033a2646970667358221220b623416f3cab1defcc1541d99e98a31dbabe9b006c764adb8b06e77d6250c60d64736f6c63430008130033

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

0000000000000000000000006f3e6272a167e8accb32072d08e0957f9c79223d0000000000000000000000000000000000000000000000000000000000000060b52b0c2d79e4e1940250202dea36651ff7f690bfef59e3077f41248e7b99299700000000000000000000000000000000000000000000000000000000000000136e6f756e732e766f746561676f72612e65746800000000000000000000000000

-----Decoded View---------------
Arg [0] : _governor (address): 0x6f3E6272A167e8AcCb32072d08E0957F9c79223d
Arg [1] : _ensName (string): nouns.voteagora.eth
Arg [2] : _ensNameHash (bytes32): 0xb52b0c2d79e4e1940250202dea36651ff7f690bfef59e3077f41248e7b992997

-----Encoded View---------------
5 Constructor Arguments found :
Arg [0] : 0000000000000000000000006f3e6272a167e8accb32072d08e0957f9c79223d
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000060
Arg [2] : b52b0c2d79e4e1940250202dea36651ff7f690bfef59e3077f41248e7b992997
Arg [3] : 0000000000000000000000000000000000000000000000000000000000000013
Arg [4] : 6e6f756e732e766f746561676f72612e65746800000000000000000000000000


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