ETH Price: $3,212.63 (-4.30%)

Contract

0x089cc95fe03BE5D6451af638A71cF24a48877a5c

Overview

ETH Balance

0 ETH

ETH Value

$0.00

More Info

Private Name Tags

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To

There are no matching entries

6 Internal Transactions found.

Latest 6 internal transactions

Advanced mode:
Parent Transaction Hash Block From To
178620362025-12-01 16:00:4710 days ago1764604847
0x089cc95f...a48877a5c
 Contract Creation0 ETH
178620362025-12-01 16:00:4710 days ago1764604847
0x089cc95f...a48877a5c
 Contract Creation0 ETH
174928352025-11-27 9:27:2614 days ago1764235646
0x089cc95f...a48877a5c
 Contract Creation0 ETH
174928352025-11-27 9:27:2614 days ago1764235646
0x089cc95f...a48877a5c
 Contract Creation0 ETH
174179252025-11-26 12:38:5615 days ago1764160736
0x089cc95f...a48877a5c
 Contract Creation0 ETH
174179252025-11-26 12:38:5615 days ago1764160736
0x089cc95f...a48877a5c
 Contract Creation0 ETH

Cross-Chain Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
StagedProposalProcessorSetup

Compiler Version
v0.8.28+commit.7893614a

Optimization Enabled:
Yes with 200 runs

Other Settings:
cancun EvmVersion
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.18;

import {SPPRuleCondition} from "./utils/SPPRuleCondition.sol";
import {StagedProposalProcessor as SPP} from "./StagedProposalProcessor.sol";
import {Permissions} from "./libraries/Permissions.sol";

import {IDAO} from "@aragon/osx-commons-contracts/src/dao/IDAO.sol";
import {IPlugin} from "@aragon/osx-commons-contracts/src/plugin/IPlugin.sol";
import {
    PluginUpgradeableSetup
} from "@aragon/osx-commons-contracts/src/plugin/setup/PluginUpgradeableSetup.sol";
import {ProxyLib} from "@aragon/osx-commons-contracts/src/utils/deployment/ProxyLib.sol";
import {IPluginSetup} from "@aragon/osx-commons-contracts/src/plugin/setup/IPluginSetup.sol";
import {PermissionLib} from "@aragon/osx-commons-contracts/src/permission/PermissionLib.sol";
import {
    RuledCondition
} from "@aragon/osx-commons-contracts/src/permission/condition/extensions/RuledCondition.sol";

/// @title MyPluginSetup
/// @author Aragon X - 2024
/// @notice The setup contract of the `StagedProposalProcessor` plugin.
/// @dev Release 1, Build 1
contract StagedProposalProcessorSetup is PluginUpgradeableSetup {
    using ProxyLib for address;

    /// @notice A special address encoding permissions that are valid for any address `who` or `where`.
    address private constant ANY_ADDR = address(type(uint160).max);

    /// @notice The address of the condition implementation contract.
    address public immutable CONDITION_IMPLEMENTATION;

    /// @notice Constructs the `PluginUpgradeableSetup` by storing the `SPP` implementation address.
    /// @dev The implementation address is used to deploy UUPS proxies referencing it and
    /// to verify the plugin on the respective block explorers.
    constructor() PluginUpgradeableSetup(address(new SPP())) {
        CONDITION_IMPLEMENTATION = address(
            new SPPRuleCondition(address(0), new RuledCondition.Rule[](0))
        );
    }

    /// @inheritdoc IPluginSetup
    function prepareInstallation(
        address _dao,
        bytes calldata _installationParams
    ) external returns (address spp, PreparedSetupData memory preparedSetupData) {
        (
            bytes memory pluginMetadata,
            SPP.Stage[] memory stages,
            RuledCondition.Rule[] memory rules,
            IPlugin.TargetConfig memory targetConfig
        ) = abi.decode(
                _installationParams,
                (bytes, SPP.Stage[], RuledCondition.Rule[], IPlugin.TargetConfig)
            );

        // By default, we assume that sub-plugins will use a delegate call to invoke the executor,
        // which will keep `msg.sender` as the sub-plugin within the SPP context.
        // Therefore, the default trusted forwarder is set to the zero address (address(0)).
        // However, the grantee of `SET_TRUSTED_FORWARDER_PERMISSION` can update this address at any time.
        // Allowing a user-provided trusted forwarder here is risky if the plugin installer is malicious.
        spp = IMPLEMENTATION.deployUUPSProxy(
            abi.encodeCall(
                SPP.initialize,
                (IDAO(_dao), address(0), stages, pluginMetadata, targetConfig)
            )
        );

        // Clone and initialize the plugin contract.
        bytes memory initData = abi.encodeCall(SPPRuleCondition.initialize, (_dao, rules));
        address sppCondition = CONDITION_IMPLEMENTATION.deployMinimalProxy(initData);

        preparedSetupData.permissions = _getPermissions(
            _dao,
            spp,
            sppCondition,
            PermissionLib.Operation.Grant
        );

        preparedSetupData.helpers = new address[](1);
        preparedSetupData.helpers[0] = sppCondition;
    }

    /// @inheritdoc IPluginSetup
    /// @dev The default implementation for the initial build 1 that reverts because no earlier build exists.
    function prepareUpdate(
        address _dao,
        uint16 _fromBuild,
        SetupPayload calldata _payload
    ) external pure virtual returns (bytes memory, PreparedSetupData memory) {
        (_dao, _fromBuild, _payload);
        revert InvalidUpdatePath({fromBuild: 0, thisBuild: 1});
    }

    /// @inheritdoc IPluginSetup
    function prepareUninstallation(
        address _dao,
        SetupPayload calldata _payload
    ) external pure returns (PermissionLib.MultiTargetPermission[] memory permissions) {
        permissions = _getPermissions(
            _dao,
            _payload.plugin,
            _payload.currentHelpers[0],
            PermissionLib.Operation.Revoke
        );
    }

    function _getPermissions(
        address _dao,
        address _spp,
        address _ruledCondition,
        PermissionLib.Operation _op
    ) private pure returns (PermissionLib.MultiTargetPermission[] memory permissions) {
        permissions = new PermissionLib.MultiTargetPermission[](9);

        // Permissions on SPP
        permissions[0] = PermissionLib.MultiTargetPermission({
            operation: _op,
            where: _spp,
            who: _dao,
            condition: PermissionLib.NO_CONDITION,
            permissionId: Permissions.UPDATE_STAGES_PERMISSION_ID
        });

        permissions[1] = PermissionLib.MultiTargetPermission({
            operation: _op,
            where: _spp,
            who: ANY_ADDR,
            condition: PermissionLib.NO_CONDITION,
            permissionId: Permissions.EXECUTE_PROPOSAL_PERMISSION_ID
        });

        permissions[2] = PermissionLib.MultiTargetPermission({
            operation: _op,
            where: _spp,
            who: _dao,
            condition: PermissionLib.NO_CONDITION,
            permissionId: Permissions.SET_TRUSTED_FORWARDER_PERMISSION_ID
        });

        permissions[3] = PermissionLib.MultiTargetPermission({
            operation: _op,
            where: _spp,
            who: _dao,
            condition: PermissionLib.NO_CONDITION,
            permissionId: Permissions.SET_TARGET_CONFIG_PERMISSION_ID
        });

        permissions[4] = PermissionLib.MultiTargetPermission({
            operation: _op,
            where: _spp,
            who: _dao,
            condition: PermissionLib.NO_CONDITION,
            permissionId: Permissions.SET_METADATA_PERMISSION_ID
        });

        permissions[5] = PermissionLib.MultiTargetPermission({
            operation: _op == PermissionLib.Operation.Grant
                ? PermissionLib.Operation.GrantWithCondition
                : _op,
            where: _spp,
            who: ANY_ADDR,
            condition: _ruledCondition,
            permissionId: Permissions.CREATE_PROPOSAL_PERMISSION_ID
        });

        permissions[6] = PermissionLib.MultiTargetPermission({
            operation: _op,
            where: _spp,
            who: ANY_ADDR,
            condition: PermissionLib.NO_CONDITION,
            permissionId: Permissions.ADVANCE_PERMISSION_ID
        });

        /// Permissions on the dao by SPP.
        permissions[7] = PermissionLib.MultiTargetPermission({
            operation: _op,
            where: _dao,
            who: _spp,
            condition: PermissionLib.NO_CONDITION,
            permissionId: Permissions.EXECUTE_PERMISSION_ID
        });

        /// Permissions on the ruledCondition
        permissions[8] = PermissionLib.MultiTargetPermission({
            operation: _op,
            where: _ruledCondition,
            who: _dao,
            condition: PermissionLib.NO_CONDITION,
            permissionId: Permissions.UPDATE_RULES_PERMISSION_ID
        });
    }
}

// SPDX-License-Identifier: AGPL-3.0-or-later

pragma solidity ^0.8.18;

import {Address} from "@openzeppelin/contracts/utils/Address.sol";

import {IDAO} from "@aragon/osx-commons-contracts/src/dao/IDAO.sol";
import {
    IPermissionCondition
} from "@aragon/osx-commons-contracts/src/permission/condition/IPermissionCondition.sol";
import {
    DaoAuthorizableUpgradeable
} from "@aragon/osx-commons-contracts/src/permission/auth/DaoAuthorizableUpgradeable.sol";
import {
    RuledCondition
} from "@aragon/osx-commons-contracts/src/permission/condition/extensions/RuledCondition.sol";

/// @title SPPRuleCondition
/// @author Aragon X - 2024
/// @notice The SPP Condition that must be granted for `createProposal` function of `StagedProposalProcessor`.
/// @dev This contract must be deployed either with clonable or `new` keyword.
contract SPPRuleCondition is DaoAuthorizableUpgradeable, RuledCondition {
    using Address for address;

    /// @notice The ID of the permission required to call the `updateRules` function.
    bytes32 public constant UPDATE_RULES_PERMISSION_ID = keccak256("UPDATE_RULES_PERMISSION");

    /// @notice Disables the initializers on the implementation contract to prevent it from being left uninitialized.
    /// @custom:oz-upgrades-unsafe-allow constructor
    constructor(address _dao, Rule[] memory _rules) {
        initialize(_dao, _rules);
    }

    /// @notice Initializes the component.
    /// @param _dao The IDAO interface of the associated DAO.
    /// @param _rules The rules that decide who can create a proposal on `StagedProposalProcessor`.
    function initialize(address _dao, Rule[] memory _rules) public initializer {
        __DaoAuthorizableUpgradeable_init(IDAO(_dao));
        if (_rules.length != 0) {
            _updateRules(_rules);
        }
    }

    /// @inheritdoc IPermissionCondition
    function isGranted(
        address _where,
        address _who,
        bytes32 _permissionId,
        bytes calldata
    ) external view returns (bool isPermitted) {
        if (getRules().length == 0) {
            return true;
        }

        return _evalRule(0, _where, _who, _permissionId, new uint256[](0));
    }

    /// @notice Internal function that updates the rules.
    /// @param _rules The rules that decide who can create a proposal on `StagedProposalProcessor`.
    function _updateRules(Rule[] memory _rules) internal override {
        for (uint256 i = 0; i < _rules.length; ++i) {
            Rule memory rule = _rules[i];

            // Make sure that `isGranted` doesn't revert
            // in case empty bytes data is provided.
            // Since SPP can not always predict what the `data`
            // should be for each sub-plugin. We make sure that
            // only those conditions that don't depend on `data` param are allowed.
            if (rule.id == CONDITION_RULE_ID) {
                bytes memory data = abi.encodeCall(
                    IPermissionCondition.isGranted,
                    (address(1), address(2), bytes32(uint256(1)), bytes(""))
                );

                address condition = address(uint160(rule.value));

                condition.functionStaticCall(data);
            }
        }

        super._updateRules(_rules);
    }

    /// @notice Updates the rules that will be used as a check upon proposal creation on `StagedProposalProcessor`.
    /// @param _rules The rules that decide who can create a proposal on `StagedProposalProcessor`.
    function updateRules(Rule[] calldata _rules) public auth(UPDATE_RULES_PERMISSION_ID) {
        _updateRules(_rules);
    }
}

File 3 of 48 : StagedProposalProcessor.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.18;

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

import {IDAO} from "@aragon/osx-commons-contracts/src/dao/IDAO.sol";
import {
    PluginUUPSUpgradeable
} from "@aragon/osx-commons-contracts/src/plugin/PluginUUPSUpgradeable.sol";
import {Action} from "@aragon/osx-commons-contracts/src/executors/IExecutor.sol";
import {
    IProposal
} from "@aragon/osx-commons-contracts/src/plugin/extensions/proposal/IProposal.sol";
import {
    MetadataExtensionUpgradeable
} from "@aragon/osx-commons-contracts/src/utils/metadata/MetadataExtensionUpgradeable.sol";
import {
    ProposalUpgradeable
} from "@aragon/osx-commons-contracts/src/plugin/extensions/proposal/ProposalUpgradeable.sol";

import {ERC165Checker} from "@openzeppelin/contracts/utils/introspection/ERC165Checker.sol";

/// @title StagedProposalProcessor
/// @author Aragon X - 2024
/// @notice A multi-stage proposal processor where proposals progress through defined stages.
///         Each stage is evaluated by the responsible bodies, determining whether the proposal advances
///         to the next stage. Once a proposal successfully passes all stages, it can be executed.
contract StagedProposalProcessor is
    ProposalUpgradeable,
    MetadataExtensionUpgradeable,
    PluginUUPSUpgradeable
{
    using ERC165Checker for address;

    /// @notice Used to distinguish proposals where the SPP was not able to create a proposal on a sub-body.
    uint256 private constant PROPOSAL_WITHOUT_ID = type(uint256).max;

    /// @notice The different types that bodies can be registered as.
    /// @param None Used to check if the body reported the result or not.
    /// @param Approval Used to allow a body to report approval result.
    /// @param Veto Used to allow a body to report veto result.
    enum ResultType {
        None,
        Approval,
        Veto
    }

    /// @notice The states of the proposal.
    /// @param Active Whether the proposal is not advanceable.
    /// @param Canceled Whether the proposal is canceled.
    /// @param Executed Whether the proposal is executed.
    /// @param Advanceable Whether the proposal can be advanced to the next stage.
    /// @param Expired Whether the proposal's stage maxAdvance time has passed.
    enum ProposalState {
        Active,
        Canceled,
        Executed,
        Advanceable,
        Expired
    }

    /// @notice A container for Body-related information.
    /// @param addr The address responsible for reporting results. For automatic bodies,
    ///     it is also where the SPP creates proposals.
    /// @param isManual Whether SPP should create a proposal on a body. If true, it will not create.
    /// @param tryAdvance Whether to try to automatically advance the stage when a body reports results.
    /// @param resultType The type(`Approval` or `Veto`) this body is registered with.
    struct Body {
        address addr;
        bool isManual;
        bool tryAdvance;
        ResultType resultType;
    }

    /// @notice A container for stage-related information.
    /// @param bodies The bodies that are responsible for advancing the stage.
    /// @param maxAdvance The maximum duration after which stage can not be advanced.
    /// @param minAdvance The minimum duration until when stage can not be advanced.
    /// @param voteDuration The time to give vetoing bodies to make decisions in optimistic stage.
    ///     Note that this also is used as an endDate time for bodies, see `_createBodyProposals`.
    /// @param approvalThreshold The number of bodies that are required to pass to advance the proposal.
    /// @param vetoThreshold If this number of bodies veto, the proposal can never advance
    ///     even if `approvalThreshold` is satisfied.
    /// @param cancelable If the proposal can be cancelled in the stage.
    /// @param editable If the proposal can be edited in the stage.
    struct Stage {
        Body[] bodies;
        uint64 maxAdvance;
        uint64 minAdvance;
        uint64 voteDuration;
        uint16 approvalThreshold;
        uint16 vetoThreshold;
        bool cancelable;
        bool editable;
    }

    /// @notice A container for proposal-related information.
    /// @param allowFailureMap A bitmap allowing the proposal to succeed, even if individual actions might revert.
    /// @param lastStageTransition The timestamp at which proposal's current stage has started.
    /// @param currentStage Which stage the proposal is at.
    /// @param stageConfigIndex The stage configuration that this proposal uses.
    /// @param executed Whether the proposal is executed or not.
    /// @param canceled Whether the proposal is canceled or not.
    /// @param creator The creator of the proposal.
    /// @param actions The actions to be executed when the proposal passes.
    /// @param targetConfig The target to which this contract will pass actions with an operation type.
    struct Proposal {
        uint128 allowFailureMap;
        uint64 lastStageTransition;
        uint16 currentStage;
        uint16 stageConfigIndex;
        bool executed;
        bool canceled;
        address creator;
        Action[] actions;
        TargetConfig targetConfig;
    }

    /// @notice A mapping to track sub-proposal IDs for a given proposal, stage, and body.
    mapping(uint256 proposalId => mapping(uint16 stageId => mapping(address body => uint256 subProposalId)))
        private bodyProposalIds;

    /// @notice A mapping to store the result types reported by bodies for a given proposal and stage.
    mapping(uint256 proposalId => mapping(uint16 stageId => mapping(address body => ResultType resultType)))
        private bodyResults;

    /// @notice A mapping to store custom proposal parameters data for a given proposal, stage, and body index.
    mapping(uint256 proposalId => mapping(uint16 stageId => mapping(uint256 bodyIndex => bytes customParams)))
        private createProposalParams;

    /// @notice A mapping between proposal IDs and their associated proposal information.
    mapping(uint256 proposalId => Proposal) private proposals;

    /// @notice A mapping between stage configuration indices and the corresponding stage configurations.
    mapping(uint256 configIndex => Stage[]) private stages;

    /// @notice The index of the current stage configuration in the `stages` mapping.
    uint16 private currentConfigIndex;

    /// @notice The address of the trusted forwarder.
    /// @dev The trusted forwarder appends the original sender's address to the calldata. If an executor is the
    ///      trusted forwarder, the `_msgSender` function extracts the original sender from the calldata.
    address private trustedForwarder;

    /// @notice Emitted when the proposal is advanced to the next stage.
    /// @param proposalId The proposal id.
    /// @param stageId The stage index.
    /// @param sender The address that advanced the proposal.
    event ProposalAdvanced(
        uint256 indexed proposalId,
        uint16 indexed stageId,
        address indexed sender
    );

    /// @notice Emitted when the proposal gets cancelled.
    /// @param proposalId the proposal id.
    /// @param stageId The stage index in which the proposal was cancelled.
    /// @param sender The sender that canceled the proposal.
    event ProposalCanceled(
        uint256 indexed proposalId,
        uint16 indexed stageId,
        address indexed sender
    );

    /// @notice Emitted when the proposal gets edited.
    /// @param proposalId the proposal id.
    /// @param stageId The stage index in which the proposal was edited.
    /// @param sender The sender that edited the proposal.
    /// @param metadata The new metadata that replaces old metadata.
    /// @param actions The new actions that replaces old actions.
    event ProposalEdited(
        uint256 indexed proposalId,
        uint16 indexed stageId,
        address indexed sender,
        bytes metadata,
        Action[] actions
    );

    /// @notice Emitted when a body reports results by calling `reportProposalResult`.
    /// @param proposalId The proposal id.
    /// @param stageId The stage index.
    /// @param body The sender that reported the result.
    event ProposalResultReported(
        uint256 indexed proposalId,
        uint16 indexed stageId,
        address indexed body
    );

    /// @notice Emitted when this plugin successfully creates a proposal on sub-body.
    /// @param proposalId The proposal id.
    /// @param stageId The stage index.
    /// @param body The sub-body on which sub-proposal has been created.
    /// @param bodyProposalId The proposal id that sub-body returns for later usage by this plugin.
    event SubProposalCreated(
        uint256 indexed proposalId,
        uint16 indexed stageId,
        address indexed body,
        uint256 bodyProposalId
    );

    /// @notice Emitted when this plugin fails in creating a proposal on sub-body.
    /// @param proposalId The proposal id.
    /// @param stageId The stage index.
    /// @param body The sub-body on which sub-proposal failed to be created.
    /// @param reason The reason why it was failed.
    event SubProposalNotCreated(
        uint256 indexed proposalId,
        uint16 indexed stageId,
        address indexed body,
        bytes reason
    );

    /// @notice Emitted when the stage configuration is updated for a proposal process.
    /// @param stages The array of `Stage` structs representing the updated stage configuration.
    event StagesUpdated(Stage[] stages);

    /// @notice Emitted when the trusted forwarder is updated.
    /// @param forwarder The new trusted forwarder address.
    event TrustedForwarderUpdated(address indexed forwarder);

    /// @notice Initializes the component.
    /// @dev This method is required to support [ERC-1822](https://eips.ethereum.org/EIPS/eip-1822).
    /// @param _dao The IDAO interface of the associated DAO.
    /// @param _trustedForwarder The trusted forwarder responsible for extracting the original sender.
    /// @param _stages The stages configuration.
    /// @param _pluginMetadata The utf8 bytes of a content addressing cid that stores plugin's information.
    /// @param _targetConfig The target to which this contract will pass actions with an operation type.
    function initialize(
        IDAO _dao,
        address _trustedForwarder,
        Stage[] calldata _stages,
        bytes calldata _pluginMetadata,
        TargetConfig calldata _targetConfig
    ) external initializer {
        __PluginUUPSUpgradeable_init(_dao);

        // Allows installation even if `stages` are not present.
        // This ensures flexibility as users can still install the plugin and decide
        // later to apply configurations.
        if (_stages.length > 0) {
            _updateStages(_stages);
        }

        if (_trustedForwarder != address(0)) {
            _setTrustedForwarder(_trustedForwarder);
        }

        _setMetadata(_pluginMetadata);
        _setTargetConfig(_targetConfig);
    }

    /// @notice Allows to update stage configuration.
    /// @dev Requires the caller to have the `UPDATE_STAGES_PERMISSION_ID` permission.
    ///      Reverts if the provided `_stages` array is empty.
    /// @param _stages The new stage configuration as an array of `Stage` structs.
    function updateStages(
        Stage[] calldata _stages
    ) external auth(Permissions.UPDATE_STAGES_PERMISSION_ID) {
        if (_stages.length == 0) {
            revert Errors.StageCountZero();
        }
        _updateStages(_stages);
    }

    /// @notice Reports and records the result for a proposal at a specific stage.
    /// @dev This function can be called by any address even if it is not included in the stage configuration.
    ///      `_canProposalAdvance` function ensures that only records from addresses
    ///      in the stage configuration are used.
    ///      If `_tryAdvance` is true, the proposal will attempt to advance to the next stage if eligible.
    ///      Requires the caller to have the `EXECUTE_PERMISSION_ID` permission to execute the final stage.
    /// @param _proposalId The ID of the proposal.
    /// @param _stageId The index of the stage, being reported on. Must not exceed the current stage of the proposal.
    /// @param _resultType The result type being reported (`Approval` or `Veto`).
    /// @param _tryAdvance Whether to attempt advancing the proposal to the next stage if conditions are met.
    function reportProposalResult(
        uint256 _proposalId,
        uint16 _stageId,
        ResultType _resultType,
        bool _tryAdvance
    ) external virtual {
        Proposal storage proposal = proposals[_proposalId];

        if (!_proposalExists(proposal)) {
            revert Errors.NonexistentProposal(_proposalId);
        }

        uint16 currentStage = proposal.currentStage;

        // Ensure that result can not be submitted
        // for the stage that has not yet become active.
        if (_stageId > currentStage) {
            revert Errors.StageIdInvalid(currentStage, _stageId);
        }

        address sender = _msgSender();

        _processProposalResult(_proposalId, _stageId, _resultType, sender);

        if (!_tryAdvance) {
            return;
        }

        // If the last stage, caller must have `EXECUTE_PERMISSION_ID`, otherwise `ADVANCE_PERMISSION_ID`.
        bool hasPermission = _isAtLastStage(proposal)
            ? hasExecutePermission(sender)
            : hasAdvancePermission(sender);

        // It's important to not revert and silently succeed even if proposal
        // can not advance due to permission or state, because as sub-body's
        // proposals could contain other actions that should still succeed.
        if (hasPermission && state(_proposalId) == ProposalState.Advanceable) {
            _advanceProposal(_proposalId, sender);
        }
    }

    /// @inheritdoc IProposal
    /// @dev This plugin inherits from `IProposal`, requiring an override for this function.
    function customProposalParamsABI() external pure virtual override returns (string memory) {
        return "(bytes[][] subBodiesCustomProposalParamsABI)";
    }

    /// @notice Sets a new trusted forwarder address.
    /// @dev Requires the caller to have the `SET_TRUSTED_FORWARDER_PERMISSION_ID` permission.
    /// @param _forwarder The new trusted forwarder address.
    function setTrustedForwarder(
        address _forwarder
    ) public virtual auth(Permissions.SET_TRUSTED_FORWARDER_PERMISSION_ID) {
        _setTrustedForwarder(_forwarder);
    }

    /// @notice Creates a new proposal in this `StagedProposalProcessor` plugin.
    /// @dev Requires the caller to have the `CREATE_PROPOSAL_PERMISSION_ID` permission.
    ///      Also creates proposals for non-manual bodies in the first stage of the proposal process.
    /// @param _metadata The metadata of the proposal.
    /// @param _actions The actions that will be executed after the proposal passes.
    /// @param _allowFailureMap Allows proposal to succeed even if an action reverts.
    ///     Uses bitmap representation.
    ///     If the bit at index `x` is 1, the tx succeeds even if the action at `x` failed.
    ///     Passing 0 will be treated as atomic execution.
    /// @param _startDate The date at which first stage's bodies' proposals must be started at.
    /// @param _proposalParams The extra abi encoded parameters for each sub-body's createProposal function.
    /// @return proposalId The ID of the proposal.
    function createProposal(
        bytes memory _metadata,
        Action[] memory _actions,
        uint128 _allowFailureMap,
        uint64 _startDate,
        bytes[][] memory _proposalParams
    ) public virtual auth(Permissions.CREATE_PROPOSAL_PERMISSION_ID) returns (uint256 proposalId) {
        // If `currentConfigIndex` is 0, this means the plugin was installed
        // with empty configurations and still hasn't updated stages
        // in which case we should revert.
        uint16 index = getCurrentConfigIndex();
        if (index == 0) {
            revert Errors.StageCountZero();
        }

        address creator = _msgSender();

        proposalId = _createProposalId(keccak256(abi.encode(_actions, _metadata, creator)));

        Proposal storage proposal = proposals[proposalId];

        if (_proposalExists(proposal)) {
            revert Errors.ProposalAlreadyExists(proposalId);
        }

        proposal.allowFailureMap = _allowFailureMap;
        proposal.targetConfig = getTargetConfig();
        proposal.creator = creator;

        // store stage configuration per proposal to avoid
        // changing it while proposal is still open
        proposal.stageConfigIndex = index;

        if (_startDate == 0) {
            _startDate = uint64(block.timestamp);
        } else if (_startDate < uint64(block.timestamp)) {
            revert Errors.StartDateInvalid(_startDate);
        }

        proposal.lastStageTransition = _startDate;

        for (uint256 i = 0; i < _actions.length; ++i) {
            proposal.actions.push(_actions[i]);
        }

        if (_proposalParams.length > type(uint16).max) {
            revert Errors.Uint16MaxSizeExceeded();
        }

        // To reduce the gas costs significantly, don't store the very
        // first stage's params in storage as they only get used in this
        // current tx and will not be needed later on for advancing.
        for (uint256 i = 1; i < _proposalParams.length; ++i) {
            for (uint256 j = 0; j < _proposalParams[i].length; ++j) {
                createProposalParams[proposalId][uint16(i)][j] = _proposalParams[i][j];
            }
        }

        _createBodyProposals(
            proposalId,
            0,
            proposal.lastStageTransition,
            _proposalParams.length > 0 ? _proposalParams[0] : new bytes[](0)
        );

        emit ProposalCreated({
            proposalId: proposalId,
            creator: creator,
            startDate: proposal.lastStageTransition,
            endDate: 0,
            metadata: _metadata,
            actions: _actions,
            allowFailureMap: _allowFailureMap
        });
    }

    /// @inheritdoc IProposal
    /// @dev Calls a public function that requires the `CREATE_PERMISSION_ID` permission.
    function createProposal(
        bytes memory _metadata,
        Action[] memory _actions,
        uint64 _startDate,
        uint64 /** */,
        bytes memory _data
    ) public virtual override returns (uint256 proposalId) {
        proposalId = createProposal(
            _metadata,
            _actions,
            0,
            _startDate,
            abi.decode(_data, (bytes[][]))
        );
    }

    /// @notice Advances the specified proposal to the next stage if allowed.
    /// @dev This function checks whether the proposal exists and can advance based on its current state.
    ///      If the proposal is in the final stage, the caller must have the
    ///      `EXECUTE_PERMISSION_ID` permission to execute it.
    /// @param _proposalId The ID of the proposal.
    function advanceProposal(uint256 _proposalId) public virtual {
        Proposal storage proposal = proposals[_proposalId];

        // Reverts if proposal is not Advanceable or is non-existent.
        _validateStateBitmap(_proposalId, _encodeStateBitmap(ProposalState.Advanceable));

        address sender = _msgSender();

        // If the last stage, caller must have `EXECUTE_PERMISSION_ID`, otherwise `ADVANCE_PERMISSION_ID`.
        bool hasPermission;
        if (_isAtLastStage(proposal)) {
            hasPermission = hasExecutePermission(sender);
            if (!hasPermission) revert Errors.ProposalExecutionForbidden(_proposalId);
        } else {
            hasPermission = hasAdvancePermission(sender);
            if (!hasPermission) revert Errors.ProposalAdvanceForbidden(_proposalId);
        }

        _advanceProposal(_proposalId, sender);
    }

    /// @notice Cancels the proposal.
    /// @dev The proposal can be canceled only if it's allowed in the stage configuration.
    ///      The caller must have the `CANCEL_PERMISSION_ID` permission to cancel it.
    /// @param _proposalId The id of the proposal.
    function cancel(uint256 _proposalId) public virtual auth(Permissions.CANCEL_PERMISSION_ID) {
        Proposal storage proposal = proposals[_proposalId];

        // Reverts if proposal is not Active, Advanceable or doesn't exist.
        _validateStateBitmap(
            _proposalId,
            _encodeStateBitmap(ProposalState.Active) | _encodeStateBitmap(ProposalState.Advanceable)
        );

        uint16 currentStage = proposal.currentStage;
        Stage storage stage = stages[proposal.stageConfigIndex][currentStage];

        if (!stage.cancelable) {
            revert Errors.ProposalCanNotBeCancelled(_proposalId, currentStage);
        }

        proposal.canceled = true;

        emit ProposalCanceled(_proposalId, currentStage, _msgSender());
    }

    /// @notice Edits the proposal.
    /// @dev The proposal can be editable only if it's allowed in the stage configuration.
    ///      The caller must have the `EDIT_PERMISSION_ID` permission to edit
    ///      and stage must be advanceable.
    /// @param _proposalId The id of the proposal.
    /// @param _metadata The metadata of the proposal.
    /// @param _actions The actions that will be executed after the proposal passes.
    function edit(
        uint256 _proposalId,
        bytes calldata _metadata,
        Action[] calldata _actions
    ) public virtual auth(Permissions.EDIT_PERMISSION_ID) {
        Proposal storage proposal = proposals[_proposalId];

        // Reverts if proposal doesn't exist.
        ProposalState currentState = _validateStateBitmap(
            _proposalId,
            _encodeStateBitmap(ProposalState.Advanceable) | _encodeStateBitmap(ProposalState.Active)
        );

        uint16 currentStage = proposal.currentStage;
        Stage storage stage = stages[proposal.stageConfigIndex][currentStage];

        // If there're bodies in a stage, state must be Advanceable, otherwise revert.
        if (stage.bodies.length != 0 && currentState != ProposalState.Advanceable) {
            revert Errors.UnexpectedProposalState(
                _proposalId,
                uint8(currentState),
                _encodeStateBitmap(ProposalState.Advanceable)
            );
        }

        if (!stage.editable) {
            revert Errors.ProposalCanNotBeEdited(_proposalId, currentStage);
        }

        delete proposal.actions;

        for (uint256 i = 0; i < _actions.length; ++i) {
            proposal.actions.push(_actions[i]);
        }

        emit ProposalEdited(_proposalId, currentStage, _msgSender(), _metadata, _actions);
    }

    /// @inheritdoc IProposal
    /// @dev Requires the `EXECUTE_PERMISSION_ID` permission.
    function execute(
        uint256 _proposalId
    ) public virtual auth(Permissions.EXECUTE_PROPOSAL_PERMISSION_ID) {
        if (!canExecute(_proposalId)) {
            revert Errors.ProposalExecutionForbidden(_proposalId);
        }

        _executeProposal(_proposalId);
    }

    /// @notice Checks if this or the parent contract supports an interface by its ID.
    /// @param _interfaceId The ID of the interface.
    /// @return Returns `true` if the interface is supported.
    function supportsInterface(
        bytes4 _interfaceId
    )
        public
        view
        virtual
        override(PluginUUPSUpgradeable, MetadataExtensionUpgradeable, ProposalUpgradeable)
        returns (bool)
    {
        return super.supportsInterface(_interfaceId);
    }

    /// @notice Indicates whether any particular address is the trusted forwarder.
    /// @param _forwarder The address of the Forwarder contract that is being used.
    /// @return `true` if the forwarder is trusted, otherwise false.
    function isTrustedForwarder(address _forwarder) public view virtual returns (bool) {
        return _forwarder == getTrustedForwarder();
    }

    /// @notice Determines whether the specified proposal can be advanced to the next stage.
    /// @dev Reverts if the proposal with the given `_proposalId` does not exist.
    /// @param _proposalId The unique identifier of the proposal to check.
    /// @return Returns `true` if the proposal can be advanced to the next stage, otherwise `false`.
    function canProposalAdvance(uint256 _proposalId) public view virtual returns (bool) {
        // `state` reverts if proposal is non existent.
        return state(_proposalId) == ProposalState.Advanceable;
    }

    /// @inheritdoc IProposal
    function canExecute(uint256 _proposalId) public view virtual returns (bool) {
        Proposal storage proposal = proposals[_proposalId];

        // 1. `state` reverts if proposal is non existent.
        // 2. Proposal must be on the last stage and be advanceable.
        return state(_proposalId) == ProposalState.Advanceable && _isAtLastStage(proposal);
    }

    /// @notice Current state of a proposal.
    /// @param _proposalId The proposal id.
    /// @return The current state of the proposal.
    function state(uint256 _proposalId) public view virtual returns (ProposalState) {
        Proposal storage proposal = proposals[_proposalId];

        if (proposal.executed) {
            return ProposalState.Executed;
        }

        if (proposal.canceled) {
            return ProposalState.Canceled;
        }

        if (!_proposalExists(proposal)) {
            revert Errors.NonexistentProposal(_proposalId);
        }

        Stage storage stage = stages[proposal.stageConfigIndex][proposal.currentStage];

        if (proposal.lastStageTransition + stage.maxAdvance < block.timestamp) {
            return ProposalState.Expired;
        }

        if (proposal.lastStageTransition + stage.minAdvance > block.timestamp) {
            return ProposalState.Active;
        }

        if (stage.vetoThreshold > 0) {
            if (proposal.lastStageTransition + stage.voteDuration > block.timestamp) {
                return ProposalState.Active;
            }
        }

        bool thresholdMet = _thresholdsMet(
            _proposalId,
            proposal.currentStage,
            stage.approvalThreshold,
            stage.vetoThreshold
        );

        if (thresholdMet) {
            return ProposalState.Advanceable;
        }

        return ProposalState.Active;
    }

    /// @notice Retrieves the address of the trusted forwarder.
    /// @return The address of the trusted forwarder.
    function getTrustedForwarder() public view virtual returns (address) {
        return trustedForwarder;
    }

    /// @notice Retrieves all information associated with a proposal by its ID.
    /// @param _proposalId The ID of the proposal.
    /// @return The proposal struct
    function getProposal(uint256 _proposalId) public view returns (Proposal memory) {
        return proposals[_proposalId];
    }

    /// @notice Retrieves the result type submitted by a body for a specific proposal and stage.
    /// @param _proposalId The ID of the proposal.
    /// @param _stageId The stage index.
    /// @param _body The address of the sub-body.
    /// @return Returns what resultType the body reported the result with.
    ///     Returns `None (0)` if no result has been provided yet.
    function getBodyResult(
        uint256 _proposalId,
        uint16 _stageId,
        address _body
    ) public view virtual returns (ResultType) {
        return bodyResults[_proposalId][_stageId][_body];
    }

    /// @notice Retrieves the sub proposal id.
    /// @param _proposalId The ID of the proposal.
    /// @param _stageId The stage index.
    /// @param _body The address of the sub-body.
    /// @return Returns what resultType the body reported the result with.
    ///     Returns `None (0)` if no result has been provided yet.
    function getBodyProposalId(
        uint256 _proposalId,
        uint16 _stageId,
        address _body
    ) public view virtual returns (uint256) {
        return bodyProposalIds[_proposalId][_stageId][_body];
    }

    /// @notice Retrieves the current configuration index at which the current configurations of stages are stored.
    /// @return The index of the current configuration in the `stages` mapping.
    function getCurrentConfigIndex() public view returns (uint16) {
        return currentConfigIndex;
    }

    /// @notice Retrieves the stages stored on the `_index` in the `stages` configuration.
    /// @param _index The index from which to get the stages configuration.
    /// @return The array of `Stage` structs.
    function getStages(uint256 _index) public view virtual returns (Stage[] memory) {
        if (_index > getCurrentConfigIndex() || _index == 0) {
            revert Errors.StageCountZero();
        }

        return stages[_index];
    }

    /// @notice Retrieves the `data` parameter encoded for a sub-body's `createProposal` function in a specific stage.
    ///         Excludes sub-bodies from the first stage, as their parameters are not stored for efficiency.
    /// @param _proposalId The ID of the proposal.
    /// @param _stageId The stage index.
    /// @param _index The index of the body within the stage.
    /// @return The encoded `data` parameter for the specified sub-body's `createProposal` function.
    function getCreateProposalParams(
        uint256 _proposalId,
        uint16 _stageId,
        uint256 _index
    ) public view returns (bytes memory) {
        return createProposalParams[_proposalId][_stageId][_index];
    }

    /// @notice Calculates and retrieves the number of approvals and vetoes for a proposal on the stage.
    /// @param _proposalId The proposal ID.
    /// @param _stageId The stage index.
    /// @return approvals The total number of approvals for the proposal.
    /// @return vetoes The total number of vetoes for the proposal.
    function getProposalTally(
        uint256 _proposalId,
        uint16 _stageId
    ) public view virtual returns (uint256 approvals, uint256 vetoes) {
        Proposal storage proposal = proposals[_proposalId];

        if (!_proposalExists(proposal)) {
            revert Errors.NonexistentProposal(_proposalId);
        }

        return _getProposalTally(_proposalId, _stageId);
    }

    /// @inheritdoc IProposal
    function hasSucceeded(uint256 _proposalId) public view virtual override returns (bool) {
        Proposal storage proposal = proposals[_proposalId];

        // `state` reverts if proposal is non existent.
        ProposalState currentState = state(_proposalId);

        // Proposal must be on the last stage and either advanceable or executed.
        return
            _isAtLastStage(proposal) &&
            (currentState == ProposalState.Advanceable || currentState == ProposalState.Executed);
    }

    /// @notice Checks whether the caller has the required permission to execute a proposal at the last stage.
    /// @param _account The address on which the `EXECUTE_PERMISSION_ID` is checked.
    /// @return Returns `true` if the caller has the `EXECUTE_PERMISSION_ID` permission, otherwise `false`.
    function hasExecutePermission(address _account) public view virtual returns (bool) {
        return
            dao().hasPermission(
                address(this),
                _account,
                Permissions.EXECUTE_PROPOSAL_PERMISSION_ID,
                _msgData()
            );
    }

    /// @notice Checks whether the caller has the required permission to advance a proposal.
    /// @param _account The address on which the `ADVANCE_PERMISSION_ID` is checked.
    /// @return Returns `true` if the caller has the `ADVANCE_PERMISSION_ID` permission, otherwise `false`.
    function hasAdvancePermission(address _account) public view virtual returns (bool) {
        return
            dao().hasPermission(
                address(this),
                _account,
                Permissions.ADVANCE_PERMISSION_ID,
                _msgData()
            );
    }

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

    /// @notice Internal function to update stage configuration.
    /// @dev It's a caller's responsibility not to call this in case `_stages` are empty.
    ///      This function can not be overridden as it's crucial to not allow duplicating bodies
    ///      in the same stage, because proposal creation and report functions depend on this assumption.
    /// @param _stages The stages configuration.
    function _updateStages(Stage[] memory _stages) internal {
        Stage[] storage storedStages = stages[++currentConfigIndex];

        for (uint256 i = 0; i < _stages.length; ++i) {
            Stage storage stage = storedStages.push();
            Body[] memory bodies = _stages[i].bodies;

            uint64 maxAdvance = _stages[i].maxAdvance;
            uint64 minAdvance = _stages[i].minAdvance;
            uint64 voteDuration = _stages[i].voteDuration;
            uint16 approvalThreshold = _stages[i].approvalThreshold;
            uint16 vetoThreshold = _stages[i].vetoThreshold;

            if (minAdvance >= maxAdvance || voteDuration >= maxAdvance) {
                revert Errors.StageDurationsInvalid();
            }

            if (approvalThreshold > bodies.length || vetoThreshold > bodies.length) {
                revert Errors.StageThresholdsInvalid();
            }

            for (uint256 j = 0; j < bodies.length; ++j) {
                // Ensure that body addresses are not duplicated in the same stage.
                for (uint256 k = j + 1; k < bodies.length; ++k) {
                    if (bodies[j].addr == bodies[k].addr) {
                        revert Errors.DuplicateBodyAddress(i, bodies[j].addr);
                    }
                }

                // If the sub-body accepts an automatic creation by SPP,
                // then it must obey `IProposal` interface.
                if (
                    !bodies[j].isManual &&
                    !bodies[j].addr.supportsInterface(type(IProposal).interfaceId)
                ) {
                    revert Errors.InterfaceNotSupported();
                }

                // body result type must be set
                if (bodies[j].resultType == ResultType.None) {
                    revert Errors.BodyResultTypeNotSet(bodies[j].addr);
                }

                // If not copied manually, requires via-ir compilation
                // pipeline which is still slow.
                stage.bodies.push(bodies[j]);
            }

            stage.maxAdvance = maxAdvance;
            stage.minAdvance = minAdvance;
            stage.voteDuration = voteDuration;
            stage.approvalThreshold = approvalThreshold;
            stage.vetoThreshold = vetoThreshold;
            stage.cancelable = _stages[i].cancelable;
            stage.editable = _stages[i].editable;
        }

        emit StagesUpdated(_stages);
    }

    /// @notice Internal function that executes the proposal's actions.
    /// @param _proposalId The ID of the proposal.
    function _executeProposal(uint256 _proposalId) internal virtual {
        Proposal storage proposal = proposals[_proposalId];

        proposal.executed = true;

        _execute(
            proposal.targetConfig.target,
            bytes32(_proposalId),
            proposal.actions,
            uint256(proposal.allowFailureMap),
            proposal.targetConfig.operation
        );

        emit ProposalExecuted(_proposalId);
    }

    /// @notice Records the result by the caller.
    /// @dev Assumes that bodies are not duplicated in the same stage. See `_updateStages` function.
    /// @param _proposalId The ID of the proposal.
    /// @param _stageId The stage index.
    /// @param _resultType The result type being reported (`Approval` or `Veto`).
    /// @param _sender The address that reported the result.
    function _processProposalResult(
        uint256 _proposalId,
        uint16 _stageId,
        ResultType _resultType,
        address _sender
    ) internal virtual {
        bodyResults[_proposalId][_stageId][_sender] = _resultType;
        emit ProposalResultReported(_proposalId, _stageId, _sender);
    }

    /// @notice Creates proposals on the non-manual bodies of the `stageId`.
    /// @dev Assumes that bodies are not duplicated in the same stage. See `_updateStages` function.
    /// @param _proposalId The ID of the proposal.
    /// @param _stageId The stage index.
    /// @param _startDate The start date that proposals on sub-bodies will be created with.
    /// @param _stageProposalParams The custom params required for each sub-body to create a proposal.
    function _createBodyProposals(
        uint256 _proposalId,
        uint16 _stageId,
        uint64 _startDate,
        bytes[] memory _stageProposalParams
    ) internal virtual {
        Stage storage stage;

        // avoid stack too deep.
        {
            Proposal storage proposal = proposals[_proposalId];
            stage = stages[proposal.stageConfigIndex][_stageId];
        }

        for (uint256 i = 0; i < stage.bodies.length; ++i) {
            Body storage body = stage.bodies[i];

            // If body proposal creation should be manual, skip it.
            if (body.isManual) continue;

            Action[] memory actions = new Action[](1);

            actions[0] = Action({
                to: address(this),
                value: 0,
                data: abi.encodeCall(
                    this.reportProposalResult,
                    (_proposalId, _stageId, body.resultType, body.tryAdvance)
                )
            });

            // Make sure that the `createProposal` call did not fail because
            // 63/64 of `gasleft()` was insufficient to execute the external call.
            // In specific scenarios, the sender could force-fail `createProposal`
            // where 63/64 is insufficient causing it to fail, but where
            // the remaining 1/64 gas are sufficient to successfully finish the call.
            // See `InsufficientGas` revert below.
            uint256 gasBefore = gasleft();
            // solhint-disable-next-line avoid-low-level-calls
            (bool success, bytes memory data) = body.addr.call(
                abi.encodeCall(
                    IProposal.createProposal,
                    (
                        abi.encode(address(this), _proposalId, _stageId),
                        actions,
                        _startDate,
                        _startDate + stage.voteDuration,
                        _stageProposalParams.length > i ? _stageProposalParams[i] : new bytes(0)
                    )
                )
            );

            uint256 gasAfter = gasleft();

            // NOTE: Handles the edge case where:
            // on success: it could return 0.
            // on failure: default 0 would be used.
            // In order to differentiate, we store `PROPOSAL_WITHOUT_ID` on failure.

            if (!success) {
                if (gasAfter < gasBefore / 64) {
                    revert Errors.InsufficientGas();
                }
            }

            if (success && data.length == 32) {
                uint256 subProposalId = abi.decode(data, (uint256));
                bodyProposalIds[_proposalId][_stageId][body.addr] = subProposalId;

                emit SubProposalCreated(_proposalId, _stageId, body.addr, subProposalId);
            } else {
                // sub-proposal was not created on sub-body, emit
                // the event and try the next sub-body without failing
                // the main(outer) tx.
                bodyProposalIds[_proposalId][_stageId][body.addr] = PROPOSAL_WITHOUT_ID;

                emit SubProposalNotCreated(_proposalId, _stageId, body.addr, data);
            }
        }
    }

    /// @notice Advances a proposal to the next stage or executes it if it is in the final stage.
    /// @dev Assumes the proposal is eligible to advance. If the proposal is not in the final stage,
    ///      it creates proposals for the sub-bodies in the next stage.
    ///      If the proposal is in the final stage, it triggers execution.
    /// @param _proposalId The ID of the proposal.
    /// @param _sender The address that advances the proposal.
    function _advanceProposal(uint256 _proposalId, address _sender) internal virtual {
        Proposal storage _proposal = proposals[_proposalId];
        Stage[] storage _stages = stages[_proposal.stageConfigIndex];

        if (_proposal.currentStage < _stages.length - 1) {
            // is not last stage
            uint16 newStage = ++_proposal.currentStage;
            _proposal.lastStageTransition = uint64(block.timestamp);

            // Grab the next stage's bodies' custom params of `createProposal`.
            bytes[] memory customParams = new bytes[](_stages[newStage].bodies.length);
            for (uint256 i = 0; i < _stages[newStage].bodies.length; i++) {
                customParams[i] = createProposalParams[_proposalId][newStage][i];
            }

            _createBodyProposals(_proposalId, newStage, uint64(block.timestamp), customParams);

            emit ProposalAdvanced(_proposalId, newStage, _sender);
        } else {
            _executeProposal(_proposalId);
        }
    }

    /// @notice Sets a new trusted forwarder address and emits the event.
    /// @param _forwarder The trusted forwarder.
    function _setTrustedForwarder(address _forwarder) internal virtual {
        trustedForwarder = _forwarder;

        emit TrustedForwarderUpdated(_forwarder);
    }

    /// @notice Internal function to calculate and retrieve the number of approvals and
    ///         vetoes for a proposal in the `_stageId`.
    /// @dev Assumes that bodies are not duplicated in the same stage. See `_updateStages` function.
    ///      This function ensures that only records from addresses in the stage configuration are used.
    /// @param _proposalId The proposal Id.
    /// @param _stageId The stage index.
    /// @return approvals The number of approvals for the proposal.
    /// @return vetoes The number of vetoes for the proposal.
    function _getProposalTally(
        uint256 _proposalId,
        uint16 _stageId
    ) internal view virtual returns (uint256 approvals, uint256 vetoes) {
        // Cheaper to do 2nd sload than to pass Proposal memory.
        Proposal storage proposal = proposals[_proposalId];
        Stage storage stage = stages[proposal.stageConfigIndex][_stageId];

        uint256 length = stage.bodies.length;

        for (uint256 i = 0; i < length; ++i) {
            Body storage body = stage.bodies[i];

            uint256 bodyProposalId = getBodyProposalId(_proposalId, _stageId, body.addr);
            ResultType resultType = getBodyResult(_proposalId, _stageId, body.addr);

            if (resultType != ResultType.None) {
                // result was already reported
                resultType == ResultType.Approval ? ++approvals : ++vetoes;
            } else if (bodyProposalId != PROPOSAL_WITHOUT_ID && !body.isManual) {
                // result was not reported yet
                // Use low-level call to ensure that outer tx doesn't revert
                // which would cause proposal to never be able to advance.
                (bool success, bytes memory data) = body.addr.staticcall(
                    abi.encodeCall(IProposal.hasSucceeded, (bodyProposalId))
                );

                if (success && data.length == 32) {
                    bool succeeded = abi.decode(data, (bool));
                    if (succeeded) {
                        body.resultType == ResultType.Approval ? ++approvals : ++vetoes;
                    }
                }
            }
        }
    }

    /// @notice Retrieves the original sender address, considering if the call was made through a trusted forwarder.
    /// @dev If the `msg.sender` is the trusted forwarder, extracts the original sender from the calldata.
    /// @return The address of the original caller or the `msg.sender` if not called through the trusted forwarder.
    function _msgSender() internal view override returns (address) {
        uint256 calldataLength = msg.data.length;

        if (isTrustedForwarder(msg.sender) && calldataLength >= 20) {
            // At this point we know that the sender is a trusted forwarder,
            // so we trust that the last bytes of msg.data are the verified sender address.
            // extract sender address from the end of msg.data
            return address(bytes20(msg.data[calldataLength - 20:]));
        } else {
            return msg.sender;
        }
    }

    /// @notice Overrides for `msg.data`. Defaults to the original `msg.data` whenever
    ///         a call is not performed by the trusted forwarder or the calldata length
    ///         is less than 20 bytes (an address length).
    /// @return The calldata without appended address.
    function _msgData() internal view virtual override returns (bytes calldata) {
        uint256 calldataLength = msg.data.length;

        if (isTrustedForwarder(msg.sender) && calldataLength >= 20) {
            return msg.data[:calldataLength - 20];
        } else {
            return msg.data;
        }
    }

    /// @notice Internal helper function that decides if the stage's thresholds are satisfied.
    /// @param _proposalId The proposal id.
    /// @param _stageId The stage index.
    /// @param _approvalThreshold The approval threshold of the `_stageId`.
    /// @param _vetoThreshold The veto threshold of the `_stageId`.
    /// @return Returns true if the thresholds are met, otherwise false.
    function _thresholdsMet(
        uint256 _proposalId,
        uint16 _stageId,
        uint256 _approvalThreshold,
        uint256 _vetoThreshold
    ) internal view returns (bool) {
        (uint256 approvals, uint256 vetoes) = _getProposalTally(_proposalId, _stageId);

        if (_vetoThreshold > 0 && vetoes >= _vetoThreshold) {
            return false;
        }

        if (approvals < _approvalThreshold) {
            return false;
        }

        return true;
    }

    /// @notice Encodes a `ProposalState` into a `bytes32` representation where each bit enabled
    ///         corresponds the underlying position in the `ProposalState` enum.
    /// @param _proposalState The state of the proposal.
    /// @return The bytes32 bitmap representation of the proposal state.
    function _encodeStateBitmap(ProposalState _proposalState) internal pure returns (bytes32) {
        return bytes32(1 << uint8(_proposalState));
    }

    /// @notice Checks if proposal is at the last stage or not.
    /// @param _proposal The proposal struct.
    /// @return Returns `true` if proposal is at the last stage, otherwise false.
    function _isAtLastStage(Proposal storage _proposal) private view returns (bool) {
        return _proposal.currentStage == stages[_proposal.stageConfigIndex].length - 1;
    }

    /// @notice Checks if proposal exists or not.
    /// @param _proposal The proposal struct.
    /// @return Returns `true` if proposal exists, otherwise false.
    function _proposalExists(Proposal storage _proposal) private view returns (bool) {
        return _proposal.lastStageTransition != 0;
    }

    /// @notice Check that the current state of a proposal matches the requirements described by the
    ///         `allowedStates` bitmap. This bitmap should be built using `_encodeStateBitmap`.
    /// @param _proposalId The proposal id.
    /// @param _allowedStates The allowed states that proposal can be in.
    /// @return Returns the current state of the proposal.
    function _validateStateBitmap(
        uint256 _proposalId,
        bytes32 _allowedStates
    ) private view returns (ProposalState) {
        ProposalState currentState = state(_proposalId);
        if (_encodeStateBitmap(currentState) & _allowedStates == bytes32(0)) {
            revert Errors.UnexpectedProposalState(_proposalId, uint8(currentState), _allowedStates);
        }
        return currentState;
    }

    /// @dev This empty reserved space is put in place to allow future versions to add new
    /// variables without shifting down storage in the inheritance chain.
    /// https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
    uint256[44] private __gap;
}

File 4 of 48 : Permissions.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.18;

library Permissions {
    /// @notice The ID of the permission required to call the `createProposal` function.
    bytes32 internal constant CREATE_PROPOSAL_PERMISSION_ID =
        keccak256("CREATE_PROPOSAL_PERMISSION");

    /// @notice The ID of the permission required to call the `setTrustedForwarder` function.
    bytes32 internal constant SET_TRUSTED_FORWARDER_PERMISSION_ID =
        keccak256("SET_TRUSTED_FORWARDER_PERMISSION");

    /// @notice The ID of the permission required to call the `updateStages` function.
    bytes32 internal constant UPDATE_STAGES_PERMISSION_ID = keccak256("UPDATE_STAGES_PERMISSION");

    /// @notice The ID of the permission required to execute the proposal if it's on the last stage.
    /// @dev It is important to use a different identifier than {keccak256("EXECUTE_PERMISSION")} to ensure
    ///      that it can still be granted with ANY_ADDR. Refer to the DAO.sol function -
    ///      {isPermissionRestrictedForAnyAddr} for more details.
    bytes32 internal constant EXECUTE_PROPOSAL_PERMISSION_ID =
        keccak256("EXECUTE_PROPOSAL_PERMISSION");

    /// @notice The ID of the permission required to execute the proposal on the dao.
    bytes32 internal constant EXECUTE_PERMISSION_ID = keccak256("EXECUTE_PERMISSION");

    /// @notice The ID of the permission required to cancel the proposal.
    bytes32 internal constant CANCEL_PERMISSION_ID = keccak256("CANCEL_PERMISSION");

    /// @notice The ID of the permission required to advance the proposal.
    bytes32 internal constant ADVANCE_PERMISSION_ID = keccak256("ADVANCE_PERMISSION");

    /// @notice The ID of the permission required to edit the proposal.
    bytes32 internal constant EDIT_PERMISSION_ID = keccak256("EDIT_PERMISSION");

    /// @notice The ID of the permission required to call the `updateRules` function.
    bytes32 internal constant UPDATE_RULES_PERMISSION_ID = keccak256("UPDATE_RULES_PERMISSION");

    /// @notice The ID of the permission required to call the `setTargetConfig` function.
    bytes32 internal constant SET_TARGET_CONFIG_PERMISSION_ID =
        keccak256("SET_TARGET_CONFIG_PERMISSION");

    /// @notice The ID of the permission required to call the `updateMetadata` function.
    bytes32 internal constant SET_METADATA_PERMISSION_ID = keccak256("SET_METADATA_PERMISSION");
}

// SPDX-License-Identifier: AGPL-3.0-or-later

pragma solidity ^0.8.8;

/// @title IDAO
/// @author Aragon X - 2022-2024
/// @notice The interface required for DAOs within the Aragon App DAO framework.
/// @custom:security-contact [email protected]
interface IDAO {
    /// @notice Checks if an address has permission on a contract via a permission identifier and considers if `ANY_ADDRESS` was used in the granting process.
    /// @param _where The address of the contract.
    /// @param _who The address of a EOA or contract to give the permissions.
    /// @param _permissionId The permission identifier.
    /// @param _data The optional data passed to the `PermissionCondition` registered.
    /// @return Returns true if the address has permission, false if not.
    function hasPermission(
        address _where,
        address _who,
        bytes32 _permissionId,
        bytes memory _data
    ) external view returns (bool);

    /// @notice Updates the DAO metadata (e.g., an IPFS hash).
    /// @param _metadata The IPFS hash of the new metadata object.
    function setMetadata(bytes calldata _metadata) external;

    /// @notice Emitted when the DAO metadata is updated.
    /// @param metadata The IPFS hash of the new metadata object.
    event MetadataSet(bytes metadata);

    /// @notice Emitted when a standard callback is registered.
    /// @param interfaceId The ID of the interface.
    /// @param callbackSelector The selector of the callback function.
    /// @param magicNumber The magic number to be registered for the callback function selector.
    event StandardCallbackRegistered(
        bytes4 interfaceId,
        bytes4 callbackSelector,
        bytes4 magicNumber
    );

    /// @notice Deposits (native) tokens to the DAO contract with a reference string.
    /// @param _token The address of the token or address(0) in case of the native token.
    /// @param _amount The amount of tokens to deposit.
    /// @param _reference The reference describing the deposit reason.
    function deposit(address _token, uint256 _amount, string calldata _reference) external payable;

    /// @notice Emitted when a token deposit has been made to the DAO.
    /// @param sender The address of the sender.
    /// @param token The address of the deposited token.
    /// @param amount The amount of tokens deposited.
    /// @param _reference The reference describing the deposit reason.
    event Deposited(
        address indexed sender,
        address indexed token,
        uint256 amount,
        string _reference
    );

    /// @notice Emitted when a native token deposit has been made to the DAO.
    /// @dev This event is intended to be emitted in the `receive` function and is therefore bound by the gas limitations for `send`/`transfer` calls introduced by [ERC-2929](https://eips.ethereum.org/EIPS/eip-2929).
    /// @param sender The address of the sender.
    /// @param amount The amount of native tokens deposited.
    event NativeTokenDeposited(address sender, uint256 amount);

    /// @notice Setter for the trusted forwarder verifying the meta transaction.
    /// @param _trustedForwarder The trusted forwarder address.
    function setTrustedForwarder(address _trustedForwarder) external;

    /// @notice Getter for the trusted forwarder verifying the meta transaction.
    /// @return The trusted forwarder address.
    function getTrustedForwarder() external view returns (address);

    /// @notice Emitted when a new TrustedForwarder is set on the DAO.
    /// @param forwarder the new forwarder address.
    event TrustedForwarderSet(address forwarder);

    /// @notice Checks whether a signature is valid for a provided hash according to [ERC-1271](https://eips.ethereum.org/EIPS/eip-1271).
    /// @param _hash The hash of the data to be signed.
    /// @param _signature The signature byte array associated with `_hash`.
    /// @return Returns the `bytes4` magic value `0x1626ba7e` if the signature is valid and `0xffffffff` if not.
    function isValidSignature(bytes32 _hash, bytes memory _signature) external returns (bytes4);

    /// @notice Registers an ERC standard having a callback by registering its [ERC-165](https://eips.ethereum.org/EIPS/eip-165) interface ID and callback function signature.
    /// @param _interfaceId The ID of the interface.
    /// @param _callbackSelector The selector of the callback function.
    /// @param _magicNumber The magic number to be registered for the function signature.
    function registerStandardCallback(
        bytes4 _interfaceId,
        bytes4 _callbackSelector,
        bytes4 _magicNumber
    ) external;

    /// @notice Removed function being left here to not corrupt the IDAO interface ID. Any call will revert.
    /// @dev Introduced in v1.0.0. Removed in v1.4.0.
    function setSignatureValidator(address) external;
}

File 6 of 48 : IPlugin.sol
// SPDX-License-Identifier: AGPL-3.0-or-later

pragma solidity ^0.8.8;

/// @title IPlugin
/// @author Aragon X - 2022-2024
/// @notice An interface defining the traits of a plugin.
/// @custom:security-contact [email protected]
interface IPlugin {
    /// @notice Types of plugin implementations available within OSx.
    enum PluginType {
        UUPS,
        Cloneable,
        Constructable
    }

    /// @notice Specifies the type of operation to perform.
    enum Operation {
        Call,
        DelegateCall
    }

    /// @notice Configuration for the target contract that the plugin will interact with, including the address and operation type.
    /// @dev By default, the plugin typically targets the associated DAO and performs a `Call` operation. However, this
    ///      configuration allows the plugin to specify a custom executor and select either `Call` or `DelegateCall` based on
    ///      the desired execution context.
    /// @param target The address of the target contract, typically the associated DAO but configurable to a custom executor.
    /// @param operation The type of operation (`Call` or `DelegateCall`) to execute on the target, as defined by `Operation`.
    struct TargetConfig {
        address target;
        Operation operation;
    }

    /// @notice Returns the plugin's type
    function pluginType() external view returns (PluginType);
}

// SPDX-License-Identifier: AGPL-3.0-or-later

pragma solidity ^0.8.8;

import {ERC165} from "@openzeppelin/contracts/utils/introspection/ERC165.sol";

import {IProtocolVersion} from "../../utils/versioning/IProtocolVersion.sol";
import {ProtocolVersion} from "../../utils/versioning/ProtocolVersion.sol";
import {IPluginSetup} from "./IPluginSetup.sol";

/// @title PluginUpgradeableSetup
/// @author Aragon X - 2022-2024
/// @notice An abstract contract to inherit from to implement the plugin setup for upgradeable plugins, i.e, `PluginUUPSUpgradeable` being deployed via the UUPS pattern (see [ERC-1822](https://eips.ethereum.org/EIPS/eip-1822) and [ERC-1967](https://eips.ethereum.org/EIPS/eip-1967)).
/// @custom:security-contact [email protected]
abstract contract PluginUpgradeableSetup is ERC165, IPluginSetup, ProtocolVersion {
    /// @notice The address of the plugin implementation contract for initial block explorer verification
    /// and to create [ERC-1967](https://eips.ethereum.org/EIPS/eip-1967) UUPS proxies from.
    address internal immutable IMPLEMENTATION;

    /// @notice Thrown when an update path is not available, for example, if this is the initial build.
    /// @param fromBuild The build number to update from.
    /// @param thisBuild The build number of this setup to update to.
    error InvalidUpdatePath(uint16 fromBuild, uint16 thisBuild);

    /// @notice The contract constructor, that setting the plugin implementation contract.
    /// @param _implementation The address of the plugin implementation contract.
    constructor(address _implementation) {
        IMPLEMENTATION = _implementation;
    }

    /// @notice Checks if this or the parent contract supports an interface by its ID.
    /// @param _interfaceId The ID of the interface.
    /// @return Returns `true` if the interface is supported.
    function supportsInterface(bytes4 _interfaceId) public view virtual override returns (bool) {
        return
            _interfaceId == type(IPluginSetup).interfaceId ||
            _interfaceId == type(IProtocolVersion).interfaceId ||
            super.supportsInterface(_interfaceId);
    }

    /// @inheritdoc IPluginSetup
    function implementation() public view returns (address) {
        return IMPLEMENTATION;
    }
}

// SPDX-License-Identifier: AGPL-3.0-or-later

pragma solidity ^0.8.8;

import {ERC1967Proxy} from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol";
import {Clones} from "@openzeppelin/contracts/proxy/Clones.sol";
import {Address} from "@openzeppelin/contracts/utils/Address.sol";

/// @title ProxyLib
/// @author Aragon X - 2024
/// @notice A library containing methods for the deployment of proxies via the UUPS pattern (see [ERC-1822](https://eips.ethereum.org/EIPS/eip-1822)) and minimal proxy pattern (see [ERC-1167](https://eips.ethereum.org/EIPS/eip-1167)).
/// @custom:security-contact [email protected]
library ProxyLib {
    using Address for address;
    using Clones for address;

    /// @notice Creates an [ERC-1967](https://eips.ethereum.org/EIPS/eip-1967) UUPS proxy contract pointing to a logic contract and allows to immediately initialize it.
    /// @param _logic The logic contract the proxy is pointing to.
    /// @param _initCalldata The initialization data for this contract.
    /// @return uupsProxy The address of the UUPS proxy contract created.
    /// @dev If `_initCalldata` is non-empty, it is used in a delegate call to the `_logic` contract. This will typically be an encoded function call initializing the storage of the proxy (see [OpenZeppelin ERC1967Proxy-constructor](https://docs.openzeppelin.com/contracts/4.x/api/proxy#ERC1967Proxy-constructor-address-bytes-)).
    function deployUUPSProxy(
        address _logic,
        bytes memory _initCalldata
    ) internal returns (address uupsProxy) {
        uupsProxy = address(new ERC1967Proxy({_logic: _logic, _data: _initCalldata}));
    }

    /// @notice Creates an [ERC-1167](https://eips.ethereum.org/EIPS/eip-1167) minimal proxy contract, also known as clones, pointing to a logic contract and allows to immediately initialize it.
    /// @param _logic The logic contract the proxy is pointing to.
    /// @param _initCalldata The initialization data for this contract.
    /// @return minimalProxy The address of the minimal proxy contract created.
    /// @dev If `_initCalldata` is non-empty, it is used in a call to the clone contract. This will typically be an encoded function call initializing the storage of the contract.
    function deployMinimalProxy(
        address _logic,
        bytes memory _initCalldata
    ) internal returns (address minimalProxy) {
        minimalProxy = _logic.clone();
        if (_initCalldata.length > 0) {
            minimalProxy.functionCall({data: _initCalldata});
        }
    }
}

// SPDX-License-Identifier: AGPL-3.0-or-later

pragma solidity ^0.8.8;

import {PermissionLib} from "../../permission/PermissionLib.sol";

// solhint-disable-next-line no-unused-import
import {IDAO} from "../../dao/IDAO.sol";

/// @title IPluginSetup
/// @author Aragon X - 2022-2023
/// @notice The interface required for a plugin setup contract to be consumed by the `PluginSetupProcessor` for plugin installations, updates, and uninstallations.
/// @custom:security-contact [email protected]
interface IPluginSetup {
    /// @notice The data associated with a prepared setup.
    /// @param helpers The address array of helpers (contracts or EOAs) associated with this plugin version after the installation or update.
    /// @param permissions The array of multi-targeted permission operations to be applied by the `PluginSetupProcessor` to the installing or updating DAO.
    struct PreparedSetupData {
        address[] helpers;
        PermissionLib.MultiTargetPermission[] permissions;
    }

    /// @notice The payload for plugin updates and uninstallations containing the existing contracts as well as optional data to be consumed by the plugin setup.
    /// @param plugin The address of the `Plugin`.
    /// @param currentHelpers The address array of all current helpers (contracts or EOAs) associated with the plugin to update from.
    /// @param data The bytes-encoded data containing the input parameters for the preparation of update/uninstall as specified in the corresponding ABI on the version's metadata.
    struct SetupPayload {
        address plugin;
        address[] currentHelpers;
        bytes data;
    }

    /// @notice Prepares the installation of a plugin.
    /// @param _dao The address of the installing DAO.
    /// @param _data The bytes-encoded data containing the input parameters for the installation as specified in the plugin's build metadata JSON file.
    /// @return plugin The address of the `Plugin` contract being prepared for installation.
    /// @return preparedSetupData The deployed plugin's relevant data which consists of helpers and permissions.
    function prepareInstallation(
        address _dao,
        bytes calldata _data
    ) external returns (address plugin, PreparedSetupData memory preparedSetupData);

    /// @notice Prepares the update of a plugin.
    /// @param _dao The address of the updating DAO.
    /// @param _fromBuild The build number of the plugin to update from.
    /// @param _payload The relevant data necessary for the `prepareUpdate`. See above.
    /// @return initData The initialization data to be passed to upgradeable contracts when the update is applied in the `PluginSetupProcessor`.
    /// @return preparedSetupData The deployed plugin's relevant data which consists of helpers and permissions.
    function prepareUpdate(
        address _dao,
        uint16 _fromBuild,
        SetupPayload calldata _payload
    ) external returns (bytes memory initData, PreparedSetupData memory preparedSetupData);

    /// @notice Prepares the uninstallation of a plugin.
    /// @param _dao The address of the uninstalling DAO.
    /// @param _payload The relevant data necessary for the `prepareUninstallation`. See above.
    /// @return permissions The array of multi-targeted permission operations to be applied by the `PluginSetupProcessor` to the uninstalling DAO.
    function prepareUninstallation(
        address _dao,
        SetupPayload calldata _payload
    ) external returns (PermissionLib.MultiTargetPermission[] memory permissions);

    /// @notice Returns the plugin implementation address.
    /// @return The address of the plugin implementation contract.
    /// @dev The implementation can be instantiated via the `new` keyword, cloned via the minimal proxy pattern (see [ERC-1167](https://eips.ethereum.org/EIPS/eip-1167)), or proxied via the UUPS proxy pattern (see [ERC-1822](https://eips.ethereum.org/EIPS/eip-1822)).
    function implementation() external view returns (address);
}

File 10 of 48 : PermissionLib.sol
// SPDX-License-Identifier: AGPL-3.0-or-later

pragma solidity ^0.8.8;

/// @title PermissionLib
/// @author Aragon X - 2021-2023
/// @notice A library containing objects for permission processing.
/// @custom:security-contact [email protected]
library PermissionLib {
    /// @notice A constant expressing that no condition is applied to a permission.
    address public constant NO_CONDITION = address(0);

    /// @notice The types of permission operations available in the `PermissionManager`.
    /// @param Grant The grant operation setting a permission without a condition.
    /// @param Revoke The revoke operation removing a permission (that was granted with or without a condition).
    /// @param GrantWithCondition The grant operation setting a permission with a condition.
    enum Operation {
        Grant,
        Revoke,
        GrantWithCondition
    }

    /// @notice A struct containing the information for a permission to be applied on a single target contract without a condition.
    /// @param operation The permission operation type.
    /// @param who The address (EOA or contract) receiving the permission.
    /// @param permissionId The permission identifier.
    struct SingleTargetPermission {
        Operation operation;
        address who;
        bytes32 permissionId;
    }

    /// @notice A struct containing the information for a permission to be applied on multiple target contracts, optionally, with a condition.
    /// @param operation The permission operation type.
    /// @param where The address of the target contract for which `who` receives permission.
    /// @param who The address (EOA or contract) receiving the permission.
    /// @param condition The `PermissionCondition` that will be asked for authorization on calls connected to the specified permission identifier.
    /// @param permissionId The permission identifier.
    struct MultiTargetPermission {
        Operation operation;
        address where;
        address who;
        address condition;
        bytes32 permissionId;
    }
}

// SPDX-License-Identifier: AGPL-3.0-or-later

pragma solidity ^0.8.8;

import {IPermissionCondition} from "../IPermissionCondition.sol";
import {PermissionConditionUpgradeable} from "../PermissionConditionUpgradeable.sol";

/// @title RuledCondition
/// @author Aragon X - 2024
/// @notice An abstract contract to create conditional permissions using rules.
abstract contract RuledCondition is PermissionConditionUpgradeable {
    /// @notice Identifier for a rule based on the current block number.
    uint8 internal constant BLOCK_NUMBER_RULE_ID = 200;

    /// @notice Identifier for a rule based on the current timestamp.
    uint8 internal constant TIMESTAMP_RULE_ID = 201;

    /// @notice Identifier for a rule that evaluates a condition based on another condition contract.
    uint8 internal constant CONDITION_RULE_ID = 202;

    /// @notice Identifier for a rule that is based on logical operations (e.g., AND, OR).
    uint8 internal constant LOGIC_OP_RULE_ID = 203;

    /// @notice Identifier for a rule that involves direct value comparison.
    uint8 internal constant VALUE_RULE_ID = 204;

    /// @notice Emitted when the rules are updated.
    /// @param rules The new rules that replaces old rules.
    event RulesUpdated(Rule[] rules);

    /// @notice Represents a rule used in the condition contract.
    /// @param id The ID representing the identifier of the rule.
    /// @param op The operation to apply, as defined in the `Op` enum.
    /// @param value The value associated with this rule, which could be an address, timestamp, etc.
    /// @param permissionId The specific permission ID to use for evaluating this rule. If set to `0x`, the passed permission ID will be used.
    struct Rule {
        uint8 id;
        uint8 op;
        uint240 value;
        bytes32 permissionId;
    }

    /// @notice Represents various operations that can be performed in a rule.
    /// @param NONE No operation.
    /// @param EQ Equal to operation.
    /// @param NEQ Not equal to operation.
    /// @param GT Greater than operation.
    /// @param LT Less than operation.
    /// @param GTE Greater than or equal to operation.
    /// @param LTE Less than or equal to operation.
    /// @param RET Return the evaluation result.
    /// @param NOT Logical NOT operation.
    /// @param AND Logical AND operation.
    /// @param OR Logical OR operation.
    /// @param XOR Logical XOR operation.
    /// @param IF_ELSE Conditional evaluation with IF-ELSE logic.
    enum Op {
        NONE,
        EQ,
        NEQ,
        GT,
        LT,
        GTE,
        LTE,
        RET,
        NOT,
        AND,
        OR,
        XOR,
        IF_ELSE
    }

    /// @notice A set of rules that will be used in the evaluation process.
    Rule[] private rules;

    /// @inheritdoc PermissionConditionUpgradeable
    function supportsInterface(bytes4 _interfaceId) public view virtual override returns (bool) {
        return
            _interfaceId == type(RuledCondition).interfaceId ||
            super.supportsInterface(_interfaceId);
    }

    /// @notice Retrieves the current rules stored in this contract.
    /// @return An array of `Rule` structs representing the currently defined rules.
    function getRules() public view virtual returns (Rule[] memory) {
        return rules;
    }

    /// @notice Updates the set of rules.
    /// @dev This function deletes the current set of rules and replaces it with a new one.
    /// @param _rules An new array of `Rule` structs to replace the current set of rules.
    function _updateRules(Rule[] memory _rules) internal virtual {
        delete rules;

        for (uint256 i; i < _rules.length; ) {
            rules.push(_rules[i]);
            unchecked {
                ++i;
            }
        }

        emit RulesUpdated(_rules);
    }

    /// @notice Evaluates a rule by its index.
    /// @param _ruleIndex The index of the rule to evaluate.
    /// @param _where The address of the target contract.
    /// @param _who The address (EOA or contract) for which the permissions are checked.
    /// @param _permissionId The permission identifier.
    /// @param _compareList A list of values used for comparison.
    /// @return Returns `true` if the rule passes.
    function _evalRule(
        uint32 _ruleIndex,
        address _where,
        address _who,
        bytes32 _permissionId,
        uint256[] memory _compareList
    ) internal view virtual returns (bool) {
        Rule memory rule = rules[_ruleIndex];

        if (rule.id == LOGIC_OP_RULE_ID) {
            return _evalLogic(rule, _where, _who, _permissionId, _compareList);
        }

        uint256 value;
        uint256 comparedTo = uint256(rule.value);

        // get value
        if (rule.id == CONDITION_RULE_ID) {
            bytes32 permissionId = rule.permissionId;

            bool conditionRes = _checkCondition(
                IPermissionCondition(address(uint160(rule.value))),
                _where,
                _who,
                permissionId == bytes32(0) ? _permissionId : permissionId,
                _compareList
            );
            value = conditionRes ? 1 : 0;
            comparedTo = 1;
        } else if (rule.id == BLOCK_NUMBER_RULE_ID) {
            value = block.number;
        } else if (rule.id == TIMESTAMP_RULE_ID) {
            value = block.timestamp;
        } else if (rule.id == VALUE_RULE_ID) {
            value = uint256(rule.value);
        } else {
            if (rule.id >= _compareList.length) {
                return false;
            }
            value = uint256(uint240(_compareList[rule.id])); // force lost precision
        }

        if (Op(rule.op) == Op.RET) {
            return uint256(value) > 0;
        }

        return _compare(value, comparedTo, Op(rule.op));
    }

    /// @notice Evaluates logical operations.
    /// @param _rule The rule containing the logical operation.
    /// @param _where The address of the target contract.
    /// @param _who The address (EOA or contract) for which the permissions are checked.
    /// @param _permissionId The permission identifier.
    /// @param _compareList A list of values used for comparison in evaluation.
    /// @return Returns `true` if the logic evaluates to true.
    function _evalLogic(
        Rule memory _rule,
        address _where,
        address _who,
        bytes32 _permissionId,
        uint256[] memory _compareList
    ) internal view virtual returns (bool) {
        if (Op(_rule.op) == Op.IF_ELSE) {
            (
                uint32 currentRuleIndex,
                uint32 ruleIndexOnSuccess,
                uint32 ruleIndexOnFailure
            ) = decodeRuleValue(uint256(_rule.value));
            bool result = _evalRule(currentRuleIndex, _who, _where, _permissionId, _compareList);

            return
                _evalRule(
                    result ? ruleIndexOnSuccess : ruleIndexOnFailure,
                    _where,
                    _who,
                    _permissionId,
                    _compareList
                );
        }

        uint32 param1;
        uint32 param2;

        (param1, param2, ) = decodeRuleValue(uint256(_rule.value));
        bool r1 = _evalRule(param1, _where, _who, _permissionId, _compareList);

        if (Op(_rule.op) == Op.NOT) {
            return !r1;
        }

        if (r1 && Op(_rule.op) == Op.OR) {
            return true;
        }

        if (!r1 && Op(_rule.op) == Op.AND) {
            return false;
        }

        bool r2 = _evalRule(param2, _where, _who, _permissionId, _compareList);

        if (Op(_rule.op) == Op.XOR) {
            return r1 != r2;
        }

        return r2; // both or and and depend on result of r2 after checks
    }

    /// @notice Checks an external condition.
    /// @param _condition The address of the external condition.
    /// @param _where The address of the target contract.
    /// @param _who The address (EOA or contract) for which the permissions are checked.
    /// @param _permissionId The permission identifier.
    /// @param _compareList A list of values used for comparison in evaluation.
    /// @return Returns `true` if the external condition is granted.
    function _checkCondition(
        IPermissionCondition _condition,
        address _where,
        address _who,
        bytes32 _permissionId,
        uint256[] memory _compareList
    ) internal view virtual returns (bool) {
        // a raw call is required so we can return false if the call reverts, rather than reverting
        bytes memory checkCalldata = abi.encodeWithSelector(
            _condition.isGranted.selector,
            _where,
            _who,
            _permissionId,
            abi.encode(_compareList)
        );

        bool ok;
        // solhint-disable-next-line no-inline-assembly
        assembly {
            // send all available gas; if the oracle eats up all the gas, we will eventually revert
            // note that we are currently guaranteed to still have some gas after the call from
            // EIP-150's 63/64 gas forward rule
            ok := staticcall(
                gas(),
                _condition,
                add(checkCalldata, 0x20),
                mload(checkCalldata),
                0,
                0
            )
        }

        if (!ok) {
            return false;
        }

        uint256 size;
        // solhint-disable-next-line no-inline-assembly
        assembly {
            size := returndatasize()
        }
        if (size != 32) {
            return false;
        }

        bool result;
        // solhint-disable-next-line no-inline-assembly
        assembly {
            let ptr := mload(0x40) // get next free memory ptr
            returndatacopy(ptr, 0, size) // copy return from above `staticcall`
            result := mload(ptr) // read data at ptr and set it to result
            mstore(ptr, 0) // set pointer memory to 0 so it still is the next free ptr
        }

        return result;
    }

    /// @notice Compares two values based on the specified operation.
    /// @param _a The first value to compare.
    /// @param _b The second value to compare.
    /// @param _op The operation to use for comparison.
    /// @return Returns `true` if the comparison holds true.
    function _compare(uint256 _a, uint256 _b, Op _op) internal pure returns (bool) {
        if (_op == Op.EQ) return _a == _b;
        if (_op == Op.NEQ) return _a != _b;
        if (_op == Op.GT) return _a > _b;
        if (_op == Op.LT) return _a < _b;
        if (_op == Op.GTE) return _a >= _b;
        if (_op == Op.LTE) return _a <= _b;
        return false;
    }

    /// @notice Encodes rule indices into a uint240 value.
    /// @param startingRuleIndex The index of the starting rule to evaluate.
    /// @param successRuleIndex The index of the rule to evaluate if the evaluation of `startingRuleIndex` was true.
    /// @param failureRuleIndex The index of the rule to evaluate if the evaluation of `startingRuleIndex` was false.
    /// @return The encoded value combining all three inputs.
    function encodeIfElse(
        uint256 startingRuleIndex,
        uint256 successRuleIndex,
        uint256 failureRuleIndex
    ) public pure returns (uint240) {
        return uint240(startingRuleIndex + (successRuleIndex << 32) + (failureRuleIndex << 64));
    }

    /// @notice Encodes two rule indexes into a uint240 value. Useful for logical operators such as `AND/OR/XOR` and others.
    /// @param ruleIndex1 The first index to evaluate.
    /// @param ruleIndex2 The second index to evaluate.
    function encodeLogicalOperator(
        uint256 ruleIndex1,
        uint256 ruleIndex2
    ) public pure returns (uint240) {
        return uint240(ruleIndex1 + (ruleIndex2 << 32));
    }

    /// @notice Decodes rule indices into three uint32.
    /// @param _x The value to decode.
    /// @return a The first 32-bit segment.
    /// @return b The second 32-bit segment.
    /// @return c The third 32-bit segment.
    function decodeRuleValue(uint256 _x) public pure returns (uint32 a, uint32 b, uint32 c) {
        a = uint32(_x);
        b = uint32(_x >> (8 * 4));
        c = uint32(_x >> (8 * 8));
    }

    /// @notice This empty reserved space is put in place to allow future versions to add new variables without shifting down storage in the inheritance chain (see [OpenZeppelin's guide about storage gaps](https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps)).
    uint256[49] private __gap;
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)

pragma solidity ^0.8.1;

/**
 * @dev Collection of functions related to the address type
 */
library Address {
    /**
     * @dev Returns true if `account` is a contract.
     *
     * [IMPORTANT]
     * ====
     * It is unsafe to assume that an address for which this function returns
     * false is an externally-owned account (EOA) and not a contract.
     *
     * Among others, `isContract` will return false for the following
     * types of addresses:
     *
     *  - an externally-owned account
     *  - a contract in construction
     *  - an address where a contract will be created
     *  - an address where a contract lived, but was destroyed
     *
     * Furthermore, `isContract` will also return true if the target contract within
     * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,
     * which only has an effect at the end of a transaction.
     * ====
     *
     * [IMPORTANT]
     * ====
     * You shouldn't rely on `isContract` to protect against flash loan attacks!
     *
     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
     * constructor.
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // This method relies on extcodesize/address.code.length, which returns 0
        // for contracts in construction, since the code is only stored at the end
        // of the constructor execution.

        return account.code.length > 0;
    }

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

        (bool success, ) = recipient.call{value: amount}("");
        require(success, "Address: unable to send value, recipient may have reverted");
    }

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

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
     * `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        return functionCallWithValue(target, data, 0, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but also transferring `value` wei to `target`.
     *
     * Requirements:
     *
     * - the calling contract must have an ETH balance of at least `value`.
     * - the called Solidity function must be `payable`.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
        return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
    }

    /**
     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
     * with `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value,
        string memory errorMessage
    ) internal returns (bytes memory) {
        require(address(this).balance >= value, "Address: insufficient balance for call");
        (bool success, bytes memory returndata) = target.call{value: value}(data);
        return verifyCallResultFromTarget(target, success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
        return functionStaticCall(target, data, "Address: low-level static call failed");
    }

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

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionDelegateCall(target, data, "Address: low-level delegate call failed");
    }

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

    /**
     * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
     * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
     *
     * _Available since v4.8._
     */
    function verifyCallResultFromTarget(
        address target,
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal view returns (bytes memory) {
        if (success) {
            if (returndata.length == 0) {
                // only check isContract if the call was successful and the return data is empty
                // otherwise we already know that it was a contract
                require(isContract(target), "Address: call to non-contract");
            }
            return returndata;
        } else {
            _revert(returndata, errorMessage);
        }
    }

    /**
     * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
     * revert reason or using the provided one.
     *
     * _Available since v4.3._
     */
    function verifyCallResult(
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal pure returns (bytes memory) {
        if (success) {
            return returndata;
        } else {
            _revert(returndata, errorMessage);
        }
    }

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

File 13 of 48 : IPermissionCondition.sol
// SPDX-License-Identifier: AGPL-3.0-or-later

pragma solidity ^0.8.8;

/// @title IPermissionCondition
/// @author Aragon X - 2021-2023
/// @notice An interface to be implemented to support custom permission logic.
/// @dev To attach a condition to a permission, the `grantWithCondition` function must be used and refer to the implementing contract's address with the `condition` argument.
/// @custom:security-contact [email protected]
interface IPermissionCondition {
    /// @notice Checks if a call is permitted.
    /// @param _where The address of the target contract.
    /// @param _who The address (EOA or contract) for which the permissions are checked.
    /// @param _permissionId The permission identifier.
    /// @param _data Optional data passed to the `PermissionCondition` implementation.
    /// @return isPermitted Returns true if the call is permitted.
    function isGranted(
        address _where,
        address _who,
        bytes32 _permissionId,
        bytes calldata _data
    ) external view returns (bool isPermitted);
}

File 14 of 48 : DaoAuthorizableUpgradeable.sol
// SPDX-License-Identifier: AGPL-3.0-or-later

pragma solidity ^0.8.8;

import {ContextUpgradeable} from "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol";

import {IDAO} from "../../dao/IDAO.sol";
import {_auth} from "./auth.sol";

/// @title DaoAuthorizableUpgradeable
/// @author Aragon X - 2022-2023
/// @notice An abstract contract providing a meta-transaction compatible modifier for upgradeable or cloneable contracts to authorize function calls through an associated DAO.
/// @dev Make sure to call `__DaoAuthorizableUpgradeable_init` during initialization of the inheriting contract.
/// @custom:security-contact [email protected]
abstract contract DaoAuthorizableUpgradeable is ContextUpgradeable {
    /// @notice The associated DAO managing the permissions of inheriting contracts.
    IDAO private dao_;

    /// @notice Initializes the contract by setting the associated DAO.
    /// @param _dao The associated DAO address.
    // solhint-disable-next-line func-name-mixedcase
    function __DaoAuthorizableUpgradeable_init(IDAO _dao) internal onlyInitializing {
        dao_ = _dao;
    }

    /// @notice Returns the DAO contract.
    /// @return The DAO contract.
    function dao() public view returns (IDAO) {
        return dao_;
    }

    /// @notice A modifier to make functions on inheriting contracts authorized. Permissions to call the function are checked through the associated DAO's permission manager.
    /// @param _permissionId The permission identifier required to call the method this modifier is applied to.
    modifier auth(bytes32 _permissionId) {
        _auth(dao_, address(this), _msgSender(), _permissionId, _msgData());
        _;
    }

    /// @notice This empty reserved space is put in place to allow future versions to add new variables without shifting down storage in the inheritance chain (see [OpenZeppelin's guide about storage gaps](https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps)).
    uint256[49] private __gap;
}

File 15 of 48 : Errors.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.18;

/// @title Errors
/// @author Aragon X - 2024
/// @notice Library containing all custom errors the plugin may revert with.
library Errors {
    // SPP

    /// @notice Thrown when a proposal doesn't exist.
    /// @param proposalId The ID of the proposal which doesn't exist.
    error NonexistentProposal(uint256 proposalId);

    /// @notice Thrown if the start date is less than current timestamp.
    error StartDateInvalid(uint64);

    /// @notice Thrown if stage durations are invalid.
    error StageDurationsInvalid();

    /// @notice Thrown if `_proposalParams`'s length exceeds `type(uint16).max`.
    error Uint16MaxSizeExceeded();

    /// @notice Thrown if the thresholds are invalid.
    error StageThresholdsInvalid();

    /// @notice Thrown if the proposal is not cancelable in the `stageId`.
    error ProposalCanNotBeCancelled(uint256 proposalId, uint16 stageId);

    /// @notice Thrown if the proposal is not editable.
    /// @dev This can happen in 2 cases:
    ///      either Proposal can not yet be advanced or,
    ///      The stage has `editable:false` in the configuration.
    /// @param proposalId The id of the proposal.
    error ProposalCanNotBeEdited(uint256 proposalId, uint16 stageId);

    /// @notice Thrown if the proposal has already been cancelled.
    /// @param proposalId The id of the proposal.
    error ProposalAlreadyCancelled(uint256 proposalId);

    /// @notice Thrown if the proposal's state doesn't match the allowed state.
    /// @param proposalId The id of the proposal.
    /// @param currentState The current state of the proposal.
    /// @param allowedStates The allowed state that must match the `currentState`, otherwise the error is thrown.
    error UnexpectedProposalState(uint256 proposalId, uint8 currentState, bytes32 allowedStates);

    /// @notice Thrown if a body address is duplicated in the same stage.
    /// @param stageId The stage id that contains the duplicated body address.
    /// @param body The address that is duplicated in `stageId`.
    error DuplicateBodyAddress(uint256 stageId, address body);

    /// @notice Thrown if the body result type is not set.
    /// @param body The address of the body.
    error BodyResultTypeNotSet(address body);

    /// @notice Thrown if the proposal with same actions and metadata already exists.
    /// @param proposalId The id of the proposal.
    error ProposalAlreadyExists(uint256 proposalId);

    /// @notice Thrown if first stage's params don't match the count of the current first stage's bodies' count.
    error InvalidCustomParamsForFirstStage();

    /// @notice Thrown when the stages length is zero.
    error StageCountZero();

    /// @notice Thrown when the body tries to submit report for the stage id that has not yet become active.
    /// @param currentStageId The stage id that proposal is currently at.
    /// @param reportedStageId The stage id for which the report is being submitted.
    error StageIdInvalid(uint64 currentStageId, uint64 reportedStageId);

    /// @notice Thrown when the metadata is empty.
    error EmptyMetadata();

    error InsufficientGas();

    // Trusted Forwarder
    /// @notice Thrown when trusted forwarder can not execute the actions.
    error IncorrectActionCount();

    /// @notice Thrown when a body doesn't support IProposal interface.
    error InterfaceNotSupported();

    /// @notice Thrown if the proposal execution is forbidden.
    /// @param proposalId The ID of the proposal.
    error ProposalExecutionForbidden(uint256 proposalId);

    /// @notice Thrown if the proposal advance is forbidden.
    /// @param proposalId The ID of the proposal.
    error ProposalAdvanceForbidden(uint256 proposalId);
}

// SPDX-License-Identifier: AGPL-3.0-or-later

pragma solidity ^0.8.8;

import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
import {IERC1822ProxiableUpgradeable} from "@openzeppelin/contracts-upgradeable/interfaces/draft-IERC1822Upgradeable.sol";
import {ERC165Upgradeable} from "@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol";
import {ERC165CheckerUpgradeable} from "@openzeppelin/contracts-upgradeable/utils/introspection/ERC165CheckerUpgradeable.sol";

import {IProtocolVersion} from "../utils/versioning/IProtocolVersion.sol";
import {ProtocolVersion} from "../utils/versioning/ProtocolVersion.sol";
import {DaoAuthorizableUpgradeable} from "../permission/auth/DaoAuthorizableUpgradeable.sol";
import {IPlugin} from "./IPlugin.sol";
import {IDAO} from "../dao/IDAO.sol";
import {IExecutor, Action} from "../executors/IExecutor.sol";

/// @title PluginUUPSUpgradeable
/// @author Aragon X - 2022-2024
/// @notice An abstract, upgradeable contract to inherit from when creating a plugin being deployed via the UUPS pattern (see [ERC-1822](https://eips.ethereum.org/EIPS/eip-1822)).
/// @custom:security-contact [email protected]
abstract contract PluginUUPSUpgradeable is
    IPlugin,
    ERC165Upgradeable,
    UUPSUpgradeable,
    DaoAuthorizableUpgradeable,
    ProtocolVersion
{
    using ERC165CheckerUpgradeable for address;

    // NOTE: When adding new state variables to the contract, the size of `_gap` has to be adapted below as well.

    /// @notice Stores the current target configuration, defining the target contract and operation type for a plugin.
    TargetConfig private currentTargetConfig;

    /// @notice Thrown when target is of type 'IDAO', but operation is `delegateCall`.
    /// @param targetConfig The target config to update it to.
    error InvalidTargetConfig(TargetConfig targetConfig);

    /// @notice Thrown when `delegatecall` fails.
    error DelegateCallFailed();

    /// @notice Thrown when initialize is called after it has already been executed.
    error AlreadyInitialized();

    /// @notice Emitted each time the TargetConfig is set.
    event TargetSet(TargetConfig newTargetConfig);

    /// @notice The ID of the permission required to call the `setTargetConfig` function.
    bytes32 public constant SET_TARGET_CONFIG_PERMISSION_ID =
        keccak256("SET_TARGET_CONFIG_PERMISSION");

    /// @notice The ID of the permission required to call the `_authorizeUpgrade` function.
    bytes32 public constant UPGRADE_PLUGIN_PERMISSION_ID = keccak256("UPGRADE_PLUGIN_PERMISSION");

    /// @notice Disables the initializers on the implementation contract to prevent it from being left uninitialized.
    /// @custom:oz-upgrades-unsafe-allow constructor
    constructor() {
        _disableInitializers();
    }

    /// @notice This ensures that the initialize function cannot be called during the upgrade process.
    modifier onlyCallAtInitialization() {
        if (_getInitializedVersion() != 0) {
            revert AlreadyInitialized();
        }

        _;
    }

    /// @inheritdoc IPlugin
    function pluginType() public pure override returns (PluginType) {
        return PluginType.UUPS;
    }

    /// @notice Returns the currently set target contract.
    /// @return TargetConfig The currently set target.
    function getCurrentTargetConfig() public view virtual returns (TargetConfig memory) {
        return currentTargetConfig;
    }

    /// @notice A convenient function to get current target config only if its target is not address(0), otherwise dao().
    /// @return TargetConfig The current target config if its target is not address(0), otherwise returns dao()."
    function getTargetConfig() public view virtual returns (TargetConfig memory) {
        TargetConfig memory targetConfig = currentTargetConfig;

        if (targetConfig.target == address(0)) {
            targetConfig = TargetConfig({target: address(dao()), operation: Operation.Call});
        }

        return targetConfig;
    }

    /// @notice Initializes the plugin by storing the associated DAO.
    /// @param _dao The DAO contract.
    // solhint-disable-next-line func-name-mixedcase
    function __PluginUUPSUpgradeable_init(IDAO _dao) internal virtual onlyInitializing {
        __DaoAuthorizableUpgradeable_init(_dao);
    }

    /// @dev Sets the target to a new target (`newTarget`).
    ///      The caller must have the `SET_TARGET_CONFIG_PERMISSION_ID` permission.
    /// @param _targetConfig The target Config containing the address and operation type.
    function setTargetConfig(
        TargetConfig calldata _targetConfig
    ) public auth(SET_TARGET_CONFIG_PERMISSION_ID) {
        _setTargetConfig(_targetConfig);
    }

    /// @notice Checks if an interface is supported by this or its parent contract.
    /// @param _interfaceId The ID of the interface.
    /// @return Returns `true` if the interface is supported.
    function supportsInterface(bytes4 _interfaceId) public view virtual override returns (bool) {
        return
            _interfaceId == type(IPlugin).interfaceId ||
            _interfaceId == type(IProtocolVersion).interfaceId ||
            _interfaceId == type(IERC1822ProxiableUpgradeable).interfaceId ||
            _interfaceId ==
            this.setTargetConfig.selector ^
                this.getTargetConfig.selector ^
                this.getCurrentTargetConfig.selector ||
            super.supportsInterface(_interfaceId);
    }

    /// @notice Returns the address of the implementation contract in the [proxy storage slot](https://eips.ethereum.org/EIPS/eip-1967) slot the [UUPS proxy](https://eips.ethereum.org/EIPS/eip-1822) is pointing to.
    /// @return The address of the implementation contract.
    function implementation() public view returns (address) {
        return _getImplementation();
    }

    /// @notice Sets the target to a new target (`newTarget`).
    /// @param _targetConfig The target Config containing the address and operation type.
    function _setTargetConfig(TargetConfig memory _targetConfig) internal virtual {
        // safety check to avoid setting dao as `target` with `delegatecall` operation
        // as this would not work and cause the plugin to be bricked.
        if (
            _targetConfig.target.supportsInterface(type(IDAO).interfaceId) &&
            _targetConfig.operation == Operation.DelegateCall
        ) {
            revert InvalidTargetConfig(_targetConfig);
        }

        currentTargetConfig = _targetConfig;

        emit TargetSet(_targetConfig);
    }

    /// @notice Forwards the actions to the currently set `target` for the execution.
    /// @dev If target is not set, passes actions to the dao.
    /// @param _callId Identifier for this execution.
    /// @param _actions actions that will be eventually called.
    /// @param _allowFailureMap Bitmap-encoded number.
    /// @return execResults address of the implementation contract.
    /// @return failureMap address of the implementation contract.
    function _execute(
        bytes32 _callId,
        Action[] memory _actions,
        uint256 _allowFailureMap
    ) internal virtual returns (bytes[] memory execResults, uint256 failureMap) {
        TargetConfig memory targetConfig = getTargetConfig();

        return
            _execute(
                targetConfig.target,
                _callId,
                _actions,
                _allowFailureMap,
                targetConfig.operation
            );
    }

    /// @notice Forwards the actions to the `target` for the execution.
    /// @param _target The address of the target contract.
    /// @param _callId Identifier for this execution.
    /// @param _actions actions that will be eventually called.
    /// @param _allowFailureMap A bitmap allowing the execution to succeed, even if individual actions might revert.
    ///     If the bit at index `i` is 1, the execution succeeds even if the `i`th action reverts.
    ///     A failure map value of 0 requires every action to not revert.
    /// @param _op The type of operation (`Call` or `DelegateCall`) to be used for the execution.
    /// @return execResults address of the implementation contract.
    /// @return failureMap address of the implementation contract.
    function _execute(
        address _target,
        bytes32 _callId,
        Action[] memory _actions,
        uint256 _allowFailureMap,
        Operation _op
    ) internal virtual returns (bytes[] memory execResults, uint256 failureMap) {
        if (_op == Operation.DelegateCall) {
            bool success;
            bytes memory data;

            // solhint-disable-next-line avoid-low-level-calls
            (success, data) = _target.delegatecall(
                abi.encodeCall(IExecutor.execute, (_callId, _actions, _allowFailureMap))
            );

            if (!success) {
                if (data.length > 0) {
                    // solhint-disable-next-line no-inline-assembly
                    assembly {
                        let returndata_size := mload(data)
                        revert(add(32, data), returndata_size)
                    }
                } else {
                    revert DelegateCallFailed();
                }
            }
            (execResults, failureMap) = abi.decode(data, (bytes[], uint256));
        } else {
            (execResults, failureMap) = IExecutor(_target).execute(
                _callId,
                _actions,
                _allowFailureMap
            );
        }
    }

    /// @notice Internal method authorizing the upgrade of the contract via the [upgradeability mechanism for UUPS proxies](https://docs.openzeppelin.com/contracts/4.x/api/proxy#UUPSUpgradeable) (see [ERC-1822](https://eips.ethereum.org/EIPS/eip-1822)).
    /// @dev The caller must have the `UPGRADE_PLUGIN_PERMISSION_ID` permission.
    function _authorizeUpgrade(
        address
    )
        internal
        virtual
        override
        auth(UPGRADE_PLUGIN_PERMISSION_ID)
    // solhint-disable-next-line no-empty-blocks
    {

    }

    /// @notice This empty reserved space is put in place to allow future versions to add new variables without shifting down storage in the inheritance chain (see [OpenZeppelin's guide about storage gaps](https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps)).
    uint256[49] private __gap;
}

File 17 of 48 : IExecutor.sol
// SPDX-License-Identifier: AGPL-3.0-or-later

pragma solidity ^0.8.8;

/// @notice The action struct to be consumed by the DAO's `execute` function resulting in an external call.
/// @param to The address to call.
/// @param value The native token value to be sent with the call.
/// @param data The bytes-encoded function selector and calldata for the call.
struct Action {
    address to;
    uint256 value;
    bytes data;
}

/// @title IExecutor
/// @author Aragon X - 2024
/// @notice The interface required for Executors within the Aragon App DAO framework.
/// @custom:security-contact [email protected]
interface IExecutor {
    /// @notice Emitted when a proposal is executed.
    /// @dev The value of `callId` is defined by the component/contract calling the execute function.
    ///      A `Plugin` implementation can use it, for example, as a nonce.
    /// @param actor The address of the caller.
    /// @param callId The ID of the call.
    /// @param actions The array of actions executed.
    /// @param allowFailureMap The allow failure map encoding which actions are allowed to fail.
    /// @param failureMap The failure map encoding which actions have failed.
    /// @param execResults The array with the results of the executed actions.
    event Executed(
        address indexed actor,
        bytes32 callId,
        Action[] actions,
        uint256 allowFailureMap,
        uint256 failureMap,
        bytes[] execResults
    );

    /// @notice Executes a list of actions. If a zero allow-failure map is provided, a failing action reverts the entire execution. If a non-zero allow-failure map is provided, allowed actions can fail without the entire call being reverted.
    /// @param _callId The ID of the call. The definition of the value of `callId` is up to the calling contract and can be used, e.g., as a nonce.
    /// @param _actions The array of actions.
    /// @param _allowFailureMap A bitmap allowing execution to succeed, even if individual actions might revert. If the bit at index `i` is 1, the execution succeeds even if the `i`th action reverts. A failure map value of 0 requires every action to not revert.
    /// @return The array of results obtained from the executed actions in `bytes`.
    /// @return The resulting failure map containing the actions have actually failed.
    function execute(
        bytes32 _callId,
        Action[] memory _actions,
        uint256 _allowFailureMap
    ) external returns (bytes[] memory, uint256);
}

// SPDX-License-Identifier: AGPL-3.0-or-later

pragma solidity ^0.8.8;

import {Action} from "../../../executors/IExecutor.sol";

/// @title IProposal
/// @author Aragon X - 2022-2024
/// @notice An interface to be implemented by DAO plugins that create and execute proposals.
/// @custom:security-contact [email protected]
interface IProposal {
    /// @notice Emitted when a proposal is created.
    /// @param proposalId The ID of the proposal.
    /// @param creator  The creator of the proposal.
    /// @param startDate The start date of the proposal in seconds.
    /// @param endDate The end date of the proposal in seconds.
    /// @param metadata The metadata of the proposal.
    /// @param actions The actions that will be executed if the proposal passes.
    /// @param allowFailureMap A bitmap allowing the proposal to succeed, even if individual actions might revert.
    ///     If the bit at index `i` is 1, the proposal succeeds even if the `i`th action reverts.
    ///     A failure map value of 0 requires every action to not revert.
    event ProposalCreated(
        uint256 indexed proposalId,
        address indexed creator,
        uint64 startDate,
        uint64 endDate,
        bytes metadata,
        Action[] actions,
        uint256 allowFailureMap
    );

    /// @notice Emitted when a proposal is executed.
    /// @param proposalId The ID of the proposal.
    event ProposalExecuted(uint256 indexed proposalId);

    /// @notice Creates a new proposal.
    /// @param _metadata The metadata of the proposal.
    /// @param _actions The actions that will be executed after the proposal passes.
    /// @param _startDate The start date of the proposal.
    /// @param _endDate The end date of the proposal.
    /// @param _data The additional abi-encoded data to include more necessary fields.
    /// @return proposalId The id of the proposal.
    function createProposal(
        bytes memory _metadata,
        Action[] memory _actions,
        uint64 _startDate,
        uint64 _endDate,
        bytes memory _data
    ) external returns (uint256 proposalId);

    /// @notice Whether proposal succeeded or not.
    /// @dev Note that this must not include time window checks and only make a decision based on the thresholds.
    /// @param _proposalId The id of the proposal.
    /// @return Returns if proposal has been succeeded or not without including time window checks.
    function hasSucceeded(uint256 _proposalId) external view returns (bool);

    /// @notice Executes a proposal.
    /// @param _proposalId The ID of the proposal to be executed.
    function execute(uint256 _proposalId) external;

    /// @notice Checks if a proposal can be executed.
    /// @param _proposalId The ID of the proposal to be checked.
    /// @return True if the proposal can be executed, false otherwise.
    function canExecute(uint256 _proposalId) external view returns (bool);

    /// @notice The human-readable abi format for extra params included in `data` of `createProposal`.
    /// @dev Used for UI to easily detect what extra params the contract expects.
    /// @return ABI of params in `data` of `createProposal`.
    function customProposalParamsABI() external view returns (string memory);

    /// @notice Returns the proposal count which determines the next proposal ID.
    /// @dev This function is deprecated but remains in the interface for backward compatibility.
    ///      It now reverts to prevent ambiguity.
    /// @return The proposal count.
    function proposalCount() external view returns (uint256);
}

// SPDX-License-Identifier: AGPL-3.0-or-later

pragma solidity ^0.8.8;

import {ERC165Upgradeable} from "@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol";

import {DaoAuthorizableUpgradeable} from "../../permission/auth/DaoAuthorizableUpgradeable.sol";

/// @title MetadataExtensionUpgradeable
/// @author Aragon X - 2024
/// @notice An abstract, upgradeable contract for managing and retrieving metadata associated with a plugin.
/// @dev Due to the requirements that already existing upgradeable plugins need to start inheritting from this,
///      we're required to use hardcoded/specific slots for storage instead of sequential slots with gaps.
/// @custom:security-contact [email protected]
abstract contract MetadataExtensionUpgradeable is ERC165Upgradeable, DaoAuthorizableUpgradeable {
    /// @notice The ID of the permission required to call the `setMetadata` function.
    bytes32 public constant SET_METADATA_PERMISSION_ID = keccak256("SET_METADATA_PERMISSION");

    // keccak256(abi.encode(uint256(keccak256("osx-commons.storage.MetadataExtension")) - 1)) & ~bytes32(uint256(0xff))
    // solhint-disable-next-line  const-name-snakecase
    bytes32 private constant MetadataExtensionStorageLocation =
        0x47ff9796f72d439c6e5c30a24b9fad985a00c85a9f2258074c400a94f8746b00;

    /// @notice Emitted when metadata is updated.
    event MetadataSet(bytes metadata);

    struct MetadataExtensionStorage {
        bytes metadata;
    }

    function _getMetadataExtensionStorage()
        private
        pure
        returns (MetadataExtensionStorage storage $)
    {
        // solhint-disable-next-line no-inline-assembly
        assembly {
            $.slot := MetadataExtensionStorageLocation
        }
    }

    /// @notice Checks if this or the parent contract supports an interface by its ID.
    /// @param _interfaceId The ID of the interface.
    /// @return Returns `true` if the interface is supported.
    function supportsInterface(bytes4 _interfaceId) public view virtual override returns (bool) {
        return
            _interfaceId == this.setMetadata.selector ^ this.getMetadata.selector ||
            super.supportsInterface(_interfaceId);
    }

    /// @notice Allows to update only the metadata.
    /// @param _metadata The utf8 bytes of a content addressing cid that stores plugin's information.
    function setMetadata(bytes calldata _metadata) public virtual auth(SET_METADATA_PERMISSION_ID) {
        _setMetadata(_metadata);
    }

    /// @notice Returns the metadata currently applied.
    /// @return The The utf8 bytes of a content addressing cid.
    function getMetadata() public view returns (bytes memory) {
        MetadataExtensionStorage storage $ = _getMetadataExtensionStorage();
        return $.metadata;
    }

    /// @notice Internal function to update metadata.
    /// @param _metadata The utf8 bytes of a content addressing cid that stores contract's information.
    function _setMetadata(bytes memory _metadata) internal virtual {
        MetadataExtensionStorage storage $ = _getMetadataExtensionStorage();
        $.metadata = _metadata;

        emit MetadataSet(_metadata);
    }
}

// SPDX-License-Identifier: AGPL-3.0-or-later

pragma solidity ^0.8.8;

import {CountersUpgradeable} from "@openzeppelin/contracts-upgradeable/utils/CountersUpgradeable.sol";
import {ERC165Upgradeable} from "@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol";

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

/// @title ProposalUpgradeable
/// @author Aragon X - 2022-2024
/// @notice An abstract contract containing the traits and internal functionality to create and execute proposals
///         that can be inherited by upgradeable DAO plugins.
/// @custom:security-contact [email protected]
abstract contract ProposalUpgradeable is IProposal, ERC165Upgradeable {
    using CountersUpgradeable for CountersUpgradeable.Counter;

    error FunctionDeprecated();

    /// @notice The incremental ID for proposals and executions.
    CountersUpgradeable.Counter private proposalCounter;

    /// @inheritdoc IProposal
    function proposalCount() public view virtual override returns (uint256) {
        revert FunctionDeprecated();
    }

    /// @notice Creates a proposal Id.
    /// @dev Uses block number and chain id to ensure more probability of uniqueness.
    /// @param _salt The extra salt to help with uniqueness.
    /// @return The id of the proposal.
    function _createProposalId(bytes32 _salt) internal view virtual returns (uint256) {
        return uint256(keccak256(abi.encode(block.chainid, block.number, address(this), _salt)));
    }

    /// @notice Checks if this or the parent contract supports an interface by its ID.
    /// @dev In addition to the current interfaceId, also support previous version of the interfaceId
    ///      that did not include the following functions:
    ///      `createProposal`, `hasSucceeded`, `execute`, `canExecute`, `customProposalParamsABI`.
    /// @param _interfaceId The ID of the interface.
    /// @return Returns `true` if the interface is supported.
    function supportsInterface(bytes4 _interfaceId) public view virtual override returns (bool) {
        return
            _interfaceId ==
            type(IProposal).interfaceId ^
                IProposal.createProposal.selector ^
                IProposal.hasSucceeded.selector ^
                IProposal.execute.selector ^
                IProposal.canExecute.selector ^
                IProposal.customProposalParamsABI.selector ||
            _interfaceId == type(IProposal).interfaceId ||
            super.supportsInterface(_interfaceId);
    }

    /// @notice This empty reserved space is put in place to allow future versions to add new variables
    ///         without shifting down storage in the inheritance chain
    ///         (see [OpenZeppelin's guide about storage gaps](https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps)).
    uint256[49] private __gap;
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/introspection/ERC165Checker.sol)

pragma solidity ^0.8.0;

import "./IERC165.sol";

/**
 * @dev Library used to query support of an interface declared via {IERC165}.
 *
 * Note that these functions return the actual result of the query: they do not
 * `revert` if an interface is not supported. It is up to the caller to decide
 * what to do in these cases.
 */
library ERC165Checker {
    // As per the EIP-165 spec, no interface should ever match 0xffffffff
    bytes4 private constant _INTERFACE_ID_INVALID = 0xffffffff;

    /**
     * @dev Returns true if `account` supports the {IERC165} interface.
     */
    function supportsERC165(address account) internal view returns (bool) {
        // Any contract that implements ERC165 must explicitly indicate support of
        // InterfaceId_ERC165 and explicitly indicate non-support of InterfaceId_Invalid
        return
            supportsERC165InterfaceUnchecked(account, type(IERC165).interfaceId) &&
            !supportsERC165InterfaceUnchecked(account, _INTERFACE_ID_INVALID);
    }

    /**
     * @dev Returns true if `account` supports the interface defined by
     * `interfaceId`. Support for {IERC165} itself is queried automatically.
     *
     * See {IERC165-supportsInterface}.
     */
    function supportsInterface(address account, bytes4 interfaceId) internal view returns (bool) {
        // query support of both ERC165 as per the spec and support of _interfaceId
        return supportsERC165(account) && supportsERC165InterfaceUnchecked(account, interfaceId);
    }

    /**
     * @dev Returns a boolean array where each value corresponds to the
     * interfaces passed in and whether they're supported or not. This allows
     * you to batch check interfaces for a contract where your expectation
     * is that some interfaces may not be supported.
     *
     * See {IERC165-supportsInterface}.
     *
     * _Available since v3.4._
     */
    function getSupportedInterfaces(
        address account,
        bytes4[] memory interfaceIds
    ) internal view returns (bool[] memory) {
        // an array of booleans corresponding to interfaceIds and whether they're supported or not
        bool[] memory interfaceIdsSupported = new bool[](interfaceIds.length);

        // query support of ERC165 itself
        if (supportsERC165(account)) {
            // query support of each interface in interfaceIds
            for (uint256 i = 0; i < interfaceIds.length; i++) {
                interfaceIdsSupported[i] = supportsERC165InterfaceUnchecked(account, interfaceIds[i]);
            }
        }

        return interfaceIdsSupported;
    }

    /**
     * @dev Returns true if `account` supports all the interfaces defined in
     * `interfaceIds`. Support for {IERC165} itself is queried automatically.
     *
     * Batch-querying can lead to gas savings by skipping repeated checks for
     * {IERC165} support.
     *
     * See {IERC165-supportsInterface}.
     */
    function supportsAllInterfaces(address account, bytes4[] memory interfaceIds) internal view returns (bool) {
        // query support of ERC165 itself
        if (!supportsERC165(account)) {
            return false;
        }

        // query support of each interface in interfaceIds
        for (uint256 i = 0; i < interfaceIds.length; i++) {
            if (!supportsERC165InterfaceUnchecked(account, interfaceIds[i])) {
                return false;
            }
        }

        // all interfaces supported
        return true;
    }

    /**
     * @notice Query if a contract implements an interface, does not check ERC165 support
     * @param account The address of the contract to query for support of an interface
     * @param interfaceId The interface identifier, as specified in ERC-165
     * @return true if the contract at account indicates support of the interface with
     * identifier interfaceId, false otherwise
     * @dev Assumes that account contains a contract that supports ERC165, otherwise
     * the behavior of this method is undefined. This precondition can be checked
     * with {supportsERC165}.
     *
     * Some precompiled contracts will falsely indicate support for a given interface, so caution
     * should be exercised when using this function.
     *
     * Interface identification is specified in ERC-165.
     */
    function supportsERC165InterfaceUnchecked(address account, bytes4 interfaceId) internal view returns (bool) {
        // prepare call
        bytes memory encodedParams = abi.encodeWithSelector(IERC165.supportsInterface.selector, interfaceId);

        // perform static call
        bool success;
        uint256 returnSize;
        uint256 returnValue;
        assembly {
            success := staticcall(30000, account, add(encodedParams, 0x20), mload(encodedParams), 0x00, 0x20)
            returnSize := returndatasize()
            returnValue := mload(0x00)
        }

        return success && returnSize >= 0x20 && returnValue > 0;
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)

pragma solidity ^0.8.0;

import "./IERC165.sol";

/**
 * @dev Implementation of the {IERC165} interface.
 *
 * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check
 * for the additional interface id that will be supported. For example:
 *
 * ```solidity
 * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
 *     return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
 * }
 * ```
 *
 * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.
 */
abstract contract ERC165 is IERC165 {
    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
        return interfaceId == type(IERC165).interfaceId;
    }
}

File 23 of 48 : IProtocolVersion.sol
// SPDX-License-Identifier: AGPL-3.0-or-later

pragma solidity ^0.8.8;

/// @title IProtocolVersion
/// @author Aragon X - 2022-2023
/// @notice An interface defining the semantic Aragon OSx protocol version number.
/// @custom:security-contact [email protected]
interface IProtocolVersion {
    /// @notice Returns the semantic Aragon OSx protocol version number that the implementing contract is associated with.
    /// @return _version Returns the semantic Aragon OSx protocol version number.
    /// @dev This version number is not to be confused with the `release` and `build` numbers found in the `Version.Tag` struct inside the `PluginRepo` contract being used to version plugin setup and associated plugin implementation contracts.
    function protocolVersion() external view returns (uint8[3] memory _version);
}

File 24 of 48 : ProtocolVersion.sol
// SPDX-License-Identifier: AGPL-3.0-or-later

pragma solidity ^0.8.8;

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

/// @title ProtocolVersion
/// @author Aragon X - 2023
/// @notice An abstract, stateless, non-upgradeable contract providing the current Aragon OSx protocol version number.
/// @dev Do not add any new variables to this contract that would shift down storage in the inheritance chain.
/// @custom:security-contact [email protected]
abstract contract ProtocolVersion is IProtocolVersion {
    // IMPORTANT: Do not add any storage variable, see the above notice.

    /// @inheritdoc IProtocolVersion
    function protocolVersion() public pure returns (uint8[3] memory) {
        return [1, 4, 0];
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (proxy/ERC1967/ERC1967Proxy.sol)

pragma solidity ^0.8.0;

import "../Proxy.sol";
import "./ERC1967Upgrade.sol";

/**
 * @dev This contract implements an upgradeable proxy. It is upgradeable because calls are delegated to an
 * implementation address that can be changed. This address is stored in storage in the location specified by
 * https://eips.ethereum.org/EIPS/eip-1967[EIP1967], so that it doesn't conflict with the storage layout of the
 * implementation behind the proxy.
 */
contract ERC1967Proxy is Proxy, ERC1967Upgrade {
    /**
     * @dev Initializes the upgradeable proxy with an initial implementation specified by `_logic`.
     *
     * If `_data` is nonempty, it's used as data in a delegate call to `_logic`. This will typically be an encoded
     * function call, and allows initializing the storage of the proxy like a Solidity constructor.
     */
    constructor(address _logic, bytes memory _data) payable {
        _upgradeToAndCall(_logic, _data, false);
    }

    /**
     * @dev Returns the current implementation address.
     */
    function _implementation() internal view virtual override returns (address impl) {
        return ERC1967Upgrade._getImplementation();
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (proxy/Clones.sol)

pragma solidity ^0.8.0;

/**
 * @dev https://eips.ethereum.org/EIPS/eip-1167[EIP 1167] is a standard for
 * deploying minimal proxy contracts, also known as "clones".
 *
 * > To simply and cheaply clone contract functionality in an immutable way, this standard specifies
 * > a minimal bytecode implementation that delegates all calls to a known, fixed address.
 *
 * The library includes functions to deploy a proxy using either `create` (traditional deployment) or `create2`
 * (salted deterministic deployment). It also includes functions to predict the addresses of clones deployed using the
 * deterministic method.
 *
 * _Available since v3.4._
 */
library Clones {
    /**
     * @dev Deploys and returns the address of a clone that mimics the behaviour of `implementation`.
     *
     * This function uses the create opcode, which should never revert.
     */
    function clone(address implementation) internal returns (address instance) {
        /// @solidity memory-safe-assembly
        assembly {
            // Cleans the upper 96 bits of the `implementation` word, then packs the first 3 bytes
            // of the `implementation` address with the bytecode before the address.
            mstore(0x00, or(shr(0xe8, shl(0x60, implementation)), 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000))
            // Packs the remaining 17 bytes of `implementation` with the bytecode after the address.
            mstore(0x20, or(shl(0x78, implementation), 0x5af43d82803e903d91602b57fd5bf3))
            instance := create(0, 0x09, 0x37)
        }
        require(instance != address(0), "ERC1167: create failed");
    }

    /**
     * @dev Deploys and returns the address of a clone that mimics the behaviour of `implementation`.
     *
     * This function uses the create2 opcode and a `salt` to deterministically deploy
     * the clone. Using the same `implementation` and `salt` multiple time will revert, since
     * the clones cannot be deployed twice at the same address.
     */
    function cloneDeterministic(address implementation, bytes32 salt) internal returns (address instance) {
        /// @solidity memory-safe-assembly
        assembly {
            // Cleans the upper 96 bits of the `implementation` word, then packs the first 3 bytes
            // of the `implementation` address with the bytecode before the address.
            mstore(0x00, or(shr(0xe8, shl(0x60, implementation)), 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000))
            // Packs the remaining 17 bytes of `implementation` with the bytecode after the address.
            mstore(0x20, or(shl(0x78, implementation), 0x5af43d82803e903d91602b57fd5bf3))
            instance := create2(0, 0x09, 0x37, salt)
        }
        require(instance != address(0), "ERC1167: create2 failed");
    }

    /**
     * @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}.
     */
    function predictDeterministicAddress(
        address implementation,
        bytes32 salt,
        address deployer
    ) internal pure returns (address predicted) {
        /// @solidity memory-safe-assembly
        assembly {
            let ptr := mload(0x40)
            mstore(add(ptr, 0x38), deployer)
            mstore(add(ptr, 0x24), 0x5af43d82803e903d91602b57fd5bf3ff)
            mstore(add(ptr, 0x14), implementation)
            mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73)
            mstore(add(ptr, 0x58), salt)
            mstore(add(ptr, 0x78), keccak256(add(ptr, 0x0c), 0x37))
            predicted := keccak256(add(ptr, 0x43), 0x55)
        }
    }

    /**
     * @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}.
     */
    function predictDeterministicAddress(
        address implementation,
        bytes32 salt
    ) internal view returns (address predicted) {
        return predictDeterministicAddress(implementation, salt, address(this));
    }
}

File 27 of 48 : PermissionConditionUpgradeable.sol
// SPDX-License-Identifier: AGPL-3.0-or-later

pragma solidity ^0.8.8;

import {ERC165Upgradeable} from "@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol";

import {IProtocolVersion} from "../../utils/versioning/IProtocolVersion.sol";
import {ProtocolVersion} from "../../utils/versioning/ProtocolVersion.sol";
import {IPermissionCondition} from "./IPermissionCondition.sol";

/// @title PermissionConditionUpgradeable
/// @author Aragon X - 2023
/// @notice An abstract contract for upgradeable or cloneable contracts to inherit from and to support customary permissions depending on arbitrary on-chain state.
/// @custom:security-contact [email protected]
abstract contract PermissionConditionUpgradeable is
    ERC165Upgradeable,
    IPermissionCondition,
    ProtocolVersion
{
    /// @notice Checks if an interface is supported by this or its parent contract.
    /// @param _interfaceId The ID of the interface.
    /// @return Returns `true` if the interface is supported.
    function supportsInterface(bytes4 _interfaceId) public view virtual override returns (bool) {
        return
            _interfaceId == type(IPermissionCondition).interfaceId ||
            _interfaceId == type(IProtocolVersion).interfaceId ||
            super.supportsInterface(_interfaceId);
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.4) (utils/Context.sol)

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

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

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

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

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

    /**
     * @dev This empty reserved space is put in place to allow future versions to add new
     * variables without shifting down storage in the inheritance chain.
     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
     */
    uint256[50] private __gap;
}

File 29 of 48 : auth.sol
// SPDX-License-Identifier: AGPL-3.0-or-later

pragma solidity ^0.8.8;

import {IDAO} from "../../dao/IDAO.sol";

/// @title DAO Authorization Utilities
/// @author Aragon X - 2022-2024
/// @notice Provides utility functions for verifying if a caller has specific permissions in an associated DAO.
/// @custom:security-contact [email protected]

/// @notice Thrown if a call is unauthorized in the associated DAO.
/// @param dao The associated DAO.
/// @param where The context in which the authorization reverted.
/// @param who The address (EOA or contract) missing the permission.
/// @param permissionId The permission identifier.
error DaoUnauthorized(address dao, address where, address who, bytes32 permissionId);

/// @notice A free function checking if a caller is granted permissions on a target contract via a permission identifier that redirects the approval to a `PermissionCondition` if this was specified in the setup.
/// @param _where The address of the target contract for which `who` receives permission.
/// @param _who The address (EOA or contract) owning the permission.
/// @param _permissionId The permission identifier.
/// @param _data The optional data passed to the `PermissionCondition` registered.
function _auth(
    IDAO _dao,
    address _where,
    address _who,
    bytes32 _permissionId,
    bytes calldata _data
) view {
    if (!_dao.hasPermission(_where, _who, _permissionId, _data))
        revert DaoUnauthorized({
            dao: address(_dao),
            where: _where,
            who: _who,
            permissionId: _permissionId
        });
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/UUPSUpgradeable.sol)

pragma solidity ^0.8.0;

import "../../interfaces/draft-IERC1822Upgradeable.sol";
import "../ERC1967/ERC1967UpgradeUpgradeable.sol";
import {Initializable} from "./Initializable.sol";

/**
 * @dev An upgradeability mechanism designed for UUPS proxies. The functions included here can perform an upgrade of an
 * {ERC1967Proxy}, when this contract is set as the implementation behind such a proxy.
 *
 * A security mechanism ensures that an upgrade does not turn off upgradeability accidentally, although this risk is
 * reinstated if the upgrade retains upgradeability but removes the security mechanism, e.g. by replacing
 * `UUPSUpgradeable` with a custom implementation of upgrades.
 *
 * The {_authorizeUpgrade} function must be overridden to include access restriction to the upgrade mechanism.
 *
 * _Available since v4.1._
 */
abstract contract UUPSUpgradeable is Initializable, IERC1822ProxiableUpgradeable, ERC1967UpgradeUpgradeable {
    /// @custom:oz-upgrades-unsafe-allow state-variable-immutable state-variable-assignment
    address private immutable __self = address(this);

    /**
     * @dev Check that the execution is being performed through a delegatecall call and that the execution context is
     * a proxy contract with an implementation (as defined in ERC1967) pointing to self. This should only be the case
     * for UUPS and transparent proxies that are using the current contract as their implementation. Execution of a
     * function through ERC1167 minimal proxies (clones) would not normally pass this test, but is not guaranteed to
     * fail.
     */
    modifier onlyProxy() {
        require(address(this) != __self, "Function must be called through delegatecall");
        require(_getImplementation() == __self, "Function must be called through active proxy");
        _;
    }

    /**
     * @dev Check that the execution is not being performed through a delegate call. This allows a function to be
     * callable on the implementing contract but not through proxies.
     */
    modifier notDelegated() {
        require(address(this) == __self, "UUPSUpgradeable: must not be called through delegatecall");
        _;
    }

    function __UUPSUpgradeable_init() internal onlyInitializing {
    }

    function __UUPSUpgradeable_init_unchained() internal onlyInitializing {
    }
    /**
     * @dev Implementation of the ERC1822 {proxiableUUID} function. This returns the storage slot used by the
     * implementation. It is used to validate the implementation's compatibility when performing an upgrade.
     *
     * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks
     * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this
     * function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier.
     */
    function proxiableUUID() external view virtual override notDelegated returns (bytes32) {
        return _IMPLEMENTATION_SLOT;
    }

    /**
     * @dev Upgrade the implementation of the proxy to `newImplementation`.
     *
     * Calls {_authorizeUpgrade}.
     *
     * Emits an {Upgraded} event.
     *
     * @custom:oz-upgrades-unsafe-allow-reachable delegatecall
     */
    function upgradeTo(address newImplementation) public virtual onlyProxy {
        _authorizeUpgrade(newImplementation);
        _upgradeToAndCallUUPS(newImplementation, new bytes(0), false);
    }

    /**
     * @dev Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call
     * encoded in `data`.
     *
     * Calls {_authorizeUpgrade}.
     *
     * Emits an {Upgraded} event.
     *
     * @custom:oz-upgrades-unsafe-allow-reachable delegatecall
     */
    function upgradeToAndCall(address newImplementation, bytes memory data) public payable virtual onlyProxy {
        _authorizeUpgrade(newImplementation);
        _upgradeToAndCallUUPS(newImplementation, data, true);
    }

    /**
     * @dev Function that should revert when `msg.sender` is not authorized to upgrade the contract. Called by
     * {upgradeTo} and {upgradeToAndCall}.
     *
     * Normally, this function will use an xref:access.adoc[access control] modifier such as {Ownable-onlyOwner}.
     *
     * ```solidity
     * function _authorizeUpgrade(address) internal override onlyOwner {}
     * ```
     */
    function _authorizeUpgrade(address newImplementation) internal virtual;

    /**
     * @dev This empty reserved space is put in place to allow future versions to add new
     * variables without shifting down storage in the inheritance chain.
     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
     */
    uint256[50] private __gap;
}

File 31 of 48 : draft-IERC1822Upgradeable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (interfaces/draft-IERC1822.sol)

pragma solidity ^0.8.0;

/**
 * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified
 * proxy whose upgrades are fully controlled by the current implementation.
 */
interface IERC1822ProxiableUpgradeable {
    /**
     * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation
     * address.
     *
     * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks
     * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this
     * function revert if invoked through a proxy.
     */
    function proxiableUUID() external view returns (bytes32);
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)

pragma solidity ^0.8.0;

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

/**
 * @dev Implementation of the {IERC165} interface.
 *
 * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check
 * for the additional interface id that will be supported. For example:
 *
 * ```solidity
 * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
 *     return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
 * }
 * ```
 *
 * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.
 */
abstract contract ERC165Upgradeable is Initializable, IERC165Upgradeable {
    function __ERC165_init() internal onlyInitializing {
    }

    function __ERC165_init_unchained() internal onlyInitializing {
    }
    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
        return interfaceId == type(IERC165Upgradeable).interfaceId;
    }

    /**
     * @dev This empty reserved space is put in place to allow future versions to add new
     * variables without shifting down storage in the inheritance chain.
     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
     */
    uint256[50] private __gap;
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/introspection/ERC165Checker.sol)

pragma solidity ^0.8.0;

import "./IERC165Upgradeable.sol";

/**
 * @dev Library used to query support of an interface declared via {IERC165}.
 *
 * Note that these functions return the actual result of the query: they do not
 * `revert` if an interface is not supported. It is up to the caller to decide
 * what to do in these cases.
 */
library ERC165CheckerUpgradeable {
    // As per the EIP-165 spec, no interface should ever match 0xffffffff
    bytes4 private constant _INTERFACE_ID_INVALID = 0xffffffff;

    /**
     * @dev Returns true if `account` supports the {IERC165} interface.
     */
    function supportsERC165(address account) internal view returns (bool) {
        // Any contract that implements ERC165 must explicitly indicate support of
        // InterfaceId_ERC165 and explicitly indicate non-support of InterfaceId_Invalid
        return
            supportsERC165InterfaceUnchecked(account, type(IERC165Upgradeable).interfaceId) &&
            !supportsERC165InterfaceUnchecked(account, _INTERFACE_ID_INVALID);
    }

    /**
     * @dev Returns true if `account` supports the interface defined by
     * `interfaceId`. Support for {IERC165} itself is queried automatically.
     *
     * See {IERC165-supportsInterface}.
     */
    function supportsInterface(address account, bytes4 interfaceId) internal view returns (bool) {
        // query support of both ERC165 as per the spec and support of _interfaceId
        return supportsERC165(account) && supportsERC165InterfaceUnchecked(account, interfaceId);
    }

    /**
     * @dev Returns a boolean array where each value corresponds to the
     * interfaces passed in and whether they're supported or not. This allows
     * you to batch check interfaces for a contract where your expectation
     * is that some interfaces may not be supported.
     *
     * See {IERC165-supportsInterface}.
     *
     * _Available since v3.4._
     */
    function getSupportedInterfaces(
        address account,
        bytes4[] memory interfaceIds
    ) internal view returns (bool[] memory) {
        // an array of booleans corresponding to interfaceIds and whether they're supported or not
        bool[] memory interfaceIdsSupported = new bool[](interfaceIds.length);

        // query support of ERC165 itself
        if (supportsERC165(account)) {
            // query support of each interface in interfaceIds
            for (uint256 i = 0; i < interfaceIds.length; i++) {
                interfaceIdsSupported[i] = supportsERC165InterfaceUnchecked(account, interfaceIds[i]);
            }
        }

        return interfaceIdsSupported;
    }

    /**
     * @dev Returns true if `account` supports all the interfaces defined in
     * `interfaceIds`. Support for {IERC165} itself is queried automatically.
     *
     * Batch-querying can lead to gas savings by skipping repeated checks for
     * {IERC165} support.
     *
     * See {IERC165-supportsInterface}.
     */
    function supportsAllInterfaces(address account, bytes4[] memory interfaceIds) internal view returns (bool) {
        // query support of ERC165 itself
        if (!supportsERC165(account)) {
            return false;
        }

        // query support of each interface in interfaceIds
        for (uint256 i = 0; i < interfaceIds.length; i++) {
            if (!supportsERC165InterfaceUnchecked(account, interfaceIds[i])) {
                return false;
            }
        }

        // all interfaces supported
        return true;
    }

    /**
     * @notice Query if a contract implements an interface, does not check ERC165 support
     * @param account The address of the contract to query for support of an interface
     * @param interfaceId The interface identifier, as specified in ERC-165
     * @return true if the contract at account indicates support of the interface with
     * identifier interfaceId, false otherwise
     * @dev Assumes that account contains a contract that supports ERC165, otherwise
     * the behavior of this method is undefined. This precondition can be checked
     * with {supportsERC165}.
     *
     * Some precompiled contracts will falsely indicate support for a given interface, so caution
     * should be exercised when using this function.
     *
     * Interface identification is specified in ERC-165.
     */
    function supportsERC165InterfaceUnchecked(address account, bytes4 interfaceId) internal view returns (bool) {
        // prepare call
        bytes memory encodedParams = abi.encodeWithSelector(IERC165Upgradeable.supportsInterface.selector, interfaceId);

        // perform static call
        bool success;
        uint256 returnSize;
        uint256 returnValue;
        assembly {
            success := staticcall(30000, account, add(encodedParams, 0x20), mload(encodedParams), 0x00, 0x20)
            returnSize := returndatasize()
            returnValue := mload(0x00)
        }

        return success && returnSize >= 0x20 && returnValue > 0;
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Counters.sol)

pragma solidity ^0.8.0;

/**
 * @title Counters
 * @author Matt Condon (@shrugs)
 * @dev Provides counters that can only be incremented, decremented or reset. This can be used e.g. to track the number
 * of elements in a mapping, issuing ERC721 ids, or counting request ids.
 *
 * Include with `using Counters for Counters.Counter;`
 */
library CountersUpgradeable {
    struct Counter {
        // This variable should never be directly accessed by users of the library: interactions must be restricted to
        // the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add
        // this feature: see https://github.com/ethereum/solidity/issues/4637
        uint256 _value; // default: 0
    }

    function current(Counter storage counter) internal view returns (uint256) {
        return counter._value;
    }

    function increment(Counter storage counter) internal {
        unchecked {
            counter._value += 1;
        }
    }

    function decrement(Counter storage counter) internal {
        uint256 value = counter._value;
        require(value > 0, "Counter: decrement overflow");
        unchecked {
            counter._value = value - 1;
        }
    }

    function reset(Counter storage counter) internal {
        counter._value = 0;
    }
}

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

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (proxy/Proxy.sol)

pragma solidity ^0.8.0;

/**
 * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM
 * instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to
 * be specified by overriding the virtual {_implementation} function.
 *
 * Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a
 * different contract through the {_delegate} function.
 *
 * The success and return data of the delegated call will be returned back to the caller of the proxy.
 */
abstract contract Proxy {
    /**
     * @dev Delegates the current call to `implementation`.
     *
     * This function does not return to its internal call site, it will return directly to the external caller.
     */
    function _delegate(address implementation) internal virtual {
        assembly {
            // Copy msg.data. We take full control of memory in this inline assembly
            // block because it will not return to Solidity code. We overwrite the
            // Solidity scratch pad at memory position 0.
            calldatacopy(0, 0, calldatasize())

            // Call the implementation.
            // out and outsize are 0 because we don't know the size yet.
            let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)

            // Copy the returned data.
            returndatacopy(0, 0, returndatasize())

            switch result
            // delegatecall returns 0 on error.
            case 0 {
                revert(0, returndatasize())
            }
            default {
                return(0, returndatasize())
            }
        }
    }

    /**
     * @dev This is a virtual function that should be overridden so it returns the address to which the fallback function
     * and {_fallback} should delegate.
     */
    function _implementation() internal view virtual returns (address);

    /**
     * @dev Delegates the current call to the address returned by `_implementation()`.
     *
     * This function does not return to its internal call site, it will return directly to the external caller.
     */
    function _fallback() internal virtual {
        _beforeFallback();
        _delegate(_implementation());
    }

    /**
     * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other
     * function in the contract matches the call data.
     */
    fallback() external payable virtual {
        _fallback();
    }

    /**
     * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if call data
     * is empty.
     */
    receive() external payable virtual {
        _fallback();
    }

    /**
     * @dev Hook that is called before falling back to the implementation. Can happen as part of a manual `_fallback`
     * call, or as part of the Solidity `fallback` or `receive` functions.
     *
     * If overridden should call `super._beforeFallback()`.
     */
    function _beforeFallback() internal virtual {}
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (proxy/ERC1967/ERC1967Upgrade.sol)

pragma solidity ^0.8.2;

import "../beacon/IBeacon.sol";
import "../../interfaces/IERC1967.sol";
import "../../interfaces/draft-IERC1822.sol";
import "../../utils/Address.sol";
import "../../utils/StorageSlot.sol";

/**
 * @dev This abstract contract provides getters and event emitting update functions for
 * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots.
 *
 * _Available since v4.1._
 */
abstract contract ERC1967Upgrade is IERC1967 {
    // This is the keccak-256 hash of "eip1967.proxy.rollback" subtracted by 1
    bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143;

    /**
     * @dev Storage slot with the address of the current implementation.
     * This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1, and is
     * validated in the constructor.
     */
    bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;

    /**
     * @dev Returns the current implementation address.
     */
    function _getImplementation() internal view returns (address) {
        return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;
    }

    /**
     * @dev Stores a new address in the EIP1967 implementation slot.
     */
    function _setImplementation(address newImplementation) private {
        require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract");
        StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
    }

    /**
     * @dev Perform implementation upgrade
     *
     * Emits an {Upgraded} event.
     */
    function _upgradeTo(address newImplementation) internal {
        _setImplementation(newImplementation);
        emit Upgraded(newImplementation);
    }

    /**
     * @dev Perform implementation upgrade with additional setup call.
     *
     * Emits an {Upgraded} event.
     */
    function _upgradeToAndCall(address newImplementation, bytes memory data, bool forceCall) internal {
        _upgradeTo(newImplementation);
        if (data.length > 0 || forceCall) {
            Address.functionDelegateCall(newImplementation, data);
        }
    }

    /**
     * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call.
     *
     * Emits an {Upgraded} event.
     */
    function _upgradeToAndCallUUPS(address newImplementation, bytes memory data, bool forceCall) internal {
        // Upgrades from old implementations will perform a rollback test. This test requires the new
        // implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing
        // this special case will break upgrade paths from old UUPS implementation to new ones.
        if (StorageSlot.getBooleanSlot(_ROLLBACK_SLOT).value) {
            _setImplementation(newImplementation);
        } else {
            try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) {
                require(slot == _IMPLEMENTATION_SLOT, "ERC1967Upgrade: unsupported proxiableUUID");
            } catch {
                revert("ERC1967Upgrade: new implementation is not UUPS");
            }
            _upgradeToAndCall(newImplementation, data, forceCall);
        }
    }

    /**
     * @dev Storage slot with the admin of the contract.
     * This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1, and is
     * validated in the constructor.
     */
    bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;

    /**
     * @dev Returns the current admin.
     */
    function _getAdmin() internal view returns (address) {
        return StorageSlot.getAddressSlot(_ADMIN_SLOT).value;
    }

    /**
     * @dev Stores a new address in the EIP1967 admin slot.
     */
    function _setAdmin(address newAdmin) private {
        require(newAdmin != address(0), "ERC1967: new admin is the zero address");
        StorageSlot.getAddressSlot(_ADMIN_SLOT).value = newAdmin;
    }

    /**
     * @dev Changes the admin of the proxy.
     *
     * Emits an {AdminChanged} event.
     */
    function _changeAdmin(address newAdmin) internal {
        emit AdminChanged(_getAdmin(), newAdmin);
        _setAdmin(newAdmin);
    }

    /**
     * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.
     * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor.
     */
    bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;

    /**
     * @dev Returns the current beacon.
     */
    function _getBeacon() internal view returns (address) {
        return StorageSlot.getAddressSlot(_BEACON_SLOT).value;
    }

    /**
     * @dev Stores a new beacon in the EIP1967 beacon slot.
     */
    function _setBeacon(address newBeacon) private {
        require(Address.isContract(newBeacon), "ERC1967: new beacon is not a contract");
        require(
            Address.isContract(IBeacon(newBeacon).implementation()),
            "ERC1967: beacon implementation is not a contract"
        );
        StorageSlot.getAddressSlot(_BEACON_SLOT).value = newBeacon;
    }

    /**
     * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does
     * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that).
     *
     * Emits a {BeaconUpgraded} event.
     */
    function _upgradeBeaconToAndCall(address newBeacon, bytes memory data, bool forceCall) internal {
        _setBeacon(newBeacon);
        emit BeaconUpgraded(newBeacon);
        if (data.length > 0 || forceCall) {
            Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data);
        }
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)

pragma solidity ^0.8.2;

import "../../utils/AddressUpgradeable.sol";

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

    /**
     * @dev Indicates that the contract is in the process of being initialized.
     */
    bool private _initializing;

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

    /**
     * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,
     * `onlyInitializing` functions can be used to initialize parent contracts.
     *
     * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a
     * constructor.
     *
     * Emits an {Initialized} event.
     */
    modifier initializer() {
        bool isTopLevelCall = !_initializing;
        require(
            (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),
            "Initializable: contract is already initialized"
        );
        _initialized = 1;
        if (isTopLevelCall) {
            _initializing = true;
        }
        _;
        if (isTopLevelCall) {
            _initializing = false;
            emit Initialized(1);
        }
    }

    /**
     * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the
     * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be
     * used to initialize parent contracts.
     *
     * A reinitializer may be used after the original initialization step. This is essential to configure modules that
     * are added through upgrades and that require initialization.
     *
     * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`
     * cannot be nested. If one is invoked in the context of another, execution will revert.
     *
     * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in
     * a contract, executing them in the right order is up to the developer or operator.
     *
     * WARNING: setting the version to 255 will prevent any future reinitialization.
     *
     * Emits an {Initialized} event.
     */
    modifier reinitializer(uint8 version) {
        require(!_initializing && _initialized < version, "Initializable: contract is already initialized");
        _initialized = version;
        _initializing = true;
        _;
        _initializing = false;
        emit Initialized(version);
    }

    /**
     * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the
     * {initializer} and {reinitializer} modifiers, directly or indirectly.
     */
    modifier onlyInitializing() {
        require(_initializing, "Initializable: contract is not initializing");
        _;
    }

    /**
     * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.
     * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized
     * to any version. It is recommended to use this to lock implementation contracts that are designed to be called
     * through proxies.
     *
     * Emits an {Initialized} event the first time it is successfully executed.
     */
    function _disableInitializers() internal virtual {
        require(!_initializing, "Initializable: contract is initializing");
        if (_initialized != type(uint8).max) {
            _initialized = type(uint8).max;
            emit Initialized(type(uint8).max);
        }
    }

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

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

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (proxy/ERC1967/ERC1967Upgrade.sol)

pragma solidity ^0.8.2;

import "../beacon/IBeaconUpgradeable.sol";
import "../../interfaces/IERC1967Upgradeable.sol";
import "../../interfaces/draft-IERC1822Upgradeable.sol";
import "../../utils/AddressUpgradeable.sol";
import "../../utils/StorageSlotUpgradeable.sol";
import {Initializable} from "../utils/Initializable.sol";

/**
 * @dev This abstract contract provides getters and event emitting update functions for
 * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots.
 *
 * _Available since v4.1._
 */
abstract contract ERC1967UpgradeUpgradeable is Initializable, IERC1967Upgradeable {
    // This is the keccak-256 hash of "eip1967.proxy.rollback" subtracted by 1
    bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143;

    /**
     * @dev Storage slot with the address of the current implementation.
     * This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1, and is
     * validated in the constructor.
     */
    bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;

    function __ERC1967Upgrade_init() internal onlyInitializing {
    }

    function __ERC1967Upgrade_init_unchained() internal onlyInitializing {
    }
    /**
     * @dev Returns the current implementation address.
     */
    function _getImplementation() internal view returns (address) {
        return StorageSlotUpgradeable.getAddressSlot(_IMPLEMENTATION_SLOT).value;
    }

    /**
     * @dev Stores a new address in the EIP1967 implementation slot.
     */
    function _setImplementation(address newImplementation) private {
        require(AddressUpgradeable.isContract(newImplementation), "ERC1967: new implementation is not a contract");
        StorageSlotUpgradeable.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
    }

    /**
     * @dev Perform implementation upgrade
     *
     * Emits an {Upgraded} event.
     */
    function _upgradeTo(address newImplementation) internal {
        _setImplementation(newImplementation);
        emit Upgraded(newImplementation);
    }

    /**
     * @dev Perform implementation upgrade with additional setup call.
     *
     * Emits an {Upgraded} event.
     */
    function _upgradeToAndCall(address newImplementation, bytes memory data, bool forceCall) internal {
        _upgradeTo(newImplementation);
        if (data.length > 0 || forceCall) {
            AddressUpgradeable.functionDelegateCall(newImplementation, data);
        }
    }

    /**
     * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call.
     *
     * Emits an {Upgraded} event.
     */
    function _upgradeToAndCallUUPS(address newImplementation, bytes memory data, bool forceCall) internal {
        // Upgrades from old implementations will perform a rollback test. This test requires the new
        // implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing
        // this special case will break upgrade paths from old UUPS implementation to new ones.
        if (StorageSlotUpgradeable.getBooleanSlot(_ROLLBACK_SLOT).value) {
            _setImplementation(newImplementation);
        } else {
            try IERC1822ProxiableUpgradeable(newImplementation).proxiableUUID() returns (bytes32 slot) {
                require(slot == _IMPLEMENTATION_SLOT, "ERC1967Upgrade: unsupported proxiableUUID");
            } catch {
                revert("ERC1967Upgrade: new implementation is not UUPS");
            }
            _upgradeToAndCall(newImplementation, data, forceCall);
        }
    }

    /**
     * @dev Storage slot with the admin of the contract.
     * This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1, and is
     * validated in the constructor.
     */
    bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;

    /**
     * @dev Returns the current admin.
     */
    function _getAdmin() internal view returns (address) {
        return StorageSlotUpgradeable.getAddressSlot(_ADMIN_SLOT).value;
    }

    /**
     * @dev Stores a new address in the EIP1967 admin slot.
     */
    function _setAdmin(address newAdmin) private {
        require(newAdmin != address(0), "ERC1967: new admin is the zero address");
        StorageSlotUpgradeable.getAddressSlot(_ADMIN_SLOT).value = newAdmin;
    }

    /**
     * @dev Changes the admin of the proxy.
     *
     * Emits an {AdminChanged} event.
     */
    function _changeAdmin(address newAdmin) internal {
        emit AdminChanged(_getAdmin(), newAdmin);
        _setAdmin(newAdmin);
    }

    /**
     * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.
     * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor.
     */
    bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;

    /**
     * @dev Returns the current beacon.
     */
    function _getBeacon() internal view returns (address) {
        return StorageSlotUpgradeable.getAddressSlot(_BEACON_SLOT).value;
    }

    /**
     * @dev Stores a new beacon in the EIP1967 beacon slot.
     */
    function _setBeacon(address newBeacon) private {
        require(AddressUpgradeable.isContract(newBeacon), "ERC1967: new beacon is not a contract");
        require(
            AddressUpgradeable.isContract(IBeaconUpgradeable(newBeacon).implementation()),
            "ERC1967: beacon implementation is not a contract"
        );
        StorageSlotUpgradeable.getAddressSlot(_BEACON_SLOT).value = newBeacon;
    }

    /**
     * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does
     * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that).
     *
     * Emits a {BeaconUpgraded} event.
     */
    function _upgradeBeaconToAndCall(address newBeacon, bytes memory data, bool forceCall) internal {
        _setBeacon(newBeacon);
        emit BeaconUpgraded(newBeacon);
        if (data.length > 0 || forceCall) {
            AddressUpgradeable.functionDelegateCall(IBeaconUpgradeable(newBeacon).implementation(), data);
        }
    }

    /**
     * @dev This empty reserved space is put in place to allow future versions to add new
     * variables without shifting down storage in the inheritance chain.
     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
     */
    uint256[50] private __gap;
}

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

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol)

pragma solidity ^0.8.0;

/**
 * @dev This is the interface that {BeaconProxy} expects of its beacon.
 */
interface IBeacon {
    /**
     * @dev Must return an address that can be used as a delegate call target.
     *
     * {BeaconProxy} will check that this address is a contract.
     */
    function implementation() external view returns (address);
}

File 42 of 48 : IERC1967.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (interfaces/IERC1967.sol)

pragma solidity ^0.8.0;

/**
 * @dev ERC-1967: Proxy Storage Slots. This interface contains the events defined in the ERC.
 *
 * _Available since v4.8.3._
 */
interface IERC1967 {
    /**
     * @dev Emitted when the implementation is upgraded.
     */
    event Upgraded(address indexed implementation);

    /**
     * @dev Emitted when the admin account has changed.
     */
    event AdminChanged(address previousAdmin, address newAdmin);

    /**
     * @dev Emitted when the beacon is changed.
     */
    event BeaconUpgraded(address indexed beacon);
}

File 43 of 48 : draft-IERC1822.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (interfaces/draft-IERC1822.sol)

pragma solidity ^0.8.0;

/**
 * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified
 * proxy whose upgrades are fully controlled by the current implementation.
 */
interface IERC1822Proxiable {
    /**
     * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation
     * address.
     *
     * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks
     * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this
     * function revert if invoked through a proxy.
     */
    function proxiableUUID() external view returns (bytes32);
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/StorageSlot.sol)
// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.

pragma solidity ^0.8.0;

/**
 * @dev Library for reading and writing primitive types to specific storage slots.
 *
 * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.
 * This library helps with reading and writing to such slots without the need for inline assembly.
 *
 * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.
 *
 * Example usage to set ERC1967 implementation slot:
 * ```solidity
 * contract ERC1967 {
 *     bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
 *
 *     function _getImplementation() internal view returns (address) {
 *         return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;
 *     }
 *
 *     function _setImplementation(address newImplementation) internal {
 *         require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract");
 *         StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
 *     }
 * }
 * ```
 *
 * _Available since v4.1 for `address`, `bool`, `bytes32`, `uint256`._
 * _Available since v4.9 for `string`, `bytes`._
 */
library StorageSlot {
    struct AddressSlot {
        address value;
    }

    struct BooleanSlot {
        bool value;
    }

    struct Bytes32Slot {
        bytes32 value;
    }

    struct Uint256Slot {
        uint256 value;
    }

    struct StringSlot {
        string value;
    }

    struct BytesSlot {
        bytes value;
    }

    /**
     * @dev Returns an `AddressSlot` with member `value` located at `slot`.
     */
    function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `BooleanSlot` with member `value` located at `slot`.
     */
    function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `Bytes32Slot` with member `value` located at `slot`.
     */
    function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `Uint256Slot` with member `value` located at `slot`.
     */
    function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `StringSlot` with member `value` located at `slot`.
     */
    function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `StringSlot` representation of the string storage pointer `store`.
     */
    function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := store.slot
        }
    }

    /**
     * @dev Returns an `BytesSlot` with member `value` located at `slot`.
     */
    function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.
     */
    function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := store.slot
        }
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)

pragma solidity ^0.8.1;

/**
 * @dev Collection of functions related to the address type
 */
library AddressUpgradeable {
    /**
     * @dev Returns true if `account` is a contract.
     *
     * [IMPORTANT]
     * ====
     * It is unsafe to assume that an address for which this function returns
     * false is an externally-owned account (EOA) and not a contract.
     *
     * Among others, `isContract` will return false for the following
     * types of addresses:
     *
     *  - an externally-owned account
     *  - a contract in construction
     *  - an address where a contract will be created
     *  - an address where a contract lived, but was destroyed
     *
     * Furthermore, `isContract` will also return true if the target contract within
     * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,
     * which only has an effect at the end of a transaction.
     * ====
     *
     * [IMPORTANT]
     * ====
     * You shouldn't rely on `isContract` to protect against flash loan attacks!
     *
     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
     * constructor.
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // This method relies on extcodesize/address.code.length, which returns 0
        // for contracts in construction, since the code is only stored at the end
        // of the constructor execution.

        return account.code.length > 0;
    }

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

        (bool success, ) = recipient.call{value: amount}("");
        require(success, "Address: unable to send value, recipient may have reverted");
    }

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

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
     * `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        return functionCallWithValue(target, data, 0, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but also transferring `value` wei to `target`.
     *
     * Requirements:
     *
     * - the calling contract must have an ETH balance of at least `value`.
     * - the called Solidity function must be `payable`.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
        return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
    }

    /**
     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
     * with `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value,
        string memory errorMessage
    ) internal returns (bytes memory) {
        require(address(this).balance >= value, "Address: insufficient balance for call");
        (bool success, bytes memory returndata) = target.call{value: value}(data);
        return verifyCallResultFromTarget(target, success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
        return functionStaticCall(target, data, "Address: low-level static call failed");
    }

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

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionDelegateCall(target, data, "Address: low-level delegate call failed");
    }

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

    /**
     * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
     * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
     *
     * _Available since v4.8._
     */
    function verifyCallResultFromTarget(
        address target,
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal view returns (bytes memory) {
        if (success) {
            if (returndata.length == 0) {
                // only check isContract if the call was successful and the return data is empty
                // otherwise we already know that it was a contract
                require(isContract(target), "Address: call to non-contract");
            }
            return returndata;
        } else {
            _revert(returndata, errorMessage);
        }
    }

    /**
     * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
     * revert reason or using the provided one.
     *
     * _Available since v4.3._
     */
    function verifyCallResult(
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal pure returns (bytes memory) {
        if (success) {
            return returndata;
        } else {
            _revert(returndata, errorMessage);
        }
    }

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

File 46 of 48 : IBeaconUpgradeable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol)

pragma solidity ^0.8.0;

/**
 * @dev This is the interface that {BeaconProxy} expects of its beacon.
 */
interface IBeaconUpgradeable {
    /**
     * @dev Must return an address that can be used as a delegate call target.
     *
     * {BeaconProxy} will check that this address is a contract.
     */
    function implementation() external view returns (address);
}

File 47 of 48 : IERC1967Upgradeable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (interfaces/IERC1967.sol)

pragma solidity ^0.8.0;

/**
 * @dev ERC-1967: Proxy Storage Slots. This interface contains the events defined in the ERC.
 *
 * _Available since v4.8.3._
 */
interface IERC1967Upgradeable {
    /**
     * @dev Emitted when the implementation is upgraded.
     */
    event Upgraded(address indexed implementation);

    /**
     * @dev Emitted when the admin account has changed.
     */
    event AdminChanged(address previousAdmin, address newAdmin);

    /**
     * @dev Emitted when the beacon is changed.
     */
    event BeaconUpgraded(address indexed beacon);
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/StorageSlot.sol)
// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.

pragma solidity ^0.8.0;

/**
 * @dev Library for reading and writing primitive types to specific storage slots.
 *
 * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.
 * This library helps with reading and writing to such slots without the need for inline assembly.
 *
 * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.
 *
 * Example usage to set ERC1967 implementation slot:
 * ```solidity
 * contract ERC1967 {
 *     bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
 *
 *     function _getImplementation() internal view returns (address) {
 *         return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;
 *     }
 *
 *     function _setImplementation(address newImplementation) internal {
 *         require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract");
 *         StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
 *     }
 * }
 * ```
 *
 * _Available since v4.1 for `address`, `bool`, `bytes32`, `uint256`._
 * _Available since v4.9 for `string`, `bytes`._
 */
library StorageSlotUpgradeable {
    struct AddressSlot {
        address value;
    }

    struct BooleanSlot {
        bool value;
    }

    struct Bytes32Slot {
        bytes32 value;
    }

    struct Uint256Slot {
        uint256 value;
    }

    struct StringSlot {
        string value;
    }

    struct BytesSlot {
        bytes value;
    }

    /**
     * @dev Returns an `AddressSlot` with member `value` located at `slot`.
     */
    function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `BooleanSlot` with member `value` located at `slot`.
     */
    function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `Bytes32Slot` with member `value` located at `slot`.
     */
    function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `Uint256Slot` with member `value` located at `slot`.
     */
    function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `StringSlot` with member `value` located at `slot`.
     */
    function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `StringSlot` representation of the string storage pointer `store`.
     */
    function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := store.slot
        }
    }

    /**
     * @dev Returns an `BytesSlot` with member `value` located at `slot`.
     */
    function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.
     */
    function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := store.slot
        }
    }
}

Settings
{
  "remappings": [
    "@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/",
    "@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/",
    "@aragon/osx/=lib/osx/packages/contracts/src/",
    "@aragon/osx-commons-contracts/=lib/osx-commons/contracts/",
    "@aragon/admin-plugin/=lib/admin-plugin/packages/contracts/src/",
    "@aragon/multisig-plugin/=lib/multisig-plugin/packages/contracts/src/",
    "@aragon/token-voting-plugin/=lib/token-voting-plugin/src/",
    "@aragon/staged-proposal-processor-plugin/=lib/staged-proposal-processor-plugin/src/",
    "@ensdomains/ens-contracts/=lib/ens-contracts/",
    "@ensdomains/buffer/=lib/buffer/",
    "forge-std/=lib/forge-std/src/",
    "@openzeppelin/openzeppelin-foundry-upgrades/=lib/staged-proposal-processor-plugin/node_modules/@openzeppelin/openzeppelin-foundry-upgrades/src/",
    "admin-plugin/=lib/admin-plugin/",
    "buffer/=lib/buffer/contracts/",
    "ds-test/=lib/openzeppelin-contracts-upgradeable/lib/forge-std/lib/ds-test/src/",
    "ens-contracts/=lib/ens-contracts/contracts/",
    "erc4626-tests/=lib/openzeppelin-contracts-upgradeable/lib/erc4626-tests/",
    "multisig-plugin/=lib/multisig-plugin/",
    "openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/",
    "openzeppelin-contracts/=lib/openzeppelin-contracts/",
    "openzeppelin/=lib/openzeppelin-contracts-upgradeable/contracts/",
    "osx-commons/=lib/osx-commons/",
    "osx/=lib/osx/",
    "plugin-version-1.3/=lib/token-voting-plugin/lib/plugin-version-1.3/packages/contracts/src/",
    "solidity-stringutils/=lib/staged-proposal-processor-plugin/node_modules/solidity-stringutils/",
    "staged-proposal-processor-plugin/=lib/staged-proposal-processor-plugin/src/",
    "token-voting-plugin/=lib/token-voting-plugin/src/"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "metadata": {
    "useLiteralContent": false,
    "bytecodeHash": "ipfs",
    "appendCBOR": true
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "evmVersion": "cancun",
  "viaIR": true
}

Contract Security Audit

Contract ABI

API
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint16","name":"fromBuild","type":"uint16"},{"internalType":"uint16","name":"thisBuild","type":"uint16"}],"name":"InvalidUpdatePath","type":"error"},{"inputs":[],"name":"CONDITION_IMPLEMENTATION","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"implementation","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_dao","type":"address"},{"internalType":"bytes","name":"_installationParams","type":"bytes"}],"name":"prepareInstallation","outputs":[{"internalType":"address","name":"spp","type":"address"},{"components":[{"internalType":"address[]","name":"helpers","type":"address[]"},{"components":[{"internalType":"enum PermissionLib.Operation","name":"operation","type":"uint8"},{"internalType":"address","name":"where","type":"address"},{"internalType":"address","name":"who","type":"address"},{"internalType":"address","name":"condition","type":"address"},{"internalType":"bytes32","name":"permissionId","type":"bytes32"}],"internalType":"struct PermissionLib.MultiTargetPermission[]","name":"permissions","type":"tuple[]"}],"internalType":"struct IPluginSetup.PreparedSetupData","name":"preparedSetupData","type":"tuple"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_dao","type":"address"},{"components":[{"internalType":"address","name":"plugin","type":"address"},{"internalType":"address[]","name":"currentHelpers","type":"address[]"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct IPluginSetup.SetupPayload","name":"_payload","type":"tuple"}],"name":"prepareUninstallation","outputs":[{"components":[{"internalType":"enum PermissionLib.Operation","name":"operation","type":"uint8"},{"internalType":"address","name":"where","type":"address"},{"internalType":"address","name":"who","type":"address"},{"internalType":"address","name":"condition","type":"address"},{"internalType":"bytes32","name":"permissionId","type":"bytes32"}],"internalType":"struct PermissionLib.MultiTargetPermission[]","name":"permissions","type":"tuple[]"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"_dao","type":"address"},{"internalType":"uint16","name":"_fromBuild","type":"uint16"},{"components":[{"internalType":"address","name":"plugin","type":"address"},{"internalType":"address[]","name":"currentHelpers","type":"address[]"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct IPluginSetup.SetupPayload","name":"_payload","type":"tuple"}],"name":"prepareUpdate","outputs":[{"internalType":"bytes","name":"","type":"bytes"},{"components":[{"internalType":"address[]","name":"helpers","type":"address[]"},{"components":[{"internalType":"enum PermissionLib.Operation","name":"operation","type":"uint8"},{"internalType":"address","name":"where","type":"address"},{"internalType":"address","name":"who","type":"address"},{"internalType":"address","name":"condition","type":"address"},{"internalType":"bytes32","name":"permissionId","type":"bytes32"}],"internalType":"struct PermissionLib.MultiTargetPermission[]","name":"permissions","type":"tuple[]"}],"internalType":"struct IPluginSetup.PreparedSetupData","name":"","type":"tuple"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"protocolVersion","outputs":[{"internalType":"uint8[3]","name":"","type":"uint8[3]"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes4","name":"_interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}]

60c0806040523461015c57615c198181016001600160401b03811183821017610143578291611ce6833903905ff080156100f5576001600160a01b03166080526040516020818101916001600160401b0383118184101761014357826040525f81526001610157575b60405191611a5c8084016001600160401b0381118582101761014357606091959392956178ff863960408101925f8252604087830152518093520191935f5b82811061010057848403855ff080156100f5576001600160a01b031660a052604051611b8590816101618239608051818181610369015261137e015260a051818181610417015261133a0152f35b6040513d5f823e3d90fd5b8551805160ff90811686528184015116858401526040808201516001600160f01b03169086015260609081015190850152948101946080909301926001016100a7565b634e487b7160e01b5f52604160045260245ffd5b610068565b5f80fdfe6080806040526004361015610012575f80fd5b5f3560e01c90816301ffc9a71461142a575080632ae9c600146113ad5780635c60da1b146113695780637da5dd7c146113255780639cb0a12414610e59578063a8a9c29e14610df55763f10832f114610069575f80fd5b34610b42576040366003190112610b4257610082611494565b6001600160401b0360243511610b4257366023602435011215610b4257602435600401356001600160401b038111610b4257366024828135010111610b42576100c96115e3565b60a06024358381010312610b42576024803501356001600160401b038111610b4257602435019060248381350101604383011215610b4257602482013561010f816115fc565b9261011d60405194856115ae565b8184526024803586010160448284010111610b4257815f926044602093018387013784010152604460243501356001600160401b038111610b42576024848135010160438260243501011215610b425760248181350101359061017f82611617565b9161018d60405193846115ae565b8083526020830190819260248881350101602060248460051b8482350101010111610b42576044816024350101925b60446024358301600585901b01018410610bb55750505050606460243501356001600160401b038111610b4257602435019560248681350101604388011215610b425760248701359561020e87611617565b9761021c604051998a6115ae565b878952602089019060206024839a60071b8301010190602484813501018211610b4257604401915b818310610b465750505060409060246083199181359082350103010112610b42576040519161027283611578565b6102806084602435016114aa565b835260a46024350135916002831015610b4257602084979592970192835260018060a01b0316956040519463bfde57c360e01b602087015260e48601928860248801525f604488015260c06064880152518093526101048601926101048160051b88010192935f905b828210610a3c575050508582036023190160848701526103099250611539565b91516001600160a01b031660a48401525160028110156108ca5761033c91839160c483015203601f1981018352826115ae565b604051906103c690818301908382106001600160401b03831117610a285760406103a192859461178a86397f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602081018290520190611539565b03905ff08015610a1d5760018060a09695961b03169360405193846020810192631d0f8ff560e31b8452606482019286602484015260406044840152518093526084820190925f5b8181106109d4575050610405925003601f1981018652856115ae565b6e5af43d82803e903d91602b57fd5bf37f0000000000000000000000000000000000000000000000000000000000000000763d602d80600a3d3981f3363d3d373d3d3d363d7300000062ffffff8260881c16175f5260781b17602052603760095ff06001600160a01b03811694908515610996578151610913575b505050610140916040519261049581856115ae565b60098452601f19015f5b8181106108de5750506040516104b481611593565b5f81528560208201528160408201525f60608201527f6f36f8bf0398781285f5a40c489dbf3268ce3e205aba87f21e49e6805391b5a160808201526104f88461165d565b526105028361165d565b5060405161050f81611593565b5f808252602082018790526001600160a01b03604083015260608201527ff281525e53675515a6ba7cc7bea8a81e649b3608423ee2d73be1752cea887889608082015261055b8461166a565b526105658361166a565b5060405161057281611593565b5f81528560208201528160408201525f60608201527f06d294bc8cbad2e393408b20dd019a772661f60b8d633e56761157cb1ec85f8c60808201526105b68461167a565b526105c08361167a565b506040516105cd81611593565b5f81528560208201528160408201525f60608201527f568cc693d84eb1901f8bcecba154cbdef23ca3cf67efc0a0b698528a06c660f760808201526106118461168a565b5261061b8361168a565b5060405161062881611593565b5f81528560208201528160408201525f60608201527f4707e94b25cfce1a7c363508fbb838c35864388ad77284b248282b9746982b9b608082015261066c8461169a565b526106768361169a565b5060405161068381611593565b60028152602081018690526001600160a01b036040820152606081018590527f8c433a4cd6b51969eca37f974940894297b9fcf4b282a213fea5cd8f85289c9060808201526106d1846116aa565b526106db836116aa565b506040516106e881611593565b5f808252602082018790526001600160a01b03604083015260608201527fb014ce248804cab6a144581acce1eeb70ce5d54f08433b989d73bb0ccee3d3f96080820152610734846116ba565b5261073e836116ba565b5060405161074b81611593565b5f81528160208201528560408201525f60608201527fbf04b4486c9663d805744005c3da000eda93de6e3308a4a7a812eb565327b78d608082015261078f846116ca565b52610799836116ca565b50604051906107a782611593565b5f8296959493965283602083015260408201525f60608201527fd3d98e95f3486fc234d80c098cf0d2a0a3fb187833d7e9cc930f8c4f8335a0e760808201526107ef826116db565b526107f9816116db565b506020840190815260409161082a835161081385826115ae565b60018152601f19850136602083013780875261165d565b528151938493845282602085015260808401905192808501528251809152602060a085019301905f5b8181106108a8575050505190603f19838203016060840152602080835192838152019201905f5b818110610888575050500390f35b91935091602061089b60019286516114c8565b940191019184939261087a565b82516001600160a01b0316855286955060209485019490920191600101610853565b634e487b7160e01b5f52602160045260245ffd5b6020906040516108ed81611593565b5f81525f838201525f60408201525f60608201525f60808201528282880101520161049f565b5f8061098594604051946109286040876115ae565b601e86527f416464726573733a206c6f772d6c6576656c2063616c6c206661696c656400006020870152519082855af13d1561098e573d91610969836115fc565b9261097760405194856115ae565b83523d5f602085013e6116ec565b505f8080610480565b6060916116ec565b60405162461bcd60e51b8152602060048201526016602482015275115490cc4c4d8dce8818dc99585d194819985a5b195960521b6044820152606490fd5b91600191935060806020916060875160ff815116835260ff858201511685840152858060f01b0360408201511660408401520151606082015201940191019187929391936103e9565b6040513d5f823e3d90fd5b634e487b7160e01b5f52604160045260245ffd5b909192936101031989820301825285519061010081019180519261010083528351809152602061012084019401905f905b808210610af85750505060019260209260e080846001600160401b03878097015116868501526001600160401b0360408201511660408501526001600160401b03606082015116606085015261ffff608082015116608085015261ffff60a08201511660a085015260c0810151151560c08501520151151591015297019201920190949392916102e9565b9091946020608060019260608951858060a01b038151168352848101511515858401526040810151151560408401520151610b32816114be565b6060820152019601920190610a6d565b5f80fd5b608060248486823501030112610b425760405190610b638261155d565b610b6c8461164f565b8252610b7a6020850161164f565b60208301526040840135906001600160f01b0382168203610b4257826020926040608095015260608601356060820152815201920191610244565b83356001600160401b038111610b42576101006024358085018301908c0103601f190112610b42576040519061010082018281106001600160401b03821117610a285760405260446024358501820101356001600160401b038111610b425760248c81350101601f6020836024868a82350101010101011215610b42576044602435860183018201013590610c4982611617565b91610c5760405193846115ae565b8083528d6024602085019181350101602089818660248a8860071b9482350101010101010111610b4257908e83926020808b979660248a8a8235010101010101915b6064602435880189018601600786901b01018310610d795750505050509383610d66610100602486610d5560e08360209c9a8d9b9a8c9b839e52610ce6604084848482350101010161163b565b8c8b0152610cfd606084848482350101010161163b565b60408b0152610d15608084848482350101010161163b565b60608b0152610d2d60a084848482350101010161152a565b60808b0152610d4560c084848482350101010161152a565b60a08b015282350101010161162e565b60c08601528a82350101010161162e565b60e08201528152019501949150506101bc565b82608092939495969750602491823501030112610b425760405190610d9d8261155d565b610da6836114aa565b8252610db46020840161162e565b6020830152610dc56040840161162e565b60408301526060830135906003821015610b4257826020926060608095015281520191018f918995949392610c99565b34610b42576060366003190112610b4257610e0e611494565b50610e17611519565b506044356001600160401b038111610b42576060906003199036030112610b4257610e406115e3565b5063098990c560e11b5f525f600452600160245260445ffd5b34610b42576040366003190112610b4257610e72611494565b6024356001600160401b038111610b42578036036060600319820112610b4257610e9e826004016115cf565b9160248101359160221901821215610b4257016004810135906001600160401b038211610b4257602401908060051b36038213610b42571561131157610ee3906115cf565b60405191610140610ef481856115ae565b60098452601f19015f5b8181106112dc57505060405190610f1482611593565b600182526001600160a01b03908116602083018190529416604082018190525f60608301527f6f36f8bf0398781285f5a40c489dbf3268ce3e205aba87f21e49e6805391b5a1608083015290610f698461165d565b52610f738361165d565b50604051610f8081611593565b60018152602081018590526001600160a01b0360408201525f60608201527ff281525e53675515a6ba7cc7bea8a81e649b3608423ee2d73be1752cea8878896080820152610fcd8461166a565b52610fd78361166a565b50604051610fe481611593565b600181528460208201528160408201525f60608201527f06d294bc8cbad2e393408b20dd019a772661f60b8d633e56761157cb1ec85f8c60808201526110298461167a565b526110338361167a565b5060405161104081611593565b600181528460208201528160408201525f60608201527f568cc693d84eb1901f8bcecba154cbdef23ca3cf67efc0a0b698528a06c660f760808201526110858461168a565b5261108f8361168a565b5060405161109c81611593565b600181528460208201528160408201525f60608201527f4707e94b25cfce1a7c363508fbb838c35864388ad77284b248282b9746982b9b60808201526110e18461169a565b526110eb8361169a565b50600193604051926110fc84611593565b60038610156108ca57858452602084018290526001600160a01b036040850181905216606084018190527f8c433a4cd6b51969eca37f974940894297b9fcf4b282a213fea5cd8f85289c90608085015292611156856116aa565b52611160846116aa565b5060405161116d81611593565b60038610156108ca57858152602081018290526001600160a01b0360408201525f60608201527fb014ce248804cab6a144581acce1eeb70ce5d54f08433b989d73bb0ccee3d3f960808201526111c2856116ba565b526111cc846116ba565b50604051906111da82611593565b60038610156108ca5785825282602083015260408201525f60608201527fbf04b4486c9663d805744005c3da000eda93de6e3308a4a7a812eb565327b78d6080820152611226846116ca565b52611230836116ca565b506040519161123e83611593565b60038510156108ca57848395949552602083015260408201525f60608201527fd3d98e95f3486fc234d80c098cf0d2a0a3fb187833d7e9cc930f8c4f8335a0e7608082015261128c836116db565b52611296826116db565b5060405190602082016020835283518091526020604084019401905f5b8181106112c05784860385f35b90919260206112d1829786516114c8565b9694019291016112b3565b6020906040516112eb81611593565b5f81525f838201525f60408201525f60608201525f608082015282828801015201610efe565b634e487b7160e01b5f52603260045260245ffd5b34610b42575f366003190112610b42576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b34610b42575f366003190112610b42576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b34610b42575f366003190112610b42576060806040516113cd82826115ae565b3690376040518181018181106001600160401b03821117610a285760405260018152600460208201525f604082015260405190815f905b6003821061141157505050f35b60208060019260ff865116815201930191019091611404565b34610b42576020366003190112610b42576004359063ffffffff60e01b8216809203610b425760209163099718b560e41b8114908115611484575b8115611473575b5015158152f35b6301ffc9a760e01b1490508361146c565b621574e360e91b81149150611465565b600435906001600160a01b0382168203610b4257565b35906001600160a01b0382168203610b4257565b600311156108ca57565b90608060a09280516114d9816114be565b8352600180851b036020820151166020840152600180851b036040820151166040840152600180851b036060820151166060840152015160808201520190565b6024359061ffff82168203610b4257565b359061ffff82168203610b4257565b805180835260209291819084018484015e5f828201840152601f01601f1916010190565b608081019081106001600160401b03821117610a2857604052565b604081019081106001600160401b03821117610a2857604052565b60a081019081106001600160401b03821117610a2857604052565b90601f801991011681019081106001600160401b03821117610a2857604052565b356001600160a01b0381168103610b425790565b604051906115f082611578565b60606020838281520152565b6001600160401b038111610a2857601f01601f191660200190565b6001600160401b038111610a285760051b60200190565b35908115158203610b4257565b35906001600160401b0382168203610b4257565b359060ff82168203610b4257565b8051156113115760200190565b8051600110156113115760400190565b8051600210156113115760600190565b8051600310156113115760800190565b8051600410156113115760a00190565b8051600510156113115760c00190565b8051600610156113115760e00190565b805160071015611311576101000190565b805160081015611311576101200190565b9192901561174e5750815115611700575090565b3b156117095790565b60405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606490fd5b8251909150156117615750805190602001fd5b60405162461bcd60e51b815260206004820152908190611785906024830190611539565b0390fdfe60806040526103c680380380610014816101f2565b9283398101906040818303126101ee5780516001600160a01b038116918282036101ee576020810151906001600160401b0382116101ee57019183601f840112156101ee57825161006c6100678261022b565b6101f2565b938185526020850195602083830101116101ee57815f926020809301885e85010152813b15610193577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80546001600160a01b031916821790557fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b5f80a281511580159061018c575b610108575b60405160cb90816102fb8239f35b5f8061017b9461011860606101f2565b94602786527f416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c6020870152660819985a5b195960ca1b60408701525190845af43d15610184573d9161016c6100678461022b565b9283523d5f602085013e610246565b505f80806100fa565b606091610246565b505f6100f5565b60405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b6064820152608490fd5b5f80fd5b6040519190601f01601f191682016001600160401b0381118382101761021757604052565b634e487b7160e01b5f52604160045260245ffd5b6001600160401b03811161021757601f01601f191660200190565b919290156102a8575081511561025a575090565b3b156102635790565b60405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606490fd5b8251909150156102bb5750805190602001fd5b604460209160405192839162461bcd60e51b83528160048401528051918291826024860152018484015e5f828201840152601f01601f19168101030190fdfe608060405236156051577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc545f9081906001600160a01b0316368280378136915af43d5f803e15604d573d5ff35b3d5ffd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc545f9081906001600160a01b0316368280378136915af43d5f803e15604d573d5ff3fea26469706673582212203bf93d98380d30a31ff94676bcd53f6cf4fd06145a15d34fda5d76afee117ce864736f6c634300081c0033a2646970667358221220d549dc05acebacd8e98bd12d54be05c98c16b1115bf8330bcbd5aeac4f46f58d64736f6c634300081c003360a080604052346100da57306080525f549060ff8260081c16610088575060ff8082160361004e575b604051615b3a90816100df8239608051818181610d8801528181611195015261130d0152f35b60ff90811916175f557f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498602060405160ff8152a15f610028565b62461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b6064820152608490fd5b5f80fdfe60806040526004361015610011575f80fd5b5f3560e01c806301ffc9a7146102c45780630b47808d146102bf5780631abf3f11146102ba5780631c622dea146102b55780631f3cb5b4146102b05780632ae9c600146102ab57806330196ab9146102a657806335ade049146102a15780633659cfe61461029c5780633d3f4b1b146102975780633e4f49e61461029257806340e58ee51461028d5780634162169f1461028857806341de6830146102835780634e3ed5e91461027e5780634f1ef28614610279578063523039621461027457806352d1902d1461026f578063572b6c051461026a5780635c23bfb7146102655780635c60da1b14610260578063761f8acb1461025b5780637a5b4f59146102565780637e3f1353146102515780638cb750591461024c578063bb225da214610247578063bfde57c314610242578063c218c1321461023d578063c7f758a814610238578063c98425ee14610233578063c9c4bfca1461022e578063cc63604a14610229578063ce1b815f14610224578063da35c6641461021f578063da7422281461021a578063dd63c06f14610215578063e306bee714610210578063ea65ab821461020b578063ee57e36f14610206578063ef8cccb014610201578063fd8d2d36146101fc578063fdbd7eb3146101f75763fe0d94c1146101f2575f80fd5b61225b565b6121ca565b6121a3565b611fda565b611d67565b611cd8565b611c9e565b611c84565b611b71565b611b52565b611b25565b611b07565b611acd565b611a9c565b611956565b61179d565b611719565b611606565b6115cc565b61159b565b6114ad565b611464565b611430565b6113fd565b6113be565b6112fb565b6112bc565b611159565b6110f2565b6110d8565b6110a6565b610fa4565b610f75565b610ede565b610d66565b610cbd565b6107e9565b61077c565b610713565b61068c565b61060b565b61041b565b346103ba5760203660031901126103ba5760043563ffffffff60e01b81168091036103ba576103279063041de68360e41b81149081156103aa575b8115610399575b8115610388575b811561032b575b5060405190151581529081906020820190565b0390f35b634a06561b60e11b811491508115610345575b505f610314565b63368d719960e21b811491508115610377575b8115610366575b505f61033e565b6301ffc9a760e01b1490505f61035f565b633f4644d160e21b81149150610358565b63afc5b82360e01b8114915061030d565b6352d1902d60e01b81149150610306565b621574e360e91b811491506102ff565b5f80fd5b9181601f840112156103ba578235916001600160401b0383116103ba57602083818601950101116103ba57565b9181601f840112156103ba578235916001600160401b0383116103ba576020808501948460051b0101116103ba57565b346103ba5760603660031901126103ba576004356024356001600160401b0381116103ba5761044e9036906004016103be565b91604435926001600160401b0384116103ba576104726104e59436906004016103eb565b60fb549091906104a0906001600160a01b031661048d613d87565b90610496613dc9565b9290913090613e0c565b6104b3845f5261016260205260405f2090565b6001906104c160098761420e565b6104fd82546104f86104d88261ffff9060c01c1690565b9b8c9260d01c61ffff1690565b61ffff165f5261016360205260405f2090565b61239b565b509081541515806105f7575b6105cc5750600101546105249060e81c60ff161590565b1590565b6105af576002016105348161242e565b5f5b848110610593575050509161058e61ffff927fc1d7dc1770290440bd536be5eca85bc1e54960c21ef0f9a838033941a7392d8d94610572613d87565b6040516001600160a01b03909116999095169785949085612726565b0390a4005b806105a96105a3859388886124e1565b8461266b565b01610536565b638b32333560e01b5f52600486905261ffff881660245260445b5ffd5b600881896105dc6105c994610f66565b632c2eee6560e11b5f5260045260ff16602452604452606490565b5061060181610f66565b6003811415610509565b346103ba575f3660031901126103ba57602061ffff6101645416604051908152f35b6024359061ffff821682036103ba57565b359061ffff821682036103ba57565b6001600160a01b038116036103ba57565b60609060031901126103ba576004359060243561ffff811681036103ba57906044356106898161064d565b90565b346103ba5760206106d56106c06106a23661065e565b92915f5261015f855260405f209061ffff165f5260205260405f2090565b9060018060a01b03165f5260205260405f2090565b54604051908152f35b805180835260209291819084018484015e5f828201840152601f01601f1916010190565b9060206106899281815201906106de565b346103ba5760603660031901126103ba5760043561075361073261062d565b604435925f5261016160205260405f209061ffff165f5260205260405f2090565b905f5260205261032761076860405f20612834565b6040519182916020835260208301906106de565b346103ba575f3660031901126103ba57606060405161079b82826109f6565b3690376040516107aa81610968565b60018152600460208201525f604082015260405190815f905b600382106107d057606084f35b60208060019260ff8651168152019301910190916107c3565b346103ba5760203660031901126103ba576004356001600160401b0381116103ba576108199036906004016103eb565b60fb546001600160a01b031661082d613d87565b610885602061083a613dc9565b604051637ef7c88360e11b81526001600160a01b03909616959384928392907f6f36f8bf0398781285f5a40c489dbf3268ce3e205aba87f21e49e6805391b5a1883060048701613721565b0381865afa90811561094f575f91610920575b50156108cb57505080156108bc576108ba916108b5913691612989565b614365565b005b63d345a56b60e01b5f5260045ffd5b604051630cb6f8ed60e21b815260048101929092523060248301526001600160a01b031660448201527f6f36f8bf0398781285f5a40c489dbf3268ce3e205aba87f21e49e6805391b5a1606482015260849150fd5b610942915060203d602011610948575b61093a81836109f6565b81019061370c565b5f610898565b503d610930565b613752565b634e487b7160e01b5f52604160045260245ffd5b606081019081106001600160401b0382111761098357604052565b610954565b61012081019081106001600160401b0382111761098357604052565b61010081019081106001600160401b0382111761098357604052565b608081019081106001600160401b0382111761098357604052565b604081019081106001600160401b0382111761098357604052565b90601f801991011681019081106001600160401b0382111761098357604052565b60405190610a27610100836109f6565b565b60405190610a276060836109f6565b6001600160401b03811161098357601f01601f191660200190565b929192610a5f82610a38565b91610a6d60405193846109f6565b8294818452818301116103ba578281602093845f960137010152565b9080601f830112156103ba5781602061068993359101610a53565b6001600160401b0381116109835760051b60200190565b9080601f830112156103ba57813591610ad383610aa4565b92610ae160405194856109f6565b80845260208085019160051b830101918383116103ba5760208101915b838310610b0d57505050505090565b82356001600160401b0381116103ba578201906060828703601f1901126103ba5760405190610b3b82610968565b6020830135610b498161064d565b8252604083013560208301526060830135916001600160401b0383116103ba57610b7b88602080969581960101610a89565b6040820152815201920191610afe565b606435906001600160401b03821682036103ba57565b604435906001600160401b03821682036103ba57565b35906001600160401b03821682036103ba57565b81601f820112156103ba57803590610be282610aa4565b92610bf060405194856109f6565b82845260208085019360051b830101918183116103ba5760208101935b838510610c1c57505050505090565b84356001600160401b0381116103ba57820183603f820112156103ba576020810135610c4781610aa4565b91610c5560405193846109f6565b8183526020808085019360051b83010101918683116103ba5760408201905b838210610c8e575050509082525060209485019401610c0d565b81356001600160401b0381116103ba57602091610cb28a8480809589010101610a89565b815201910190610c74565b346103ba5760a03660031901126103ba576004356001600160401b0381116103ba57610ced903690600401610a89565b6024356001600160401b0381116103ba57610d0c903690600401610abb565b90604435906001600160801b03821682036103ba57610d29610b8b565b608435926001600160401b0384116103ba5761032794610d50610d56953690600401610bcb565b93612a94565b6040519081529081906020820190565b346103ba5760203660031901126103ba57600435610d838161064d565b610dda7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316610dbc30821415613390565b5f516020615ae55f395f51905f52546001600160a01b0316146133f1565b60fb54610e05906001600160a01b0316610df2613d87565b90610dfb613dc9565b9290913090613ef6565b610e0d613452565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff1615610e4157506108ba90615882565b6040516352d1902d60e01b8152906020826004816001600160a01b0387165afa5f9281610ead575b50610e8b5760405162461bcd60e51b815280610e8760048201614e8d565b0390fd5b6108ba92610ea85f516020615ae55f395f51905f525f9414614e2f565b6157c4565b610ed091935060203d602011610ed7575b610ec881836109f6565b810190614895565b915f610e69565b503d610ebe565b346103ba575f3660031901126103ba57610327604051610eff6060826109f6565b602c81527f2862797465735b5d5b5d20737562426f64696573437573746f6d50726f706f7360208201526b616c506172616d734142492960a01b60408201526040519182916020835260208301906106de565b634e487b7160e01b5f52602160045260245ffd5b60051115610f7057565b610f52565b346103ba5760203660031901126103ba57610f9160043561348d565b6040516005821015610f70576020918152f35b346103ba5760203660031901126103ba576104e560043560fb54610fe6906001600160a01b0316610fd3613d87565b90610fdc613dc9565b9290913090613fe0565b5f81815261016260205260409020610fff60098361420e565b50611038610520600161102c84546104f861101f8261ffff9060c01c1690565b98899260d01c61ffff1690565b50015460e01c60ff1690565b61108a57805460ff60e81b1916600160e81b17905561ffff6001600160a01b03611060613d87565b169216907f578c7050405154b6a8167f305908011ff85e3231eff1fbce2bbe95500b92f2035f80a4005b638b9b77af60e01b5f52600482905261ffff831660245260445ffd5b346103ba575f3660031901126103ba5760fb546040516001600160a01b039091168152602090f35b60031115610f7057565b346103ba575f3660031901126103ba5760206040515f8152f35b346103ba5760403660031901126103ba5760043561110e61062d565b5f828152610162602052604090205460801c6001600160401b0316156111465761113a90604092614f28565b82519182526020820152f35b50630853c2a360e41b5f5260045260245ffd5b60403660031901126103ba576004356111718161064d565b6024356001600160401b0381116103ba57611190903690600401610a89565b6111c97f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316610dbc30821415613390565b60fb546111e1906001600160a01b0316610df2613d87565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff161561121557506108ba90615882565b6040516352d1902d60e01b8152906020826004816001600160a01b0387165afa5f9281611279575b5061125b5760405162461bcd60e51b815280610e8760048201614e8d565b6108ba92610ea85f516020615ae55f395f51905f5260019414614e2f565b61129391935060203d602011610ed757610ec881836109f6565b915f61123d565b359060038210156103ba57565b801515036103ba57565b3590610a27826112a7565b346103ba5760803660031901126103ba576004356112d861062d565b9060443560038110156103ba576108ba92606435926112f6846112a7565b6135ed565b346103ba575f3660031901126103ba577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03163003611353576040515f516020615ae55f395f51905f528152602090f35b60405162461bcd60e51b815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c60448201527f6c6564207468726f7567682064656c656761746563616c6c00000000000000006064820152608490fd5b346103ba5760203660031901126103ba5760206004356113dd8161064d565b610164546040516001600160a01b0392831660109290921c909216148152f35b346103ba5760203660031901126103ba5761141960043561348d565b6005811015610f7057602090600360405191148152f35b346103ba575f3660031901126103ba575f516020615ae55f395f51905f52546040516001600160a01b039091168152602090f35b346103ba57602060ff61149a6106c061147c3661065e565b92915f52610160865260405f209061ffff165f5260205260405f2090565b5416604051906114a9816110ce565b8152f35b346103ba575f3660031901126103ba576040515f5f516020615ac55f395f51905f52546114d9816123cd565b8084529060018116908115611577575060011461150d575b61032783611501818503826109f6565b60405191829182610702565b5f516020615ac55f395f51905f525f9081527f20120d26379ad35b0c68e58a20f1251f24acf3aee87d3a8d8759c48671c8cace939250905b80821061155d575090915081016020016115016114f1565b919260018160209254838588010152019101909291611545565b60ff191660208086019190915291151560051b8401909101915061150190506114f1565b346103ba5760203660031901126103ba5760206115c26004356115bd8161064d565b61375d565b6040519015158152f35b346103ba575f3660031901126103ba5760206040517f568cc693d84eb1901f8bcecba154cbdef23ca3cf67efc0a0b698528a06c660f78152f35b346103ba5760403660031901126103ba5760fb546001600160a01b031661162b613d87565b906116786020611639613dc9565b604051637ef7c88360e11b81529384928392907f568cc693d84eb1901f8bcecba154cbdef23ca3cf67efc0a0b698528a06c660f7893060048701613721565b0381855afa90811561094f575f916116fa575b50156116a4576108ba61169f366004613809565b6152d7565b604051630cb6f8ed60e21b815260048101919091523060248201526001600160a01b0390911660448201527f568cc693d84eb1901f8bcecba154cbdef23ca3cf67efc0a0b698528a06c660f76064820152608490fd5b611713915060203d6020116109485761093a81836109f6565b5f61168b565b346103ba5760c03660031901126103ba576004356117368161064d565b602435906117438261064d565b6044356001600160401b0381116103ba576117629036906004016103eb565b906064356001600160401b0381116103ba576117829036906004016103be565b92909160403660831901126103ba576108ba956084956138a7565b346103ba5760203660031901126103ba57600435805f526101626020526117d06117ca60405f209261348d565b91615139565b90816117e5575b506040519015158152602090f35b90506005811015610f705760038114908115611803575b505f6117d7565b60029150145f6117fc565b9080602083519182815201916020808360051b8301019401925f915b83831061183957505050505090565b9091929394602080611879600193601f19868203018752606060408b51878060a01b038151168452858101518685015201519181604082015201906106de565b9701930193019193929061182a565b60021115610f7057565b80516001600160a01b0316825260200151906002821015610f705760200152565b61068990602081526118d16020820184516001600160801b03169052565b60208301516001600160401b03166040820152604083015161ffff166060820152606083015161ffff1660808201526080830151151560a082015260a0830151151560c082015260c08301516001600160a01b031660e082015261012061010061194b60e08601516101408386015261016085019061180e565b940151910190611892565b346103ba5760203660031901126103ba5760043560405161197681610988565b5f81525f60208201525f60408201525f60608201525f60808201525f60a08201525f60c0820152606060e08201526101006119af613a0e565b9101525f5261016260205261032760405f20611a7a6003604051926119d384610988565b611a50611a4782546119fb6119ee826001600160801b031690565b6001600160801b03168852565b6001600160401b03608082901c16602088015261ffff60c082901c16604088015261ffff60d082901c166060880152611a3e60e082901c60ff1615156080890152565b60e81c60ff1690565b151560a0860152565b60018101546001600160a01b031660c0850152611a6f60028201613a26565b60e085015201613adf565b610100820152604051918291826118b3565b604081019291610a279190611892565b346103ba575f3660031901126103ba57611ab4613a0e565b506040611abf613aaf565b611acb82518092611892565bf35b346103ba575f3660031901126103ba5760206040517f821b6e3a557148015a918c89e5d092e878a69854a2d1a410635f771bd5a8a3f58152f35b346103ba5760203660031901126103ba5760206115c2600435613b0c565b346103ba575f3660031901126103ba576101645460405160109190911c6001600160a01b03168152602090f35b346103ba575f3660031901126103ba57631bebc11560e01b5f5260045ffd5b346103ba5760203660031901126103ba57600435611b8e8161064d565b60fb546001600160a01b0316611ba2613d87565b611bee6020611baf613dc9565b604051637ef7c88360e11b81529384928392907f06d294bc8cbad2e393408b20dd019a772661f60b8d633e56761157cb1ec85f8c883060048701613721565b0381865afa90811561094f575f91611c65575b5015611c10576108ba8361543b565b604051630cb6f8ed60e21b815260048101929092523060248301526001600160a01b031660448201527f06d294bc8cbad2e393408b20dd019a772661f60b8d633e56761157cb1ec85f8c606482015260849150fd5b611c7e915060203d6020116109485761093a81836109f6565b5f611c01565b346103ba575f3660031901126103ba576040611abf613b42565b346103ba575f3660031901126103ba5760206040517f4707e94b25cfce1a7c363508fbb838c35864388ad77284b248282b9746982b9b8152f35b346103ba5760a03660031901126103ba576004356001600160401b0381116103ba57611d08903690600401610a89565b6024356001600160401b0381116103ba57611d27903690600401610abb565b90611d30610ba1565b90611d39610b8b565b50608435916001600160401b0383116103ba5761032793611d61610d56943690600401610a89565b92613c43565b346103ba5760203660031901126103ba576004356001600160401b0381116103ba57611d979036906004016103be565b60fb546001600160a01b0316611dab613d87565b611df76020611db8613dc9565b604051637ef7c88360e11b81529384928392907f4707e94b25cfce1a7c363508fbb838c35864388ad77284b248282b9746982b9b883060048701613721565b0381865afa90811561094f575f91611e78575b5015611e23576108ba611e1e368587610a53565b61548e565b604051630cb6f8ed60e21b815260048101929092523060248301526001600160a01b031660448201527f4707e94b25cfce1a7c363508fbb838c35864388ad77284b248282b9746982b9b606482015260849150fd5b611e91915060203d6020116109485761093a81836109f6565b5f611e0a565b602081016020825282518091526040820191602060408360051b8301019401925f915b838310611ec957505050505090565b9091929394603f1982820301835285519061010081019180519261010083528351809152602061012084019401905f905b808210611f9057505050600192611f8160209360e08085611f2a8880980151888601906001600160401b03169052565b6040818101516001600160401b0316908501526060818101516001600160401b03169085015260808181015161ffff169085015260a08181015161ffff169085015260c08181015115159085015201511515910152565b97019301930191939290611eba565b9091946020608060019260608951858060a01b038151168352848101511515858401526040810151151560408401520151611fca816110ce565b6060820152019601920190611efa565b346103ba5760203660031901126103ba5760043561ffff61016454168111801561219b575b6108bc575f5261016360205260405f20805461201a81610aa4565b9161202860405193846109f6565b81835260208301905f5260205f205f915b83831061204e57604051806103278782611e97565b60405161205a816109a4565b825461206581610aa4565b9061207360405192836109f6565b80825260208201855f5260205f20905f905b8382106121425750505050600192826020926002945261213461212b868801546120c76120b8826001600160401b031690565b6001600160401b031685880152565b6120e8604082901c6001600160401b03166001600160401b03166040860152565b6001600160401b03608082901c16606085015261ffff60c082901c16608085015261ffff60d082901c1660a0850152611a3e60e082901c60ff16151560c0860152565b151560e0830152565b815201920192019190612039565b600160208192604051612154816109c0565b60ff8754858060a01b0381168352818160a01c16151585840152818160a81c161515604084015260b01c16612188816110ce565b6060820152815201930191019091612085565b508015611fff565b346103ba5760203660031901126103ba5760206115c26004356121c58161064d565b613cfb565b346103ba5760203660031901126103ba57600435805f5261016260205260405f206121f4826141c7565b506122006117ca613d87565b156122305761220e81613cfb565b1561221c576108ba91615166565b639fefd0f160e01b5f52600482905260245ffd5b6122398161375d565b15612247576108ba91615166565b637171293960e11b5f52600482905260245ffd5b346103ba5760203660031901126103ba5760fb54600435906001600160a01b0316612284613d87565b6122d06020612291613dc9565b604051637ef7c88360e11b81529384928392907ff281525e53675515a6ba7cc7bea8a81e649b3608423ee2d73be1752cea887889883060048701613721565b0381865afa90811561094f575f91612368575b501561231357826122f381613b0c565b15612301576108ba906155f7565b639fefd0f160e01b5f5260045260245ffd5b604051630cb6f8ed60e21b815260048101929092523060248301526001600160a01b031660448201527ff281525e53675515a6ba7cc7bea8a81e649b3608423ee2d73be1752cea887889606482015260849150fd5b612381915060203d6020116109485761093a81836109f6565b5f6122e3565b634e487b7160e01b5f52603260045260245ffd5b80548210156123b4575f5260205f209060011b01905f90565b612387565b634e487b7160e01b5f52601160045260245ffd5b90600182811c921680156123fb575b60208310146123e757565b634e487b7160e01b5f52602260045260245ffd5b91607f16916123dc565b818110612410575050565b5f8155600101612405565b634e487b7160e01b5f525f60045260245ffd5b8054905f81558161243d575050565b816003029160038304036124dc575f5260205f20908101905b818110612461575050565b805f600392555f60018201556002810161247b81546123cd565b908161248a575b505001612456565b601f82116001146124a1575f9055505b5f80612482565b6124c76124d7926001601f6124b9855f5260205f2090565b920160051c82019101612405565b5f81815260208120918190559055565b61249a565b6123b9565b91908110156123b45760051b81013590605e19813603018212156103ba570190565b80548210156123b4575f52600360205f20910201905f90565b90601f8211612529575050565b610a27915f516020615ac55f395f51905f525f5260205f20906020601f840160051c83019310612561575b601f0160051c0190612405565b9091508190612554565b9190601f811161257a57505050565b610a27925f5260205f20906020601f840160051c8301931061256157601f0160051c0190612405565b9092916001600160401b038111610983576125c8816125c284546123cd565b8461256b565b5f601f82116001146126065781906125f79394955f926125fb575b50508160011b915f199060031b1c19161790565b9055565b013590505f806125e3565b601f19821694612619845f5260205f2090565b915f5b87811061265357508360019596971061263a575b505050811b019055565b01355f19600384901b60f8161c191690555f8080612630565b9092602060018192868601358155019401910161261c565b8054600160401b8110156109835761268891600182018155612503565b919091612701576126b9813561269d8161064d565b83546001600160a01b0319166001600160a01b03909116178355565b60208101356001830155604081013590601e19813603018212156103ba57018035906001600160401b0382116103ba5760200181360381136103ba576002610a2793016125a3565b61241b565b908060209392818452848401375f828201840152601f01601f1916010190565b93919061273b91604086526040860191612706565b9260208185039101528083526020830160208260051b85010193835f91605e1982360301905b858410612772575050505050505090565b90919293949596601f198282030186528735838112156103ba57840180356127998161064d565b6001600160a01b0316825260208181013590830152604081013536829003601e19018112156103ba5701602081359101906001600160401b0381116103ba5780360382136103ba576127fb602092839260608681604060019901520191612706565b99019796019401929190612761565b61283092916106c0915f5261015f60205260405f209061ffff165f5260205260405f2090565b5490565b9060405191825f825492612847846123cd565b80845293600181169081156128b0575060011461286c575b50610a27925003836109f6565b90505f9291925260205f20905f915b818310612894575050906020610a27928201015f61285f565b602091935080600191548385890101520191019091849261287b565b905060209250610a2794915060ff191682840152151560051b8201015f61285f565b81601f820112156103ba578035906128e982610aa4565b926128f760405194856109f6565b82845260208085019360071b830101918183116103ba57602001925b828410612921575050505090565b6080848303126103ba57602060809160405161293c816109c0565b86356129478161064d565b815282870135612956816112a7565b838201526040870135612968816112a7565b60408201526129796060880161129a565b6060820152815201930192612913565b9291909261299684610aa4565b936129a460405195866109f6565b602085828152019060051b8201918383116103ba5780915b8383106129ca575050505050565b82356001600160401b0381116103ba57820190610100828703126103ba576129f0610a17565b908235916001600160401b0383116103ba57612a8460e085612a188b602098978998016128d2565b8452612a25868201610bb7565b86850152612a3560408201610bb7565b6040850152612a4660608201610bb7565b6060850152612a576080820161063e565b6080850152612a6860a0820161063e565b60a0850152612a7960c082016112b1565b60c0850152016112b1565b60e08201528152019201916129bc565b909293949194612ac360018060a01b0360fb5416612ab0613d87565b90612ab9613dc9565b92909130906140ca565b84612ad26101645461ffff1690565b9261ffff8416156108bc57612ae5613d87565b96612b1787604051612b0f81612b018d8860208401968761302d565b03601f1981018352826109f6565b51902061475e565b92612b2b845f5261016260205260405f2090565b95612b43876001600160401b03905460801c16151590565b612dbe5786546001600160801b0319166001600160801b038c16178755612bb190612b78612b6f613b42565b60038a016130b2565b6001880180546001600160a01b0319166001600160a01b038d16179055875461ffff60d01b191660d09190911b61ffff60d01b16178755565b6001600160401b03811680612d8757505050612bfc6001600160401b0342169897985b855467ffffffffffffffff60801b191660809190911b67ffffffffffffffff60801b16178555565b60028401975f5b8751811015612c295780612c23612c1c6001938b613104565b518c6131d7565b01612c03565b50919497509194929561ffff865111612d785796929095916001965b8651881015612cd4575f5b612c5a8989613104565b5151811015612cc85780612cc288612cbd83612cb08e61ffff8f612c8d60019a612c8785612c9e94613104565b51613104565b51965f5261016160205260405f2090565b911661ffff165f5260205260405f2090565b905f5260205260405f2090565b613118565b01612c50565b50600190970196612c45565b919585975097612d49612d639294612d397fa6c1f8f4276dc3f243459e13b557c84e8f4e90b2e09070bad5f6909cee687c92979b612d1d83546001600160401b039060801c1690565b815190919015612d6957612d30906130f7565b51905b8a6148a4565b5460801c6001600160401b031690565b6040516001600160a01b0390941697939485949185613342565b0390a390565b50612d726132c6565b90612d33565b638d48ed3360e01b5f5260045ffd5b6001600160401b03421611612da35750612bfc90989798612bd4565b636f6a0b6560e11b5f526001600160401b031660045260245ffd5b6312dba68f60e01b5f52600485905260245ffd5b92939091612dec60018060a01b0360fb5416612ab0613d87565b8094612dfc6101645461ffff1690565b9161ffff8316156108bc57612e0f613d87565b96612e2b6040516020810190612b0f81612b018d8d8d8761302d565b91612e3f835f5261016260205260405f2090565b94612e57866001600160401b03905460801c16151590565b6130195785546001600160801b0319168655612eba90612e81612e78613b42565b600389016130b2565b6001870180546001600160a01b0319166001600160a01b038d16179055865461ffff60d01b191660d09190911b61ffff60d01b16178655565b6001600160401b03811680612ffd57505050612f056001600160401b0342169796975b845467ffffffffffffffff60801b191660809190911b67ffffffffffffffff60801b16178455565b60028301965f5b8651811015612f325780612f2c612f256001938a613104565b518b6131d7565b01612f0c565b50919492959093965061ffff855111612d78579591600195915b8551871015612fa0575f5b612f618888613104565b5151811015612f945780612f8e87612cbd83612cb08d61ffff612c9e8f60019a612c8785612c8d93613104565b01612f57565b50600190960195612f4c565b918496505f612d49612d6392612d397fa6c1f8f4276dc3f243459e13b557c84e8f4e90b2e09070bad5f6909cee687c92979b9599612fe983546001600160401b039060801c1690565b90805115158614612d6957612d30906130f7565b6001600160401b03421611612da35750612f0590979697612edd565b6312dba68f60e01b5f52600484905260245ffd5b916130579061304960409396959660608652606086019061180e565b9084820360208601526106de565b6001600160a01b03909416910152565b60209060018060a01b038151166001600160601b0360a01b61012d54161761012d5501516002811015610f705761012d5460ff60a01b191660a09190911b60ff60a01b161761012d55565b815181546001600160a01b0319166001600160a01b039190911617815590602001516002811015610f7057815460ff60a01b191660a09190911b60ff60a01b16179055565b8051156123b45760200190565b80518210156123b45760209160051b010190565b91909182516001600160401b03811161098357613139816125c284546123cd565b6020601f82116001146131735781906125f79394955f926131685750508160011b915f199060031b1c19161790565b015190505f806125e3565b601f19821690613186845f5260205f2090565b915f5b8181106131bf575095836001959697106131a757505050811b019055565b01515f1960f88460031b161c191690555f8080612630565b9192602060018192868b015181550194019201613189565b9190918054600160401b811015610983576131f791600182018155612503565b61270157825181546001600160a01b0319166001600160a01b039190911617815560409060029060208501516001820155019201519182516001600160401b0381116109835761324b816125c284546123cd565b6020601f821160011461327a5781906125f79394955f926131685750508160011b915f199060031b1c19161790565b601f1982169061328d845f5260205f2090565b915f5b8181106132ae575095836001959697106131a757505050811b019055565b9192602060018192868b015181550194019201613290565b604051906132d56020836109f6565b5f80835282815b8281106132e857505050565b8060606020809385010152016132dc565b9061330382610aa4565b61331060405191826109f6565b8281528092613321601f1991610aa4565b01905f5b82811061333157505050565b806060602080938501015201613325565b926133899061337b6080946001600160401b036001600160801b03959998991687525f602088015260a0604088015260a08701906106de565b90858203606087015261180e565b9416910152565b1561339757565b60405162461bcd60e51b815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201526b19195b1959d85d1958d85b1b60a21b6064820152608490fd5b156133f857565b60405162461bcd60e51b815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201526b6163746976652070726f787960a01b6064820152608490fd5b604051906134616020836109f6565b5f808352366020840137565b906001600160401b03809116911601906001600160401b0382116124dc57565b6134a0815f5261016260205260405f2090565b80549060e082901c60ff166135e55760e882901c60ff166135dd575460801c6001600160401b0316156135c9576134de60d082901c61ffff166104e5565b9160016135086134f760c085901c61ffff16809661239b565b509360801c6001600160401b031690565b9201549261351f6001600160401b0385168461346d565b6001600160401b03429116106135c0574261355761354b604087901c6001600160401b03165b8661346d565b6001600160401b031690565b116135b85760d084901c61ffff16928361358b575b5061357e9360c01c61ffff1691614edc565b613586575f90565b600390565b6135ad61354b42926135a7886001600160401b039060801c1690565b9061346d565b116135b8575f61356c565b505050505f90565b50505050600490565b630853c2a360e41b5f52600482905260245ffd5b505050600190565b505050600290565b92613601845f5261016260205260405f2090565b9161361c610520846001600160401b03905460801c16151590565b6136cb57825460c01c61ffff1661ffff811661ffff8316116136af575061364e90613645613d87565b948591876150c5565b156136aa5761365c90615139565b1561369c5761366a81613cfb565b80613681575b613678575050565b610a2791615166565b50600361368d8361348d565b61369681610f66565b14613670565b6136a58161375d565b61366a565b505050565b63d0a90c2d60e01b5f5261ffff9081166004521660245260445ffd5b630853c2a360e41b5f52600485905260245ffd5b916106c06137079260ff945f5261016060205260405f209061ffff165f5260205260405f2090565b541690565b908160209103126103ba5751610689816112a7565b6001600160a01b03918216815291166020820152604081019190915260806060820181905261068993910191612706565b6040513d5f823e3d90fd5b60fb546137db916020916001600160a01b0316613778613dc9565b604051637ef7c88360e11b81523060048201526001600160a01b0390941660248501527fb014ce248804cab6a144581acce1eeb70ce5d54f08433b989d73bb0ccee3d3f96044850152608060648501529294859384928392916084840191612706565b03915afa90811561094f575f916137f0575090565b610689915060203d6020116109485761093a81836109f6565b91908260409103126103ba57604051613821816109db565b6020819380356138308161064d565b835201359060028210156103ba5760200152565b1561384b57565b60405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608490fd5b9593916138ef9593915f54976138d560ff8a60081c16151515809a8161396e575b811561394e575b50613844565b886138e6600160ff195f5416175f55565b6139375761397c565b6138f557565b61390361ff00195f54165f55565b604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989080602081015b0390a1565b61394961010061ff00195f5416175f55565b61397c565b303b15915081613960575b505f6138cf565b60ff1660011490505f613959565b600160ff82161091506138c8565b94610a27969491611e1e936139e29561169f986139a860ff5f5460081c166139a3816153db565b6153db565b60018060a01b03166001600160601b0360a01b60fb54161760fb55806139f8575b50506001600160a01b0381166139e9575b503691610a53565b3690613809565b6139f29061543b565b5f6139da565b613a07916108b5913691612989565b5f806139c9565b60405190613a1b826109db565b5f6020838281520152565b908154613a3281610aa4565b92613a4060405194856109f6565b81845260208401905f5260205f205f915b838310613a5e5750505050565b60036020600192604051613a7181610968565b848060a01b0386541681528486015483820152613a9060028701612834565b6040820152815201920192019190613a51565b6002821015610f705752565b60405190613abc826109db565b61012d546001600160a01b0381168352610a279060a01c60ff1660208401613aa3565b90610a27604051613aef816109db565b92546001600160a01b038116845260a01c60ff1660208401613aa3565b805f52610162602052613b2260405f209161348d565b6005811015610f70576003149081613b38575090565b6106899150615139565b613b4a613a0e565b50613b53613aaf565b80516001600160a01b031615613b665790565b5060fb54604051906001600160a01b0316613b80826109db565b81525f602082015290565b9080601f830112156103ba57815191613ba383610aa4565b92613bb160405194856109f6565b80845260208085019160051b830101918383116103ba5760208101915b838310613bdd57505050505090565b82516001600160401b0381116103ba57820185603f820112156103ba57602081015191613c0983610a38565b613c1660405191826109f6565b83815260408385010188106103ba575f602085819660408397018386015e83010152815201920191613bce565b919093929384518501946020818188019703126103ba576020810151906001600160401b0382116103ba57019285603f850112156103ba576020840151613c8981610aa4565b94613c9760405196876109f6565b8186526020808088019360051b83010101918883116103ba5760408201905b838210613ccc5750505050610689949550612dd2565b81516001600160401b0381116103ba57602091613cf08c8480809589010101613b8b565b815201910190613cb6565b60fb546137db916020916001600160a01b0316613d16613dc9565b604051637ef7c88360e11b81523060048201526001600160a01b0390941660248501527ff281525e53675515a6ba7cc7bea8a81e649b3608423ee2d73be1752cea8878896044850152608060648501529294859384928392916084840191612706565b5f198101919082116124dc57565b610164543360109190911c6001600160a01b03161480613dbe575b15613dba5760131936013681116124dc573560601c90565b3390565b506014361015613da2565b610164543360109190911c6001600160a01b03161480613e01575b15613dfb576013193601903682116124dc575f9190565b5f903690565b506014361015613de4565b604051637ef7c88360e11b81526001600160a01b039091169492939192909160209183918291613e62917fa73a22e0fc9b71a5463a75c9711d02d08dae26e85aa1033f4416b719a0239107898960048701613721565b0381875afa90811561094f575f91613ed7575b5015613e8057505050565b604051630cb6f8ed60e21b815260048101939093526001600160a01b0390811660248401521660448201527fa73a22e0fc9b71a5463a75c9711d02d08dae26e85aa1033f4416b719a0239107606482015260849150fd5b613ef0915060203d6020116109485761093a81836109f6565b5f613e75565b604051637ef7c88360e11b81526001600160a01b039091169492939192909160209183918291613f4c917f821b6e3a557148015a918c89e5d092e878a69854a2d1a410635f771bd5a8a3f5898960048701613721565b0381875afa90811561094f575f91613fc1575b5015613f6a57505050565b604051630cb6f8ed60e21b815260048101939093526001600160a01b0390811660248401521660448201527f821b6e3a557148015a918c89e5d092e878a69854a2d1a410635f771bd5a8a3f5606482015260849150fd5b613fda915060203d6020116109485761093a81836109f6565b5f613f5f565b604051637ef7c88360e11b81526001600160a01b039091169492939192909160209183918291614036917fbdfef02014e2b7a6c80226083f80d72d22fcf656d917f92d242c5b61e108bcd3898960048701613721565b0381875afa90811561094f575f916140ab575b501561405457505050565b604051630cb6f8ed60e21b815260048101939093526001600160a01b0390811660248401521660448201527fbdfef02014e2b7a6c80226083f80d72d22fcf656d917f92d242c5b61e108bcd3606482015260849150fd5b6140c4915060203d6020116109485761093a81836109f6565b5f614049565b604051637ef7c88360e11b81526001600160a01b039091169492939192909160209183918291614120917f8c433a4cd6b51969eca37f974940894297b9fcf4b282a213fea5cd8f85289c90898960048701613721565b0381875afa90811561094f575f91614195575b501561413e57505050565b604051630cb6f8ed60e21b815260048101939093526001600160a01b0390811660248401521660448201527f8c433a4cd6b51969eca37f974940894297b9fcf4b282a213fea5cd8f85289c90606482015260849150fd5b6141ae915060203d6020116109485761093a81836109f6565b5f614133565b6005811015610f705760ff600191161b90565b6141d08161348d565b9060086141dc836141b4565b16156141e6575090565b906005811015610f705760ff91632c2eee6560e11b5f5260045216602452600860445260645ffd5b906142188261348d565b9181614223846141b4565b161561422e57505090565b826005811015610f705760ff91632c2eee6560e11b5f526004521660245260445260645ffd5b61ffff1661ffff81146124dc5760010190565b8054600160401b811015610983576142849160018201815561239b565b9091565b90600182018092116124dc57565b51610689816110ce565b80548210156123b4575f5260205f2001905f90565b8054600160401b811015610983576142d2916001820181556142a0565b91909161270157805182546001600160a01b0319166001600160a01b03919091161782556020810151825460ff60a01b191690151560a01b60ff60a01b1617604082015160ff60a81b90151560a81b1660ff60a81b19821681178455606090920151909190614340816110ce565b614349816110ce565b61ffff60a81b199092161760b09190911b60ff60b01b16179055565b61439661437e6143796101645461ffff1690565b614254565b6104e58161ffff1661ffff1961016454161761016455565b5f915b805183101561472a576143ab82614267565b50936143b78483613104565b5151916143d860206143c98784613104565b5101516001600160401b031690565b6143e760406143c98885613104565b916143f760606143c98984613104565b9361441160806144078a85613104565b51015161ffff1690565b61442060a06144078b86613104565b916001600160401b038516806001600160401b0388161090811591614716575b506147075787518061ffff8416119081156146f9575b506146ea575f985b88518a10156145bd576144708a614288565b89518110156144fc57896144b26144a6614492848f6144926144a09187613104565b51516001600160a01b031690565b94613104565b6001600160a01b031690565b6001600160a01b03909116146144ca57600101614470565b6105c98c6144db6144928e8e613104565b635169d4b960e11b5f526004919091526001600160a01b0316602452604490565b50986145186105206020614510848d613104565b510151151590565b8061459f575b614590576145386060614531838c613104565b5101614296565b614541816110ce565b15614565578061455e8d6145576001948d613104565b51906142b5565b019861445e565b6145756144926105c9928b613104565b63385ccd4360e11b5f526001600160a01b0316600452602490565b632c7ca6d760e01b5f5260045ffd5b506145b86105206145b3614492848d613104565b615752565b61451e565b9850989560019750906146556146719261462d6146e2986145fb61468d989f8d01998a906001600160401b03166001600160401b0319825416179055565b88546fffffffffffffffff0000000000000000191660409190911b6fffffffffffffffff000000000000000016178855565b865467ffffffffffffffff60801b191660809190911b67ffffffffffffffff60801b16178655565b845461ffff60c01b191660c09190911b61ffff60c01b16178455565b825461ffff60d01b191660d09190911b61ffff60d01b16178255565b6146b961469f60c0614510868b613104565b825460ff60e01b191690151560e01b60ff60e01b16178255565b6146c860e0614510858a613104565b815460ff60e81b191690151560e81b60ff60e81b16179055565b019192614399565b635813b74160e01b5f5260045ffd5b905061ffff8416115f614456565b631f7b222b60e31b5f5260045ffd5b90506001600160401b03881610155f614440565b7f435d9e99466e98c43eea30339b592c89335a9cd4304822838938882df53308fe9250613932915060405191829182611e97565b604051602081019146835243604083015230606083015260808201526080815261478960a0826109f6565b51902090565b60408051919061479f90836109f6565b6001825281601f196147b16001610aa4565b01905f5b8281106147c157505050565b6020906040516147d081610968565b5f81525f8382015260606040820152828285010152016147b5565b9261ffff606093969592966080860197865216602085015261480c816110ce565b60408401521515910152565b91936001600160401b0361484c61068997959661483e839560a0885260a08801906106de565b90868203602088015261180e565b9516604084015216606082015260808184039101526106de565b3d15614890573d9061487782610a38565b9161488560405193846109f6565b82523d5f602084013e565b606090565b908160209103126103ba575190565b9291906148cf5f6104f86104e56148c4885f5261016260205260405f2090565b5460d01c61ffff1690565b5060018101905f5b8154811015614b8f576148ea81836142a0565b50908154888688876149008560ff9060a01c1690565b614b81575f809492936149f987612b0184976149c36135458798886149568c612b0161492a61478f565b9960ff60b082901c81169160a81c16906040519586946329181cb160e11b6020870152602486016147eb565b61495e610a29565b308152908a60208301526040820152614976876130f7565b52614980866130f7565b50612d396149955a9f6001600160a01b031690565b604080513060208201529081019d909d5261ffff9b909b166060808e01919091528c52999a9960808b6109f6565b908c808251118814614b71576149d891613104565b51905b6040519586946020860199637532d5c160e11b8b5260248701614818565b51925af19289614a07614866565b925a908615614b50575b50508460019590614b45575b15614ad3577fdc04d6b37a483003e6bdc5660d9d9bb22854fffba622b62f658a398efc88ca44614ac9614a5b856020805f9798518301019101614895565b9485614aa4614a8887614a77885f5261015f60205260405f2090565b9061ffff165f5260205260405f2090565b83546001600160a01b03165f9081526020919091526040902090565b555460405195865260a088901b889003166001600160a01b0316949081906020820190565b0390a45b016148d7565b7fe03b818c74400ef42fafb3f6cfa61d8a38950d4f403eee88ec39bc0cafe54d24614b3d5f93614b1c614b16614a8887614a77885f5261015f60205260405f2090565b5f199055565b5460a088901b889003906001600160a01b0316169460405191829182610702565b0390a4614acd565b506020835114614a1d565b60061c119050614b6257895f80614a11565b6307099c5360e21b5f5260045ffd5b5050614b7b613452565b906149db565b505050505060019150614acd565b50505050509050565b939293919091614bbb836104f86104e56148c4855f5261016260205260405f2090565b5060018101905f5b8154811015614e2557614bd681836142a0565b509086825492614bea8460ff9060a01c1690565b614e1a5786614bf761478f565b6040516329181cb160e11b602082015280614c2660ff60a88a901c81169060b08b901c168887602486016147eb565b03601f1981018252614c3890826109f6565b614c40610a29565b308152905f60208301526040820152614c58826130f7565b52614c62816130f7565b508c5a6040805130602082015290810185905261ffff8716606080830191909152815290976001600160a01b031690614c9c6080826109f6565b8a548d9060801c6001600160401b0316614cb59161346d565b928d89808351115f1496612b015f9897899895614cdb948a97614b71576149d891613104565b51925af194614ce8614866565b905a908715614e03575b50508560019690614df8575b15614d845761ffff614d67614d3d836020807fdc04d6b37a483003e6bdc5660d9d9bb22854fffba622b62f658a398efc88ca4496518301019101614895565b9485614d59614a8889614a77895f5261015f60205260405f2090565b55546001600160a01b031690565b60405194855260a088901b88900316941692602090a45b01614bc3565b9161ffff614dd77fe03b818c74400ef42fafb3f6cfa61d8a38950d4f403eee88ec39bc0cafe54d2492614dca614b16614a8889614a77895f5261015f60205260405f2090565b546001600160a01b031690565b614df06040519283928a8060a01b031697169582610702565b0390a4614d7e565b506020815114614cfe565b919450915060061c11614b62578689925f80614cf2565b505060019150614d7e565b5050505050509050565b15614e3657565b60405162461bcd60e51b815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f786044820152681a58589b195555525160ba1b6064820152608490fd5b60809060208152602e60208201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960408201526d6f6e206973206e6f74205555505360901b60608201520190565b90614ee991939293614f28565b90918015159182614f0f575b5050614f095710614f0557600190565b5f90565b50505f90565b101590505f80614ef5565b5f1981146124dc5760010190565b90915f925f92614f4b826104f86104e56148c4855f5261016260205260405f2090565b50918254915f935b838510614f61575050505050565b9091929396614f7088836142a0565b50546001600160a01b03811690614f8882878761280a565b91614f948188886136df565b92614f9e846110ce565b8315614fe25750505080614fb36001926110ce565b03614fcf57614fc3600191614f1a565b975b0193929190614f53565b9695614fdc600191614f1a565b96614fc5565b939a93919250905f19811415806150b6575b615004575b505050600190614fc5565b5f91829160405161502f81612b01602082019463610c609960e11b8652602483019190602083019252565b51915afa61503b614866565b90806150ab575b61504d575b80614ff9565b806020806150609351830101910161370c565b61506b575b80615047565b90979060019060b01c60ff16615080816110ce565b0361509857615090600191614f1a565b975b90615065565b96956150a5600191614f1a565b96615092565b506020815114615042565b5060ff60a084901c1615614ff4565b919261ffff9193835f526101606020526150f2826106c08760405f209061ffff165f5260205260405f2090565b906150fc816110ce565b60ff8019835416911617905560018060a01b03169216907fbfaa970a350cc4e6c21888b5c4b888e2750f035ce824e40cfc7dc5f07e3936c55f80a4565b5461ffff8160d01c165f5261016360205260405f2054905f1982019182116124dc5760c01c61ffff161490565b919061517b835f5261016260205260405f2090565b9283549261519f6151946104e58661ffff9060d01c1690565b9460c01c61ffff1690565b61ffff6151ac8654613d79565b911610156152c95784546151c69060c01c61ffff16614254565b855460c082901b61ffff60c01b1669ffffffffffffffffffff60801b199091161742608081901b67ffffffffffffffff60801b16919091179096556001600160401b03909516949261522261521b858761239b565b50546132f9565b955f5b61522f868861239b565b5054811015615281578560018261526261525d61522f95612cb086614a778d5f5261016160205260405f2090565b612834565b61526c828d613104565b52615277818c613104565b5001915050615225565b5061ffff93949550956152979192968686614b98565b6001600160a01b03169216907fa21690322ce39bce6ee8416aefbe1e66cf767ff37e9db8f708a3c6cbbf17db9b5f80a4565b93509050610a2791506155f7565b80516001600160a01b03166152eb8161596b565b9081615375575b5080615354575b615337576139328161532b7f88e879ae0d71faf3aa708f2978daccb99b95243615dc104835b8c5a21c884ae693613067565b60405191829182611a8c565b60405163266d0fb960e01b8152908190610e879060048301611a8c565b5060208101516002811015610f70578061536f600192611888565b146152f9565b602091505f90604051838101906301ffc9a760e01b8252632a4f53ad60e11b6024820152602481526153a86044826109f6565b5191617530fa5f513d826153cf575b50816153c5575b505f6152f2565b905015155f6153be565b6020111591505f6153b7565b156153e257565b60405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608490fd5b610164805462010000600160b01b031916601083901b62010000600160b01b03161790556001600160a01b03167fa4388ecc389b1390354ae0c65a856c0d7dd4fb648419f5d3ac0b99e38f46fd115f80a2565b908151916001600160401b038311610983576154c0836154bb5f516020615ac55f395f51905f52546123cd565b61251c565b602092601f811160011461553a579061551482613932937fbb39ebb37e60fb5d606ffdb749d2336e56b88e6c88c4bd6513b308f643186eed95965f9161552f575b508160011b915f199060031b1c19161790565b5f516020615ac55f395f51905f525560405191829182610702565b90508301515f615501565b5f516020615ac55f395f51905f525f52601f1981167f20120d26379ad35b0c68e58a20f1251f24acf3aee87d3a8d8759c48671c8cace905f5b8181106155df5750916001917fbb39ebb37e60fb5d606ffdb749d2336e56b88e6c88c4bd6513b308f643186eed9596826139329695106155c7575b5050811b015f516020615ac55f395f51905f5255611501565b8401515f1960f88460031b161c191690555f806155ae565b84870151835560209687019660019093019201615573565b5f81815261016260205260409020805460ff60e01b198116600160e01b178255600382015460a081901c60ff16926001600160a01b03909116916001600160801b03169060019061564a90600201613a26565b9361565481611888565b036156ef57905f92612b01615683859460405192839160208301956331c6fcc960e21b87528a60248501615949565b51915af461568f614866565b90156156d157806020806156a893518301019101615919565b50505b7f712ae1383f79ac853f8d882153778e0260ef8f03b504e2866e0593e04d2b291f5f80a2565b8051156156e057805190602001fd5b6318cecad560e01b5f5260045ffd5b5f9161571393836040518096819582946331c6fcc960e21b84528a60048501615949565b03925af1801561094f575f915f9161572e575b5050506156ab565b905061574c91503d805f833e61574481836109f6565b810190615919565b5f615726565b61575b8161596b565b9081615765575090565b602091505f90604051838101906301ffc9a760e01b8252633f4644d160e21b6024820152602481526157986044826109f6565b5191617530fa5f513d826157b8575b50816157b1575090565b9050151590565b6020111591505f6157a7565b916157ce83615882565b6001600160a01b0383167fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b5f80a28151159081159161587a575b50615811575050565b615877915f80604051936158266060866109f6565b602785527f416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c6020860152660819985a5b195960ca1b6040860152602081519101845af4615871614866565b91615a33565b50565b90505f615808565b803b156158be5760018060a01b03166001600160601b0360a01b5f516020615ae55f395f51905f525416175f516020615ae55f395f51905f5255565b60405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b6064820152608490fd5b91906040838203126103ba5782516001600160401b0381116103ba57602091615943918501613b8b565b92015190565b93929161596690604092865260606020870152606086019061180e565b930152565b60205f604051828101906301ffc9a760e01b82526301ffc9a760e01b60248201526024815261599b6044826109f6565b519084617530fa903d5f519083615a27575b5082615a1d575b50816159be575090565b602091505f90604051838101906301ffc9a760e01b825263ffffffff60e01b6024820152602481526159f16044826109f6565b5191617530fa5f513d82615a11575b5081615a0b57501590565b15919050565b6020111591505f615a00565b151591505f6159b4565b6020111592505f6159ad565b91929015615a955750815115615a47575090565b3b15615a505790565b60405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606490fd5b825190915015615aa85750805190602001fd5b60405162461bcd60e51b8152908190610e87906004830161070256fe47ff9796f72d439c6e5c30a24b9fad985a00c85a9f2258074c400a94f8746b00360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbca264697066735822122007715bb6b38669f83c106899679117f83b81d207060f277593591379a095fb9564736f6c634300081c0033608080604052346105ca57611a5c803803809161001c82856105ce565b833981016040828203126105ca5781516001600160a01b03811692908390036105ca576020810151906001600160401b0382116105ca57019080601f830112156105ca578151906001600160401b03821161028d576040519261008560208460051b01856105ce565b82845260208401916020839460071b830101918183116105ca57602001925b82841061055157505050505f549260ff8460081c161593848095610544575b801561052d575b156104d15760ff1981166001175f55846104bf575b5060ff5f5460081c161561046657603380546001600160a01b0319169190911790558151610157575b505061011e575b60405161138790816106d58239f35b61ff00195f54165f557f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498602060405160018152a161010f565b5f5b82518110156102b05761016c81846105ff565b519060ca60ff83511614610185575b6001915001610159565b60405160209261019584836105ce565b5f8252604051906101e5826101d7878201956302675fdd60e41b87526001602484015260026044840152600160648401526080608484015260a4830190610613565b03601f1981018452836105ce565b604060018060a01b0391015116935f806060946040519461020687876105ce565b602586527f416464726573733a206c6f772d6c6576656c207374617469632063616c6c20668587015264185a5b195960da1b60408701525190885afa923d156102a157503d926001600160401b03841161028d576001956102879483601f19601f830116019061027960405192836105ce565b81525f81943d92013e610637565b5061017b565b634e487b7160e01b5f52604160045260245ffd5b60019561028794919250610637565b50916097545f609755806103f7575b505f5b825181101561035f576102d581846105ff565b5190609754916801000000000000000083101561028d57600183018060975583101561034b5760016060819460975f5260205f2090831b019260ff81511660ff198554161784556020810151845460ff61ff0061ffff19604086015160101b169360081b169116171784550151910155016102c2565b634e487b7160e01b5f52603260045260245ffd5b509160405191602083019060208452518091526040830191905f5b8181106103b25750505090807f6517634f0cf2fee5bec4e10d9a05e7a61f4e8610d8db2b83bc84416b3dc0f666920390a15f80610108565b909192602060806001926060875160ff815116835260ff858201511685840152858060f01b03604082015116604084015201516060820152019401910191909161037a565b6001600160ff1b03811681036104525760975f5260011b7f354a83ed9988f79f6038d4c7a7dadbad8af32f4ad6df893e0e5807a1b1944ff9908101905b81811061044157506102bf565b5f8082556001820155600201610434565b634e487b7160e01b5f52601160045260245ffd5b60405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608490fd5b61ffff1916610101175f9081556100df565b60405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608490fd5b50303b1580156100ca5750600160ff8216146100ca565b50600160ff8216106100c3565b6080848303126105ca5760405190608082016001600160401b0381118382101761028d57604052610581856105f1565b825261058f602086016105f1565b60208301526040850151906001600160f01b03821682036105ca578260209260406080950152606087015160608201528152019301926100a4565b5f80fd5b601f909101601f19168101906001600160401b0382119082101761028d57604052565b519060ff821682036105ca57565b805182101561034b5760209160051b010190565b805180835260209291819084018484015e5f828201840152601f01601f1916010190565b91929015610699575081511561064b575090565b3b156106545790565b60405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606490fd5b8251909150156106ac5750805190602001fd5b60405162461bcd60e51b8152602060048201529081906106d0906024830190610613565b0390fdfe60806040526004361015610011575f80fd5b5f3560e01c806301ffc9a7146100c45780631498b514146100bf57806323e8cefc146100ba5780632675fdd0146100b55780632ae9c600146100b05780634162169f146100ab57806345e2984a146100a65780638306b5f1146100a1578063b580939c1461009c578063d09e5361146100975763e87c7fa814610092575f80fd5b610627565b6104d0565b610496565b610437565b6103be565b61032e565b61029f565b61021b565b6101a2565b61014f565b3461014b57602036600319011261014b5760043563ffffffff60e01b811680910361014b576328fcde5960e21b8114908115610109575b506040519015158152602090f35b6302675fdd60e41b81149150811561013b575b811561012a575b505f6100fb565b6301ffc9a760e01b1490505f610123565b621574e360e91b8114915061011c565b5f80fd5b3461014b57602036600319011261014b57606063ffffffff8061018960043563ffffffff81169163ffffffff808360201c169260401c1690565b9193908160405195168552166020840152166040820152f35b3461014b57606036600319011261014b576004356024356044359060201b82018092116101ea5760401b81018091116101ea576040516001600160f01b039091168152602090f35b61073b565b600435906001600160a01b038216820361014b57565b602435906001600160a01b038216820361014b57565b3461014b57608036600319011261014b576102346101ef565b61023c610205565b9060443560643567ffffffffffffffff811161014b573660238201121561014b57806004013567ffffffffffffffff811161014b573691016024011161014b5761029b926102899261074f565b60405190151581529081906020820190565b0390f35b3461014b575f36600319011261014b5760606040516102be8282610538565b3690376040516060810181811067ffffffffffffffff8211176103295760405260018152600460208201525f604082015260405180916060820190825f905b6003821061030c575050500390f35b825160ff16815285945060209283019260019290920191016102fd565b610508565b3461014b575f36600319011261014b576033546040516001600160a01b039091168152602090f35b60206040818301928281528451809452019201905f5b8181106103795750505090565b909192602060806001926060875160ff815116835260ff858201511685840152858060f01b03604082015116604084015201516060820152019401910191909161036c565b3461014b575f36600319011261014b576097546103da8161055a565b906103e86040519283610538565b8082526020820160975f525f5160206113325f395f51905f525f915b838310610419576040518061029b8782610356565b60026020600192610429856107e4565b815201920192019190610404565b3461014b57602036600319011261014b5760043567ffffffffffffffff811161014b573660238201121561014b57806004013567ffffffffffffffff811161014b573660248260071b8401011161014b576024610494920161081a565b005b3461014b575f36600319011261014b5760206040517fd3d98e95f3486fc234d80c098cf0d2a0a3fb187833d7e9cc930f8c4f8335a0e78152f35b3461014b57604036600319011261014b5760043560243560201b81018091116101ea576040516001600160f01b039091168152602090f35b634e487b7160e01b5f52604160045260245ffd5b6080810190811067ffffffffffffffff82111761032957604052565b90601f8019910116810190811067ffffffffffffffff82111761032957604052565b67ffffffffffffffff81116103295760051b60200190565b359060ff8216820361014b57565b92919261058c8261055a565b9361059a6040519586610538565b602085848152019260071b82019181831161014b57925b8284106105be5750505050565b60808483031261014b57604051906105d58261051c565b6105de85610572565b82526105ec60208601610572565b60208301526040850135906001600160f01b038216820361014b578260209260406080950152606087013560608201528152019301926105b1565b3461014b57604036600319011261014b576106406101ef565b60243567ffffffffffffffff811161014b573660238201121561014b576106746106b3913690602481600401359101610580565b5f549261069960ff600886901c16158095819661072d575b811561070d575b5061095f565b836106aa600160ff195f5416175f55565b6106f6576109c2565b6106b957005b6106c75f5461ff0019165f55565b604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb384740249890602090a1005b6107086101005f5461ff001916175f55565b6109c2565b303b1591508161071f575b505f610693565b60ff1660011490505f610718565b600160ff821610915061068c565b634e487b7160e01b5f52601160045260245ffd5b909160975461075d8161055a565b9061076b6040519283610538565b8082526020820160975f525f5160206113325f395f51905f525f915b8383106107c6575050505051156107be576107bb92604051926107ab602085610538565b5f8085523660208601375f610ae9565b90565b505050600190565b600260206001926107d6856107e4565b815201920192019190610787565b906040516107f18161051c565b606060018294805460ff8116855260ff8160081c16602086015260101c60408501520154910152565b603354604051637ef7c88360e11b81523060048201523360248201527fd3d98e95f3486fc234d80c098cf0d2a0a3fb187833d7e9cc930f8c4f8335a0e760448201526080606482015236608482018190526001600160a01b03909216949392915f60a48301375f60a4368301015260208160a481601f19601f3601168101030181885afa908115610946575f91610917575b50156108bf576108bd92935061094b565b565b604051630cb6f8ed60e21b81526001600160a01b03851660048201523060248201523360448201527fd3d98e95f3486fc234d80c098cf0d2a0a3fb187833d7e9cc930f8c4f8335a0e7606482015280608481015b0390fd5b610939915060203d60201161093f575b6109318183610538565b810190610c99565b5f6108ac565b503d610927565b610cb1565b61095a906108bd923691610580565b610d67565b1561096657565b60405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608490fd5b60ff5f5460081c1615610a015760018060a01b03166bffffffffffffffffffffffff60a01b603354161760335580516109f85750565b6108bd90610d67565b60405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608490fd5b634e487b7160e01b5f52603260045260245ffd5b609754811015610a8a5760975f5260205f209060011b01905f90565b610a5a565b8054821015610a8a575f5260205f209060011b01905f90565b8051821015610a8a5760209160051b010190565b600d1115610ac657565b634e487b7160e01b5f52602160045260245ffd5b60ff16600d811015610ac65790565b610af9610aff9195939495610a6e565b506107e4565b9260cb60ff610b0f865160ff1690565b1614610c8d57604084018051909290610b38906001600160f01b03165b6001600160f01b031690565b95610b44865160ff1690565b60ff811660ca8103610bf457505060608601519351959650610b8f95610b8290610b769081906001600160f01b031681565b6001600160a01b031690565b9380610bec575092610fc7565b15610be45760ff60015b1660206001925b01916007610bb7610bb2855160ff1690565b610ada565b610bc081610abc565b14610bdc57610bd6610bb26107bb945160ff1690565b91611044565b509050151590565b60ff5f610b99565b905092610fc7565b925092505060c881949394145f14610c13575050505060204391610ba0565b60c98103610c28575050505060204291610ba0565b60cc8103610c50575050905160209150610c4a906001600160f01b0316610b2c565b91610ba0565b9091809350511115610c8557610b2c610c78602093610c72610c4a9460ff1690565b90610aa8565b516001600160f01b031690565b505050505f90565b906107bb949293610e0f565b9081602091031261014b5751801515810361014b5790565b6040513d5f823e3d90fd5b67ffffffffffffffff811161032957601f01601f191660200190565b60405190610ce7602083610538565b5f8252565b805180835260209291819084018484015e5f828201840152601f01601f1916010190565b9060806107bb926001815260026020820152600160408201528160608201520190610cec565b6001600160a01b0391821681529116602082015260408101919091526080606082018190526107bb92910190610cec565b905f5b8251811015610e045780610d8060019285610aa8565b5160ca610d97610d91835160ff1690565b60ff1690565b14610da4575b5001610d6a565b610ddc610df8610b76610b766040610dfd95610dea610dc1610cd8565b83516302675fdd60e41b602082015297889160248301610d10565b03601f198101885287610538565b01516001600160f01b031690565b6110d2565b505f610d9d565b50906108bd906111d9565b939091926020850193600c610e28610bb2875160ff1690565b610e3181610abc565b14610f4757610e7a838383610e72610e57610b2c60408b9c9d015160018060f01b031690565b63ffffffff81169163ffffffff808360201c169260401c1690565b509890610ae9565b6008610e8a610bb2895160ff1690565b610e9381610abc565b14610f3c578080610f1c575b610f105715948580610ef0575b610ee557610eb994610ae9565b610eca610bb2600b92945160ff1690565b610ed381610abc565b14610edc575090565b15901515141590565b505050505050505f90565b506009610f01610bb2895160ff1690565b610f0a81610abc565b14610eac565b50505050505050600190565b50600a610f2d610bb2895160ff1690565b610f3681610abc565b14610e9f565b955050505050501590565b829450610f77819383610f6d610e57610b2c60408a9c9a989a015160018060f01b031690565b9a91959095610ae9565b6107bb969015610f875750610ae9565b9050610ae9565b60206040818301928281528451809452019201905f5b818110610fb15750505090565b8251845260209384019390920191600101610fa4565b905f936110178594610feb610feb610ff961101f9a60405192839160208301610f8e565b03601f198101835282610538565b60405194859360208501976302675fdd60e41b895260248601610d36565b51915afa1590565b611040573d6020810361103b57604051905f823e5f8151915290565b505f90565b5f90565b909161104f81610abc565b600181146110cd5761106081610abc565b600281146110c75761107181610abc565b600381146110c25761108281610abc565b600481146110bd5761109381610abc565b600581146110b757806110a7600692610abc565b146110b25750505f90565b111590565b50101590565b501090565b501190565b50141590565b501490565b906107bb915f80604051936110e8606086610538565b602585527f416464726573733a206c6f772d6c6576656c207374617469632063616c6c2066602086015264185a5b195960da1b6040860152602081519101845afa3d15611156573d9161113a83610cbc565b926111486040519485610538565b83523d5f602085013e611298565b606091611298565b634e487b7160e01b5f525f60045260245ffd5b609754680100000000000000008110156103295780600161119792016097556097610a8f565b9190916111d45780516020820151604083015161ffff1960109190911b1660ff90921660089190911b61ff00161717825560600151600190910155565b61115e565b6097545f60975580611245575b505f5b815181101561120e578061120861120260019385610aa8565b51611171565b016111e9565b506112407f6517634f0cf2fee5bec4e10d9a05e7a61f4e8610d8db2b83bc84416b3dc0f6669160405191829182610356565b0390a1565b6001600160ff1b03811681036101ea5760975f5260011b5f5160206113325f395f51905f52015f5160206113325f395f51905f525b81811061128757506111e6565b5f808255600182015560020161127a565b919290156112fa57508151156112ac575090565b3b156112b55790565b60405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606490fd5b82519091501561130d5750805190602001fd5b60405162461bcd60e51b815260206004820152908190610913906024830190610cec56fe354a83ed9988f79f6038d4c7a7dadbad8af32f4ad6df893e0e5807a1b1944ff9a2646970667358221220f6a4d9a0e6665d7f0c42efe7fecd3a28ebb96664195a8956a23d1cdb52f00fb664736f6c634300081c0033

Deployed Bytecode

0x6080806040526004361015610012575f80fd5b5f3560e01c90816301ffc9a71461142a575080632ae9c600146113ad5780635c60da1b146113695780637da5dd7c146113255780639cb0a12414610e59578063a8a9c29e14610df55763f10832f114610069575f80fd5b34610b42576040366003190112610b4257610082611494565b6001600160401b0360243511610b4257366023602435011215610b4257602435600401356001600160401b038111610b4257366024828135010111610b42576100c96115e3565b60a06024358381010312610b42576024803501356001600160401b038111610b4257602435019060248381350101604383011215610b4257602482013561010f816115fc565b9261011d60405194856115ae565b8184526024803586010160448284010111610b4257815f926044602093018387013784010152604460243501356001600160401b038111610b42576024848135010160438260243501011215610b425760248181350101359061017f82611617565b9161018d60405193846115ae565b8083526020830190819260248881350101602060248460051b8482350101010111610b42576044816024350101925b60446024358301600585901b01018410610bb55750505050606460243501356001600160401b038111610b4257602435019560248681350101604388011215610b425760248701359561020e87611617565b9761021c604051998a6115ae565b878952602089019060206024839a60071b8301010190602484813501018211610b4257604401915b818310610b465750505060409060246083199181359082350103010112610b42576040519161027283611578565b6102806084602435016114aa565b835260a46024350135916002831015610b4257602084979592970192835260018060a01b0316956040519463bfde57c360e01b602087015260e48601928860248801525f604488015260c06064880152518093526101048601926101048160051b88010192935f905b828210610a3c575050508582036023190160848701526103099250611539565b91516001600160a01b031660a48401525160028110156108ca5761033c91839160c483015203601f1981018352826115ae565b604051906103c690818301908382106001600160401b03831117610a285760406103a192859461178a86397f0000000000000000000000006ab6528e0d5a0f7c5738adfe6bc92dabc501d5066001600160a01b03168152602081018290520190611539565b03905ff08015610a1d5760018060a09695961b03169360405193846020810192631d0f8ff560e31b8452606482019286602484015260406044840152518093526084820190925f5b8181106109d4575050610405925003601f1981018652856115ae565b6e5af43d82803e903d91602b57fd5bf37f000000000000000000000000feb8a7ed4ab17cd2928f097b6622dc560b576e90763d602d80600a3d3981f3363d3d373d3d3d363d7300000062ffffff8260881c16175f5260781b17602052603760095ff06001600160a01b03811694908515610996578151610913575b505050610140916040519261049581856115ae565b60098452601f19015f5b8181106108de5750506040516104b481611593565b5f81528560208201528160408201525f60608201527f6f36f8bf0398781285f5a40c489dbf3268ce3e205aba87f21e49e6805391b5a160808201526104f88461165d565b526105028361165d565b5060405161050f81611593565b5f808252602082018790526001600160a01b03604083015260608201527ff281525e53675515a6ba7cc7bea8a81e649b3608423ee2d73be1752cea887889608082015261055b8461166a565b526105658361166a565b5060405161057281611593565b5f81528560208201528160408201525f60608201527f06d294bc8cbad2e393408b20dd019a772661f60b8d633e56761157cb1ec85f8c60808201526105b68461167a565b526105c08361167a565b506040516105cd81611593565b5f81528560208201528160408201525f60608201527f568cc693d84eb1901f8bcecba154cbdef23ca3cf67efc0a0b698528a06c660f760808201526106118461168a565b5261061b8361168a565b5060405161062881611593565b5f81528560208201528160408201525f60608201527f4707e94b25cfce1a7c363508fbb838c35864388ad77284b248282b9746982b9b608082015261066c8461169a565b526106768361169a565b5060405161068381611593565b60028152602081018690526001600160a01b036040820152606081018590527f8c433a4cd6b51969eca37f974940894297b9fcf4b282a213fea5cd8f85289c9060808201526106d1846116aa565b526106db836116aa565b506040516106e881611593565b5f808252602082018790526001600160a01b03604083015260608201527fb014ce248804cab6a144581acce1eeb70ce5d54f08433b989d73bb0ccee3d3f96080820152610734846116ba565b5261073e836116ba565b5060405161074b81611593565b5f81528160208201528560408201525f60608201527fbf04b4486c9663d805744005c3da000eda93de6e3308a4a7a812eb565327b78d608082015261078f846116ca565b52610799836116ca565b50604051906107a782611593565b5f8296959493965283602083015260408201525f60608201527fd3d98e95f3486fc234d80c098cf0d2a0a3fb187833d7e9cc930f8c4f8335a0e760808201526107ef826116db565b526107f9816116db565b506020840190815260409161082a835161081385826115ae565b60018152601f19850136602083013780875261165d565b528151938493845282602085015260808401905192808501528251809152602060a085019301905f5b8181106108a8575050505190603f19838203016060840152602080835192838152019201905f5b818110610888575050500390f35b91935091602061089b60019286516114c8565b940191019184939261087a565b82516001600160a01b0316855286955060209485019490920191600101610853565b634e487b7160e01b5f52602160045260245ffd5b6020906040516108ed81611593565b5f81525f838201525f60408201525f60608201525f60808201528282880101520161049f565b5f8061098594604051946109286040876115ae565b601e86527f416464726573733a206c6f772d6c6576656c2063616c6c206661696c656400006020870152519082855af13d1561098e573d91610969836115fc565b9261097760405194856115ae565b83523d5f602085013e6116ec565b505f8080610480565b6060916116ec565b60405162461bcd60e51b8152602060048201526016602482015275115490cc4c4d8dce8818dc99585d194819985a5b195960521b6044820152606490fd5b91600191935060806020916060875160ff815116835260ff858201511685840152858060f01b0360408201511660408401520151606082015201940191019187929391936103e9565b6040513d5f823e3d90fd5b634e487b7160e01b5f52604160045260245ffd5b909192936101031989820301825285519061010081019180519261010083528351809152602061012084019401905f905b808210610af85750505060019260209260e080846001600160401b03878097015116868501526001600160401b0360408201511660408501526001600160401b03606082015116606085015261ffff608082015116608085015261ffff60a08201511660a085015260c0810151151560c08501520151151591015297019201920190949392916102e9565b9091946020608060019260608951858060a01b038151168352848101511515858401526040810151151560408401520151610b32816114be565b6060820152019601920190610a6d565b5f80fd5b608060248486823501030112610b425760405190610b638261155d565b610b6c8461164f565b8252610b7a6020850161164f565b60208301526040840135906001600160f01b0382168203610b4257826020926040608095015260608601356060820152815201920191610244565b83356001600160401b038111610b42576101006024358085018301908c0103601f190112610b42576040519061010082018281106001600160401b03821117610a285760405260446024358501820101356001600160401b038111610b425760248c81350101601f6020836024868a82350101010101011215610b42576044602435860183018201013590610c4982611617565b91610c5760405193846115ae565b8083528d6024602085019181350101602089818660248a8860071b9482350101010101010111610b4257908e83926020808b979660248a8a8235010101010101915b6064602435880189018601600786901b01018310610d795750505050509383610d66610100602486610d5560e08360209c9a8d9b9a8c9b839e52610ce6604084848482350101010161163b565b8c8b0152610cfd606084848482350101010161163b565b60408b0152610d15608084848482350101010161163b565b60608b0152610d2d60a084848482350101010161152a565b60808b0152610d4560c084848482350101010161152a565b60a08b015282350101010161162e565b60c08601528a82350101010161162e565b60e08201528152019501949150506101bc565b82608092939495969750602491823501030112610b425760405190610d9d8261155d565b610da6836114aa565b8252610db46020840161162e565b6020830152610dc56040840161162e565b60408301526060830135906003821015610b4257826020926060608095015281520191018f918995949392610c99565b34610b42576060366003190112610b4257610e0e611494565b50610e17611519565b506044356001600160401b038111610b42576060906003199036030112610b4257610e406115e3565b5063098990c560e11b5f525f600452600160245260445ffd5b34610b42576040366003190112610b4257610e72611494565b6024356001600160401b038111610b42578036036060600319820112610b4257610e9e826004016115cf565b9160248101359160221901821215610b4257016004810135906001600160401b038211610b4257602401908060051b36038213610b42571561131157610ee3906115cf565b60405191610140610ef481856115ae565b60098452601f19015f5b8181106112dc57505060405190610f1482611593565b600182526001600160a01b03908116602083018190529416604082018190525f60608301527f6f36f8bf0398781285f5a40c489dbf3268ce3e205aba87f21e49e6805391b5a1608083015290610f698461165d565b52610f738361165d565b50604051610f8081611593565b60018152602081018590526001600160a01b0360408201525f60608201527ff281525e53675515a6ba7cc7bea8a81e649b3608423ee2d73be1752cea8878896080820152610fcd8461166a565b52610fd78361166a565b50604051610fe481611593565b600181528460208201528160408201525f60608201527f06d294bc8cbad2e393408b20dd019a772661f60b8d633e56761157cb1ec85f8c60808201526110298461167a565b526110338361167a565b5060405161104081611593565b600181528460208201528160408201525f60608201527f568cc693d84eb1901f8bcecba154cbdef23ca3cf67efc0a0b698528a06c660f760808201526110858461168a565b5261108f8361168a565b5060405161109c81611593565b600181528460208201528160408201525f60608201527f4707e94b25cfce1a7c363508fbb838c35864388ad77284b248282b9746982b9b60808201526110e18461169a565b526110eb8361169a565b50600193604051926110fc84611593565b60038610156108ca57858452602084018290526001600160a01b036040850181905216606084018190527f8c433a4cd6b51969eca37f974940894297b9fcf4b282a213fea5cd8f85289c90608085015292611156856116aa565b52611160846116aa565b5060405161116d81611593565b60038610156108ca57858152602081018290526001600160a01b0360408201525f60608201527fb014ce248804cab6a144581acce1eeb70ce5d54f08433b989d73bb0ccee3d3f960808201526111c2856116ba565b526111cc846116ba565b50604051906111da82611593565b60038610156108ca5785825282602083015260408201525f60608201527fbf04b4486c9663d805744005c3da000eda93de6e3308a4a7a812eb565327b78d6080820152611226846116ca565b52611230836116ca565b506040519161123e83611593565b60038510156108ca57848395949552602083015260408201525f60608201527fd3d98e95f3486fc234d80c098cf0d2a0a3fb187833d7e9cc930f8c4f8335a0e7608082015261128c836116db565b52611296826116db565b5060405190602082016020835283518091526020604084019401905f5b8181106112c05784860385f35b90919260206112d1829786516114c8565b9694019291016112b3565b6020906040516112eb81611593565b5f81525f838201525f60408201525f60608201525f608082015282828801015201610efe565b634e487b7160e01b5f52603260045260245ffd5b34610b42575f366003190112610b42576040517f000000000000000000000000feb8a7ed4ab17cd2928f097b6622dc560b576e906001600160a01b03168152602090f35b34610b42575f366003190112610b42576040517f0000000000000000000000006ab6528e0d5a0f7c5738adfe6bc92dabc501d5066001600160a01b03168152602090f35b34610b42575f366003190112610b42576060806040516113cd82826115ae565b3690376040518181018181106001600160401b03821117610a285760405260018152600460208201525f604082015260405190815f905b6003821061141157505050f35b60208060019260ff865116815201930191019091611404565b34610b42576020366003190112610b42576004359063ffffffff60e01b8216809203610b425760209163099718b560e41b8114908115611484575b8115611473575b5015158152f35b6301ffc9a760e01b1490508361146c565b621574e360e91b81149150611465565b600435906001600160a01b0382168203610b4257565b35906001600160a01b0382168203610b4257565b600311156108ca57565b90608060a09280516114d9816114be565b8352600180851b036020820151166020840152600180851b036040820151166040840152600180851b036060820151166060840152015160808201520190565b6024359061ffff82168203610b4257565b359061ffff82168203610b4257565b805180835260209291819084018484015e5f828201840152601f01601f1916010190565b608081019081106001600160401b03821117610a2857604052565b604081019081106001600160401b03821117610a2857604052565b60a081019081106001600160401b03821117610a2857604052565b90601f801991011681019081106001600160401b03821117610a2857604052565b356001600160a01b0381168103610b425790565b604051906115f082611578565b60606020838281520152565b6001600160401b038111610a2857601f01601f191660200190565b6001600160401b038111610a285760051b60200190565b35908115158203610b4257565b35906001600160401b0382168203610b4257565b359060ff82168203610b4257565b8051156113115760200190565b8051600110156113115760400190565b8051600210156113115760600190565b8051600310156113115760800190565b8051600410156113115760a00190565b8051600510156113115760c00190565b8051600610156113115760e00190565b805160071015611311576101000190565b805160081015611311576101200190565b9192901561174e5750815115611700575090565b3b156117095790565b60405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606490fd5b8251909150156117615750805190602001fd5b60405162461bcd60e51b815260206004820152908190611785906024830190611539565b0390fdfe60806040526103c680380380610014816101f2565b9283398101906040818303126101ee5780516001600160a01b038116918282036101ee576020810151906001600160401b0382116101ee57019183601f840112156101ee57825161006c6100678261022b565b6101f2565b938185526020850195602083830101116101ee57815f926020809301885e85010152813b15610193577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80546001600160a01b031916821790557fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b5f80a281511580159061018c575b610108575b60405160cb90816102fb8239f35b5f8061017b9461011860606101f2565b94602786527f416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c6020870152660819985a5b195960ca1b60408701525190845af43d15610184573d9161016c6100678461022b565b9283523d5f602085013e610246565b505f80806100fa565b606091610246565b505f6100f5565b60405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b6064820152608490fd5b5f80fd5b6040519190601f01601f191682016001600160401b0381118382101761021757604052565b634e487b7160e01b5f52604160045260245ffd5b6001600160401b03811161021757601f01601f191660200190565b919290156102a8575081511561025a575090565b3b156102635790565b60405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606490fd5b8251909150156102bb5750805190602001fd5b604460209160405192839162461bcd60e51b83528160048401528051918291826024860152018484015e5f828201840152601f01601f19168101030190fdfe608060405236156051577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc545f9081906001600160a01b0316368280378136915af43d5f803e15604d573d5ff35b3d5ffd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc545f9081906001600160a01b0316368280378136915af43d5f803e15604d573d5ff3fea26469706673582212203bf93d98380d30a31ff94676bcd53f6cf4fd06145a15d34fda5d76afee117ce864736f6c634300081c0033a2646970667358221220d549dc05acebacd8e98bd12d54be05c98c16b1115bf8330bcbd5aeac4f46f58d64736f6c634300081c0033

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

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

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading
[ Download: CSV Export  ]

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