Source Code
Overview
ETH Balance
0 ETH
ETH Value
$0.00| Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
Latest 6 internal transactions
Advanced mode:
| Parent Transaction Hash | Block | From | To | |||
|---|---|---|---|---|---|---|
| 17862036 | 10 days ago | Contract Creation | 0 ETH | |||
| 17862036 | 10 days ago | Contract Creation | 0 ETH | |||
| 17492835 | 14 days ago | Contract Creation | 0 ETH | |||
| 17492835 | 14 days ago | Contract Creation | 0 ETH | |||
| 17417925 | 15 days ago | Contract Creation | 0 ETH | |||
| 17417925 | 15 days ago | Contract Creation | 0 ETH |
Cross-Chain Transactions
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
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
Contract Source Code (Solidity Standard Json-Input format)
// 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);
}
}// 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;
}// 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; }
// 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);
}// 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);
}
}
}// 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); }
// 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;
}// 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;
}// 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;
}
}// 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); }
// 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));
}
}// 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;
}// 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;
}// 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);
}// 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);
}// 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);
}
}
}// 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);
}// 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
}
}
}{
"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
- No Contract Security Audit Submitted- Submit Audit Here
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"}]Contract Creation Code
60c0806040523461015c57615c198181016001600160401b03811183821017610143578291611ce6833903905ff080156100f5576001600160a01b03166080526040516020818101916001600160401b0383118184101761014357826040525f81526001610157575b60405191611a5c8084016001600160401b0381118582101761014357606091959392956178ff863960408101925f8252604087830152518093520191935f5b82811061010057848403855ff080156100f5576001600160a01b031660a052604051611b8590816101618239608051818181610369015261137e015260a051818181610417015261133a0152f35b6040513d5f823e3d90fd5b8551805160ff90811686528184015116858401526040808201516001600160f01b03169086015260609081015190850152948101946080909301926001016100a7565b634e487b7160e01b5f52604160045260245ffd5b610068565b5f80fdfe6080806040526004361015610012575f80fd5b5f3560e01c90816301ffc9a71461142a575080632ae9c600146113ad5780635c60da1b146113695780637da5dd7c146113255780639cb0a12414610e59578063a8a9c29e14610df55763f10832f114610069575f80fd5b34610b42576040366003190112610b4257610082611494565b6001600160401b0360243511610b4257366023602435011215610b4257602435600401356001600160401b038111610b4257366024828135010111610b42576100c96115e3565b60a06024358381010312610b42576024803501356001600160401b038111610b4257602435019060248381350101604383011215610b4257602482013561010f816115fc565b9261011d60405194856115ae565b8184526024803586010160448284010111610b4257815f926044602093018387013784010152604460243501356001600160401b038111610b42576024848135010160438260243501011215610b425760248181350101359061017f82611617565b9161018d60405193846115ae565b8083526020830190819260248881350101602060248460051b8482350101010111610b42576044816024350101925b60446024358301600585901b01018410610bb55750505050606460243501356001600160401b038111610b4257602435019560248681350101604388011215610b425760248701359561020e87611617565b9761021c604051998a6115ae565b878952602089019060206024839a60071b8301010190602484813501018211610b4257604401915b818310610b465750505060409060246083199181359082350103010112610b42576040519161027283611578565b6102806084602435016114aa565b835260a46024350135916002831015610b4257602084979592970192835260018060a01b0316956040519463bfde57c360e01b602087015260e48601928860248801525f604488015260c06064880152518093526101048601926101048160051b88010192935f905b828210610a3c575050508582036023190160848701526103099250611539565b91516001600160a01b031660a48401525160028110156108ca5761033c91839160c483015203601f1981018352826115ae565b604051906103c690818301908382106001600160401b03831117610a285760406103a192859461178a86397f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602081018290520190611539565b03905ff08015610a1d5760018060a09695961b03169360405193846020810192631d0f8ff560e31b8452606482019286602484015260406044840152518093526084820190925f5b8181106109d4575050610405925003601f1981018652856115ae565b6e5af43d82803e903d91602b57fd5bf37f0000000000000000000000000000000000000000000000000000000000000000763d602d80600a3d3981f3363d3d373d3d3d363d7300000062ffffff8260881c16175f5260781b17602052603760095ff06001600160a01b03811694908515610996578151610913575b505050610140916040519261049581856115ae565b60098452601f19015f5b8181106108de5750506040516104b481611593565b5f81528560208201528160408201525f60608201527f6f36f8bf0398781285f5a40c489dbf3268ce3e205aba87f21e49e6805391b5a160808201526104f88461165d565b526105028361165d565b5060405161050f81611593565b5f808252602082018790526001600160a01b03604083015260608201527ff281525e53675515a6ba7cc7bea8a81e649b3608423ee2d73be1752cea887889608082015261055b8461166a565b526105658361166a565b5060405161057281611593565b5f81528560208201528160408201525f60608201527f06d294bc8cbad2e393408b20dd019a772661f60b8d633e56761157cb1ec85f8c60808201526105b68461167a565b526105c08361167a565b506040516105cd81611593565b5f81528560208201528160408201525f60608201527f568cc693d84eb1901f8bcecba154cbdef23ca3cf67efc0a0b698528a06c660f760808201526106118461168a565b5261061b8361168a565b5060405161062881611593565b5f81528560208201528160408201525f60608201527f4707e94b25cfce1a7c363508fbb838c35864388ad77284b248282b9746982b9b608082015261066c8461169a565b526106768361169a565b5060405161068381611593565b60028152602081018690526001600160a01b036040820152606081018590527f8c433a4cd6b51969eca37f974940894297b9fcf4b282a213fea5cd8f85289c9060808201526106d1846116aa565b526106db836116aa565b506040516106e881611593565b5f808252602082018790526001600160a01b03604083015260608201527fb014ce248804cab6a144581acce1eeb70ce5d54f08433b989d73bb0ccee3d3f96080820152610734846116ba565b5261073e836116ba565b5060405161074b81611593565b5f81528160208201528560408201525f60608201527fbf04b4486c9663d805744005c3da000eda93de6e3308a4a7a812eb565327b78d608082015261078f846116ca565b52610799836116ca565b50604051906107a782611593565b5f8296959493965283602083015260408201525f60608201527fd3d98e95f3486fc234d80c098cf0d2a0a3fb187833d7e9cc930f8c4f8335a0e760808201526107ef826116db565b526107f9816116db565b506020840190815260409161082a835161081385826115ae565b60018152601f19850136602083013780875261165d565b528151938493845282602085015260808401905192808501528251809152602060a085019301905f5b8181106108a8575050505190603f19838203016060840152602080835192838152019201905f5b818110610888575050500390f35b91935091602061089b60019286516114c8565b940191019184939261087a565b82516001600160a01b0316855286955060209485019490920191600101610853565b634e487b7160e01b5f52602160045260245ffd5b6020906040516108ed81611593565b5f81525f838201525f60408201525f60608201525f60808201528282880101520161049f565b5f8061098594604051946109286040876115ae565b601e86527f416464726573733a206c6f772d6c6576656c2063616c6c206661696c656400006020870152519082855af13d1561098e573d91610969836115fc565b9261097760405194856115ae565b83523d5f602085013e6116ec565b505f8080610480565b6060916116ec565b60405162461bcd60e51b8152602060048201526016602482015275115490cc4c4d8dce8818dc99585d194819985a5b195960521b6044820152606490fd5b91600191935060806020916060875160ff815116835260ff858201511685840152858060f01b0360408201511660408401520151606082015201940191019187929391936103e9565b6040513d5f823e3d90fd5b634e487b7160e01b5f52604160045260245ffd5b909192936101031989820301825285519061010081019180519261010083528351809152602061012084019401905f905b808210610af85750505060019260209260e080846001600160401b03878097015116868501526001600160401b0360408201511660408501526001600160401b03606082015116606085015261ffff608082015116608085015261ffff60a08201511660a085015260c0810151151560c08501520151151591015297019201920190949392916102e9565b9091946020608060019260608951858060a01b038151168352848101511515858401526040810151151560408401520151610b32816114be565b6060820152019601920190610a6d565b5f80fd5b608060248486823501030112610b425760405190610b638261155d565b610b6c8461164f565b8252610b7a6020850161164f565b60208301526040840135906001600160f01b0382168203610b4257826020926040608095015260608601356060820152815201920191610244565b83356001600160401b038111610b42576101006024358085018301908c0103601f190112610b42576040519061010082018281106001600160401b03821117610a285760405260446024358501820101356001600160401b038111610b425760248c81350101601f6020836024868a82350101010101011215610b42576044602435860183018201013590610c4982611617565b91610c5760405193846115ae565b8083528d6024602085019181350101602089818660248a8860071b9482350101010101010111610b4257908e83926020808b979660248a8a8235010101010101915b6064602435880189018601600786901b01018310610d795750505050509383610d66610100602486610d5560e08360209c9a8d9b9a8c9b839e52610ce6604084848482350101010161163b565b8c8b0152610cfd606084848482350101010161163b565b60408b0152610d15608084848482350101010161163b565b60608b0152610d2d60a084848482350101010161152a565b60808b0152610d4560c084848482350101010161152a565b60a08b015282350101010161162e565b60c08601528a82350101010161162e565b60e08201528152019501949150506101bc565b82608092939495969750602491823501030112610b425760405190610d9d8261155d565b610da6836114aa565b8252610db46020840161162e565b6020830152610dc56040840161162e565b60408301526060830135906003821015610b4257826020926060608095015281520191018f918995949392610c99565b34610b42576060366003190112610b4257610e0e611494565b50610e17611519565b506044356001600160401b038111610b42576060906003199036030112610b4257610e406115e3565b5063098990c560e11b5f525f600452600160245260445ffd5b34610b42576040366003190112610b4257610e72611494565b6024356001600160401b038111610b42578036036060600319820112610b4257610e9e826004016115cf565b9160248101359160221901821215610b4257016004810135906001600160401b038211610b4257602401908060051b36038213610b42571561131157610ee3906115cf565b60405191610140610ef481856115ae565b60098452601f19015f5b8181106112dc57505060405190610f1482611593565b600182526001600160a01b03908116602083018190529416604082018190525f60608301527f6f36f8bf0398781285f5a40c489dbf3268ce3e205aba87f21e49e6805391b5a1608083015290610f698461165d565b52610f738361165d565b50604051610f8081611593565b60018152602081018590526001600160a01b0360408201525f60608201527ff281525e53675515a6ba7cc7bea8a81e649b3608423ee2d73be1752cea8878896080820152610fcd8461166a565b52610fd78361166a565b50604051610fe481611593565b600181528460208201528160408201525f60608201527f06d294bc8cbad2e393408b20dd019a772661f60b8d633e56761157cb1ec85f8c60808201526110298461167a565b526110338361167a565b5060405161104081611593565b600181528460208201528160408201525f60608201527f568cc693d84eb1901f8bcecba154cbdef23ca3cf67efc0a0b698528a06c660f760808201526110858461168a565b5261108f8361168a565b5060405161109c81611593565b600181528460208201528160408201525f60608201527f4707e94b25cfce1a7c363508fbb838c35864388ad77284b248282b9746982b9b60808201526110e18461169a565b526110eb8361169a565b50600193604051926110fc84611593565b60038610156108ca57858452602084018290526001600160a01b036040850181905216606084018190527f8c433a4cd6b51969eca37f974940894297b9fcf4b282a213fea5cd8f85289c90608085015292611156856116aa565b52611160846116aa565b5060405161116d81611593565b60038610156108ca57858152602081018290526001600160a01b0360408201525f60608201527fb014ce248804cab6a144581acce1eeb70ce5d54f08433b989d73bb0ccee3d3f960808201526111c2856116ba565b526111cc846116ba565b50604051906111da82611593565b60038610156108ca5785825282602083015260408201525f60608201527fbf04b4486c9663d805744005c3da000eda93de6e3308a4a7a812eb565327b78d6080820152611226846116ca565b52611230836116ca565b506040519161123e83611593565b60038510156108ca57848395949552602083015260408201525f60608201527fd3d98e95f3486fc234d80c098cf0d2a0a3fb187833d7e9cc930f8c4f8335a0e7608082015261128c836116db565b52611296826116db565b5060405190602082016020835283518091526020604084019401905f5b8181106112c05784860385f35b90919260206112d1829786516114c8565b9694019291016112b3565b6020906040516112eb81611593565b5f81525f838201525f60408201525f60608201525f608082015282828801015201610efe565b634e487b7160e01b5f52603260045260245ffd5b34610b42575f366003190112610b42576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b34610b42575f366003190112610b42576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b34610b42575f366003190112610b42576060806040516113cd82826115ae565b3690376040518181018181106001600160401b03821117610a285760405260018152600460208201525f604082015260405190815f905b6003821061141157505050f35b60208060019260ff865116815201930191019091611404565b34610b42576020366003190112610b42576004359063ffffffff60e01b8216809203610b425760209163099718b560e41b8114908115611484575b8115611473575b5015158152f35b6301ffc9a760e01b1490508361146c565b621574e360e91b81149150611465565b600435906001600160a01b0382168203610b4257565b35906001600160a01b0382168203610b4257565b600311156108ca57565b90608060a09280516114d9816114be565b8352600180851b036020820151166020840152600180851b036040820151166040840152600180851b036060820151166060840152015160808201520190565b6024359061ffff82168203610b4257565b359061ffff82168203610b4257565b805180835260209291819084018484015e5f828201840152601f01601f1916010190565b608081019081106001600160401b03821117610a2857604052565b604081019081106001600160401b03821117610a2857604052565b60a081019081106001600160401b03821117610a2857604052565b90601f801991011681019081106001600160401b03821117610a2857604052565b356001600160a01b0381168103610b425790565b604051906115f082611578565b60606020838281520152565b6001600160401b038111610a2857601f01601f191660200190565b6001600160401b038111610a285760051b60200190565b35908115158203610b4257565b35906001600160401b0382168203610b4257565b359060ff82168203610b4257565b8051156113115760200190565b8051600110156113115760400190565b8051600210156113115760600190565b8051600310156113115760800190565b8051600410156113115760a00190565b8051600510156113115760c00190565b8051600610156113115760e00190565b805160071015611311576101000190565b805160081015611311576101200190565b9192901561174e5750815115611700575090565b3b156117095790565b60405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606490fd5b8251909150156117615750805190602001fd5b60405162461bcd60e51b815260206004820152908190611785906024830190611539565b0390fdfe60806040526103c680380380610014816101f2565b9283398101906040818303126101ee5780516001600160a01b038116918282036101ee576020810151906001600160401b0382116101ee57019183601f840112156101ee57825161006c6100678261022b565b6101f2565b938185526020850195602083830101116101ee57815f926020809301885e85010152813b15610193577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80546001600160a01b031916821790557fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b5f80a281511580159061018c575b610108575b60405160cb90816102fb8239f35b5f8061017b9461011860606101f2565b94602786527f416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c6020870152660819985a5b195960ca1b60408701525190845af43d15610184573d9161016c6100678461022b565b9283523d5f602085013e610246565b505f80806100fa565b606091610246565b505f6100f5565b60405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b6064820152608490fd5b5f80fd5b6040519190601f01601f191682016001600160401b0381118382101761021757604052565b634e487b7160e01b5f52604160045260245ffd5b6001600160401b03811161021757601f01601f191660200190565b919290156102a8575081511561025a575090565b3b156102635790565b60405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606490fd5b8251909150156102bb5750805190602001fd5b604460209160405192839162461bcd60e51b83528160048401528051918291826024860152018484015e5f828201840152601f01601f19168101030190fdfe608060405236156051577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc545f9081906001600160a01b0316368280378136915af43d5f803e15604d573d5ff35b3d5ffd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc545f9081906001600160a01b0316368280378136915af43d5f803e15604d573d5ff3fea26469706673582212203bf93d98380d30a31ff94676bcd53f6cf4fd06145a15d34fda5d76afee117ce864736f6c634300081c0033a2646970667358221220d549dc05acebacd8e98bd12d54be05c98c16b1115bf8330bcbd5aeac4f46f58d64736f6c634300081c003360a080604052346100da57306080525f549060ff8260081c16610088575060ff8082160361004e575b604051615b3a90816100df8239608051818181610d8801528181611195015261130d0152f35b60ff90811916175f557f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498602060405160ff8152a15f610028565b62461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b6064820152608490fd5b5f80fdfe60806040526004361015610011575f80fd5b5f3560e01c806301ffc9a7146102c45780630b47808d146102bf5780631abf3f11146102ba5780631c622dea146102b55780631f3cb5b4146102b05780632ae9c600146102ab57806330196ab9146102a657806335ade049146102a15780633659cfe61461029c5780633d3f4b1b146102975780633e4f49e61461029257806340e58ee51461028d5780634162169f1461028857806341de6830146102835780634e3ed5e91461027e5780634f1ef28614610279578063523039621461027457806352d1902d1461026f578063572b6c051461026a5780635c23bfb7146102655780635c60da1b14610260578063761f8acb1461025b5780637a5b4f59146102565780637e3f1353146102515780638cb750591461024c578063bb225da214610247578063bfde57c314610242578063c218c1321461023d578063c7f758a814610238578063c98425ee14610233578063c9c4bfca1461022e578063cc63604a14610229578063ce1b815f14610224578063da35c6641461021f578063da7422281461021a578063dd63c06f14610215578063e306bee714610210578063ea65ab821461020b578063ee57e36f14610206578063ef8cccb014610201578063fd8d2d36146101fc578063fdbd7eb3146101f75763fe0d94c1146101f2575f80fd5b61225b565b6121ca565b6121a3565b611fda565b611d67565b611cd8565b611c9e565b611c84565b611b71565b611b52565b611b25565b611b07565b611acd565b611a9c565b611956565b61179d565b611719565b611606565b6115cc565b61159b565b6114ad565b611464565b611430565b6113fd565b6113be565b6112fb565b6112bc565b611159565b6110f2565b6110d8565b6110a6565b610fa4565b610f75565b610ede565b610d66565b610cbd565b6107e9565b61077c565b610713565b61068c565b61060b565b61041b565b346103ba5760203660031901126103ba5760043563ffffffff60e01b81168091036103ba576103279063041de68360e41b81149081156103aa575b8115610399575b8115610388575b811561032b575b5060405190151581529081906020820190565b0390f35b634a06561b60e11b811491508115610345575b505f610314565b63368d719960e21b811491508115610377575b8115610366575b505f61033e565b6301ffc9a760e01b1490505f61035f565b633f4644d160e21b81149150610358565b63afc5b82360e01b8114915061030d565b6352d1902d60e01b81149150610306565b621574e360e91b811491506102ff565b5f80fd5b9181601f840112156103ba578235916001600160401b0383116103ba57602083818601950101116103ba57565b9181601f840112156103ba578235916001600160401b0383116103ba576020808501948460051b0101116103ba57565b346103ba5760603660031901126103ba576004356024356001600160401b0381116103ba5761044e9036906004016103be565b91604435926001600160401b0384116103ba576104726104e59436906004016103eb565b60fb549091906104a0906001600160a01b031661048d613d87565b90610496613dc9565b9290913090613e0c565b6104b3845f5261016260205260405f2090565b6001906104c160098761420e565b6104fd82546104f86104d88261ffff9060c01c1690565b9b8c9260d01c61ffff1690565b61ffff165f5261016360205260405f2090565b61239b565b509081541515806105f7575b6105cc5750600101546105249060e81c60ff161590565b1590565b6105af576002016105348161242e565b5f5b848110610593575050509161058e61ffff927fc1d7dc1770290440bd536be5eca85bc1e54960c21ef0f9a838033941a7392d8d94610572613d87565b6040516001600160a01b03909116999095169785949085612726565b0390a4005b806105a96105a3859388886124e1565b8461266b565b01610536565b638b32333560e01b5f52600486905261ffff881660245260445b5ffd5b600881896105dc6105c994610f66565b632c2eee6560e11b5f5260045260ff16602452604452606490565b5061060181610f66565b6003811415610509565b346103ba575f3660031901126103ba57602061ffff6101645416604051908152f35b6024359061ffff821682036103ba57565b359061ffff821682036103ba57565b6001600160a01b038116036103ba57565b60609060031901126103ba576004359060243561ffff811681036103ba57906044356106898161064d565b90565b346103ba5760206106d56106c06106a23661065e565b92915f5261015f855260405f209061ffff165f5260205260405f2090565b9060018060a01b03165f5260205260405f2090565b54604051908152f35b805180835260209291819084018484015e5f828201840152601f01601f1916010190565b9060206106899281815201906106de565b346103ba5760603660031901126103ba5760043561075361073261062d565b604435925f5261016160205260405f209061ffff165f5260205260405f2090565b905f5260205261032761076860405f20612834565b6040519182916020835260208301906106de565b346103ba575f3660031901126103ba57606060405161079b82826109f6565b3690376040516107aa81610968565b60018152600460208201525f604082015260405190815f905b600382106107d057606084f35b60208060019260ff8651168152019301910190916107c3565b346103ba5760203660031901126103ba576004356001600160401b0381116103ba576108199036906004016103eb565b60fb546001600160a01b031661082d613d87565b610885602061083a613dc9565b604051637ef7c88360e11b81526001600160a01b03909616959384928392907f6f36f8bf0398781285f5a40c489dbf3268ce3e205aba87f21e49e6805391b5a1883060048701613721565b0381865afa90811561094f575f91610920575b50156108cb57505080156108bc576108ba916108b5913691612989565b614365565b005b63d345a56b60e01b5f5260045ffd5b604051630cb6f8ed60e21b815260048101929092523060248301526001600160a01b031660448201527f6f36f8bf0398781285f5a40c489dbf3268ce3e205aba87f21e49e6805391b5a1606482015260849150fd5b610942915060203d602011610948575b61093a81836109f6565b81019061370c565b5f610898565b503d610930565b613752565b634e487b7160e01b5f52604160045260245ffd5b606081019081106001600160401b0382111761098357604052565b610954565b61012081019081106001600160401b0382111761098357604052565b61010081019081106001600160401b0382111761098357604052565b608081019081106001600160401b0382111761098357604052565b604081019081106001600160401b0382111761098357604052565b90601f801991011681019081106001600160401b0382111761098357604052565b60405190610a27610100836109f6565b565b60405190610a276060836109f6565b6001600160401b03811161098357601f01601f191660200190565b929192610a5f82610a38565b91610a6d60405193846109f6565b8294818452818301116103ba578281602093845f960137010152565b9080601f830112156103ba5781602061068993359101610a53565b6001600160401b0381116109835760051b60200190565b9080601f830112156103ba57813591610ad383610aa4565b92610ae160405194856109f6565b80845260208085019160051b830101918383116103ba5760208101915b838310610b0d57505050505090565b82356001600160401b0381116103ba578201906060828703601f1901126103ba5760405190610b3b82610968565b6020830135610b498161064d565b8252604083013560208301526060830135916001600160401b0383116103ba57610b7b88602080969581960101610a89565b6040820152815201920191610afe565b606435906001600160401b03821682036103ba57565b604435906001600160401b03821682036103ba57565b35906001600160401b03821682036103ba57565b81601f820112156103ba57803590610be282610aa4565b92610bf060405194856109f6565b82845260208085019360051b830101918183116103ba5760208101935b838510610c1c57505050505090565b84356001600160401b0381116103ba57820183603f820112156103ba576020810135610c4781610aa4565b91610c5560405193846109f6565b8183526020808085019360051b83010101918683116103ba5760408201905b838210610c8e575050509082525060209485019401610c0d565b81356001600160401b0381116103ba57602091610cb28a8480809589010101610a89565b815201910190610c74565b346103ba5760a03660031901126103ba576004356001600160401b0381116103ba57610ced903690600401610a89565b6024356001600160401b0381116103ba57610d0c903690600401610abb565b90604435906001600160801b03821682036103ba57610d29610b8b565b608435926001600160401b0384116103ba5761032794610d50610d56953690600401610bcb565b93612a94565b6040519081529081906020820190565b346103ba5760203660031901126103ba57600435610d838161064d565b610dda7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316610dbc30821415613390565b5f516020615ae55f395f51905f52546001600160a01b0316146133f1565b60fb54610e05906001600160a01b0316610df2613d87565b90610dfb613dc9565b9290913090613ef6565b610e0d613452565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff1615610e4157506108ba90615882565b6040516352d1902d60e01b8152906020826004816001600160a01b0387165afa5f9281610ead575b50610e8b5760405162461bcd60e51b815280610e8760048201614e8d565b0390fd5b6108ba92610ea85f516020615ae55f395f51905f525f9414614e2f565b6157c4565b610ed091935060203d602011610ed7575b610ec881836109f6565b810190614895565b915f610e69565b503d610ebe565b346103ba575f3660031901126103ba57610327604051610eff6060826109f6565b602c81527f2862797465735b5d5b5d20737562426f64696573437573746f6d50726f706f7360208201526b616c506172616d734142492960a01b60408201526040519182916020835260208301906106de565b634e487b7160e01b5f52602160045260245ffd5b60051115610f7057565b610f52565b346103ba5760203660031901126103ba57610f9160043561348d565b6040516005821015610f70576020918152f35b346103ba5760203660031901126103ba576104e560043560fb54610fe6906001600160a01b0316610fd3613d87565b90610fdc613dc9565b9290913090613fe0565b5f81815261016260205260409020610fff60098361420e565b50611038610520600161102c84546104f861101f8261ffff9060c01c1690565b98899260d01c61ffff1690565b50015460e01c60ff1690565b61108a57805460ff60e81b1916600160e81b17905561ffff6001600160a01b03611060613d87565b169216907f578c7050405154b6a8167f305908011ff85e3231eff1fbce2bbe95500b92f2035f80a4005b638b9b77af60e01b5f52600482905261ffff831660245260445ffd5b346103ba575f3660031901126103ba5760fb546040516001600160a01b039091168152602090f35b60031115610f7057565b346103ba575f3660031901126103ba5760206040515f8152f35b346103ba5760403660031901126103ba5760043561110e61062d565b5f828152610162602052604090205460801c6001600160401b0316156111465761113a90604092614f28565b82519182526020820152f35b50630853c2a360e41b5f5260045260245ffd5b60403660031901126103ba576004356111718161064d565b6024356001600160401b0381116103ba57611190903690600401610a89565b6111c97f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316610dbc30821415613390565b60fb546111e1906001600160a01b0316610df2613d87565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff161561121557506108ba90615882565b6040516352d1902d60e01b8152906020826004816001600160a01b0387165afa5f9281611279575b5061125b5760405162461bcd60e51b815280610e8760048201614e8d565b6108ba92610ea85f516020615ae55f395f51905f5260019414614e2f565b61129391935060203d602011610ed757610ec881836109f6565b915f61123d565b359060038210156103ba57565b801515036103ba57565b3590610a27826112a7565b346103ba5760803660031901126103ba576004356112d861062d565b9060443560038110156103ba576108ba92606435926112f6846112a7565b6135ed565b346103ba575f3660031901126103ba577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03163003611353576040515f516020615ae55f395f51905f528152602090f35b60405162461bcd60e51b815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c60448201527f6c6564207468726f7567682064656c656761746563616c6c00000000000000006064820152608490fd5b346103ba5760203660031901126103ba5760206004356113dd8161064d565b610164546040516001600160a01b0392831660109290921c909216148152f35b346103ba5760203660031901126103ba5761141960043561348d565b6005811015610f7057602090600360405191148152f35b346103ba575f3660031901126103ba575f516020615ae55f395f51905f52546040516001600160a01b039091168152602090f35b346103ba57602060ff61149a6106c061147c3661065e565b92915f52610160865260405f209061ffff165f5260205260405f2090565b5416604051906114a9816110ce565b8152f35b346103ba575f3660031901126103ba576040515f5f516020615ac55f395f51905f52546114d9816123cd565b8084529060018116908115611577575060011461150d575b61032783611501818503826109f6565b60405191829182610702565b5f516020615ac55f395f51905f525f9081527f20120d26379ad35b0c68e58a20f1251f24acf3aee87d3a8d8759c48671c8cace939250905b80821061155d575090915081016020016115016114f1565b919260018160209254838588010152019101909291611545565b60ff191660208086019190915291151560051b8401909101915061150190506114f1565b346103ba5760203660031901126103ba5760206115c26004356115bd8161064d565b61375d565b6040519015158152f35b346103ba575f3660031901126103ba5760206040517f568cc693d84eb1901f8bcecba154cbdef23ca3cf67efc0a0b698528a06c660f78152f35b346103ba5760403660031901126103ba5760fb546001600160a01b031661162b613d87565b906116786020611639613dc9565b604051637ef7c88360e11b81529384928392907f568cc693d84eb1901f8bcecba154cbdef23ca3cf67efc0a0b698528a06c660f7893060048701613721565b0381855afa90811561094f575f916116fa575b50156116a4576108ba61169f366004613809565b6152d7565b604051630cb6f8ed60e21b815260048101919091523060248201526001600160a01b0390911660448201527f568cc693d84eb1901f8bcecba154cbdef23ca3cf67efc0a0b698528a06c660f76064820152608490fd5b611713915060203d6020116109485761093a81836109f6565b5f61168b565b346103ba5760c03660031901126103ba576004356117368161064d565b602435906117438261064d565b6044356001600160401b0381116103ba576117629036906004016103eb565b906064356001600160401b0381116103ba576117829036906004016103be565b92909160403660831901126103ba576108ba956084956138a7565b346103ba5760203660031901126103ba57600435805f526101626020526117d06117ca60405f209261348d565b91615139565b90816117e5575b506040519015158152602090f35b90506005811015610f705760038114908115611803575b505f6117d7565b60029150145f6117fc565b9080602083519182815201916020808360051b8301019401925f915b83831061183957505050505090565b9091929394602080611879600193601f19868203018752606060408b51878060a01b038151168452858101518685015201519181604082015201906106de565b9701930193019193929061182a565b60021115610f7057565b80516001600160a01b0316825260200151906002821015610f705760200152565b61068990602081526118d16020820184516001600160801b03169052565b60208301516001600160401b03166040820152604083015161ffff166060820152606083015161ffff1660808201526080830151151560a082015260a0830151151560c082015260c08301516001600160a01b031660e082015261012061010061194b60e08601516101408386015261016085019061180e565b940151910190611892565b346103ba5760203660031901126103ba5760043560405161197681610988565b5f81525f60208201525f60408201525f60608201525f60808201525f60a08201525f60c0820152606060e08201526101006119af613a0e565b9101525f5261016260205261032760405f20611a7a6003604051926119d384610988565b611a50611a4782546119fb6119ee826001600160801b031690565b6001600160801b03168852565b6001600160401b03608082901c16602088015261ffff60c082901c16604088015261ffff60d082901c166060880152611a3e60e082901c60ff1615156080890152565b60e81c60ff1690565b151560a0860152565b60018101546001600160a01b031660c0850152611a6f60028201613a26565b60e085015201613adf565b610100820152604051918291826118b3565b604081019291610a279190611892565b346103ba575f3660031901126103ba57611ab4613a0e565b506040611abf613aaf565b611acb82518092611892565bf35b346103ba575f3660031901126103ba5760206040517f821b6e3a557148015a918c89e5d092e878a69854a2d1a410635f771bd5a8a3f58152f35b346103ba5760203660031901126103ba5760206115c2600435613b0c565b346103ba575f3660031901126103ba576101645460405160109190911c6001600160a01b03168152602090f35b346103ba575f3660031901126103ba57631bebc11560e01b5f5260045ffd5b346103ba5760203660031901126103ba57600435611b8e8161064d565b60fb546001600160a01b0316611ba2613d87565b611bee6020611baf613dc9565b604051637ef7c88360e11b81529384928392907f06d294bc8cbad2e393408b20dd019a772661f60b8d633e56761157cb1ec85f8c883060048701613721565b0381865afa90811561094f575f91611c65575b5015611c10576108ba8361543b565b604051630cb6f8ed60e21b815260048101929092523060248301526001600160a01b031660448201527f06d294bc8cbad2e393408b20dd019a772661f60b8d633e56761157cb1ec85f8c606482015260849150fd5b611c7e915060203d6020116109485761093a81836109f6565b5f611c01565b346103ba575f3660031901126103ba576040611abf613b42565b346103ba575f3660031901126103ba5760206040517f4707e94b25cfce1a7c363508fbb838c35864388ad77284b248282b9746982b9b8152f35b346103ba5760a03660031901126103ba576004356001600160401b0381116103ba57611d08903690600401610a89565b6024356001600160401b0381116103ba57611d27903690600401610abb565b90611d30610ba1565b90611d39610b8b565b50608435916001600160401b0383116103ba5761032793611d61610d56943690600401610a89565b92613c43565b346103ba5760203660031901126103ba576004356001600160401b0381116103ba57611d979036906004016103be565b60fb546001600160a01b0316611dab613d87565b611df76020611db8613dc9565b604051637ef7c88360e11b81529384928392907f4707e94b25cfce1a7c363508fbb838c35864388ad77284b248282b9746982b9b883060048701613721565b0381865afa90811561094f575f91611e78575b5015611e23576108ba611e1e368587610a53565b61548e565b604051630cb6f8ed60e21b815260048101929092523060248301526001600160a01b031660448201527f4707e94b25cfce1a7c363508fbb838c35864388ad77284b248282b9746982b9b606482015260849150fd5b611e91915060203d6020116109485761093a81836109f6565b5f611e0a565b602081016020825282518091526040820191602060408360051b8301019401925f915b838310611ec957505050505090565b9091929394603f1982820301835285519061010081019180519261010083528351809152602061012084019401905f905b808210611f9057505050600192611f8160209360e08085611f2a8880980151888601906001600160401b03169052565b6040818101516001600160401b0316908501526060818101516001600160401b03169085015260808181015161ffff169085015260a08181015161ffff169085015260c08181015115159085015201511515910152565b97019301930191939290611eba565b9091946020608060019260608951858060a01b038151168352848101511515858401526040810151151560408401520151611fca816110ce565b6060820152019601920190611efa565b346103ba5760203660031901126103ba5760043561ffff61016454168111801561219b575b6108bc575f5261016360205260405f20805461201a81610aa4565b9161202860405193846109f6565b81835260208301905f5260205f205f915b83831061204e57604051806103278782611e97565b60405161205a816109a4565b825461206581610aa4565b9061207360405192836109f6565b80825260208201855f5260205f20905f905b8382106121425750505050600192826020926002945261213461212b868801546120c76120b8826001600160401b031690565b6001600160401b031685880152565b6120e8604082901c6001600160401b03166001600160401b03166040860152565b6001600160401b03608082901c16606085015261ffff60c082901c16608085015261ffff60d082901c1660a0850152611a3e60e082901c60ff16151560c0860152565b151560e0830152565b815201920192019190612039565b600160208192604051612154816109c0565b60ff8754858060a01b0381168352818160a01c16151585840152818160a81c161515604084015260b01c16612188816110ce565b6060820152815201930191019091612085565b508015611fff565b346103ba5760203660031901126103ba5760206115c26004356121c58161064d565b613cfb565b346103ba5760203660031901126103ba57600435805f5261016260205260405f206121f4826141c7565b506122006117ca613d87565b156122305761220e81613cfb565b1561221c576108ba91615166565b639fefd0f160e01b5f52600482905260245ffd5b6122398161375d565b15612247576108ba91615166565b637171293960e11b5f52600482905260245ffd5b346103ba5760203660031901126103ba5760fb54600435906001600160a01b0316612284613d87565b6122d06020612291613dc9565b604051637ef7c88360e11b81529384928392907ff281525e53675515a6ba7cc7bea8a81e649b3608423ee2d73be1752cea887889883060048701613721565b0381865afa90811561094f575f91612368575b501561231357826122f381613b0c565b15612301576108ba906155f7565b639fefd0f160e01b5f5260045260245ffd5b604051630cb6f8ed60e21b815260048101929092523060248301526001600160a01b031660448201527ff281525e53675515a6ba7cc7bea8a81e649b3608423ee2d73be1752cea887889606482015260849150fd5b612381915060203d6020116109485761093a81836109f6565b5f6122e3565b634e487b7160e01b5f52603260045260245ffd5b80548210156123b4575f5260205f209060011b01905f90565b612387565b634e487b7160e01b5f52601160045260245ffd5b90600182811c921680156123fb575b60208310146123e757565b634e487b7160e01b5f52602260045260245ffd5b91607f16916123dc565b818110612410575050565b5f8155600101612405565b634e487b7160e01b5f525f60045260245ffd5b8054905f81558161243d575050565b816003029160038304036124dc575f5260205f20908101905b818110612461575050565b805f600392555f60018201556002810161247b81546123cd565b908161248a575b505001612456565b601f82116001146124a1575f9055505b5f80612482565b6124c76124d7926001601f6124b9855f5260205f2090565b920160051c82019101612405565b5f81815260208120918190559055565b61249a565b6123b9565b91908110156123b45760051b81013590605e19813603018212156103ba570190565b80548210156123b4575f52600360205f20910201905f90565b90601f8211612529575050565b610a27915f516020615ac55f395f51905f525f5260205f20906020601f840160051c83019310612561575b601f0160051c0190612405565b9091508190612554565b9190601f811161257a57505050565b610a27925f5260205f20906020601f840160051c8301931061256157601f0160051c0190612405565b9092916001600160401b038111610983576125c8816125c284546123cd565b8461256b565b5f601f82116001146126065781906125f79394955f926125fb575b50508160011b915f199060031b1c19161790565b9055565b013590505f806125e3565b601f19821694612619845f5260205f2090565b915f5b87811061265357508360019596971061263a575b505050811b019055565b01355f19600384901b60f8161c191690555f8080612630565b9092602060018192868601358155019401910161261c565b8054600160401b8110156109835761268891600182018155612503565b919091612701576126b9813561269d8161064d565b83546001600160a01b0319166001600160a01b03909116178355565b60208101356001830155604081013590601e19813603018212156103ba57018035906001600160401b0382116103ba5760200181360381136103ba576002610a2793016125a3565b61241b565b908060209392818452848401375f828201840152601f01601f1916010190565b93919061273b91604086526040860191612706565b9260208185039101528083526020830160208260051b85010193835f91605e1982360301905b858410612772575050505050505090565b90919293949596601f198282030186528735838112156103ba57840180356127998161064d565b6001600160a01b0316825260208181013590830152604081013536829003601e19018112156103ba5701602081359101906001600160401b0381116103ba5780360382136103ba576127fb602092839260608681604060019901520191612706565b99019796019401929190612761565b61283092916106c0915f5261015f60205260405f209061ffff165f5260205260405f2090565b5490565b9060405191825f825492612847846123cd565b80845293600181169081156128b0575060011461286c575b50610a27925003836109f6565b90505f9291925260205f20905f915b818310612894575050906020610a27928201015f61285f565b602091935080600191548385890101520191019091849261287b565b905060209250610a2794915060ff191682840152151560051b8201015f61285f565b81601f820112156103ba578035906128e982610aa4565b926128f760405194856109f6565b82845260208085019360071b830101918183116103ba57602001925b828410612921575050505090565b6080848303126103ba57602060809160405161293c816109c0565b86356129478161064d565b815282870135612956816112a7565b838201526040870135612968816112a7565b60408201526129796060880161129a565b6060820152815201930192612913565b9291909261299684610aa4565b936129a460405195866109f6565b602085828152019060051b8201918383116103ba5780915b8383106129ca575050505050565b82356001600160401b0381116103ba57820190610100828703126103ba576129f0610a17565b908235916001600160401b0383116103ba57612a8460e085612a188b602098978998016128d2565b8452612a25868201610bb7565b86850152612a3560408201610bb7565b6040850152612a4660608201610bb7565b6060850152612a576080820161063e565b6080850152612a6860a0820161063e565b60a0850152612a7960c082016112b1565b60c0850152016112b1565b60e08201528152019201916129bc565b909293949194612ac360018060a01b0360fb5416612ab0613d87565b90612ab9613dc9565b92909130906140ca565b84612ad26101645461ffff1690565b9261ffff8416156108bc57612ae5613d87565b96612b1787604051612b0f81612b018d8860208401968761302d565b03601f1981018352826109f6565b51902061475e565b92612b2b845f5261016260205260405f2090565b95612b43876001600160401b03905460801c16151590565b612dbe5786546001600160801b0319166001600160801b038c16178755612bb190612b78612b6f613b42565b60038a016130b2565b6001880180546001600160a01b0319166001600160a01b038d16179055875461ffff60d01b191660d09190911b61ffff60d01b16178755565b6001600160401b03811680612d8757505050612bfc6001600160401b0342169897985b855467ffffffffffffffff60801b191660809190911b67ffffffffffffffff60801b16178555565b60028401975f5b8751811015612c295780612c23612c1c6001938b613104565b518c6131d7565b01612c03565b50919497509194929561ffff865111612d785796929095916001965b8651881015612cd4575f5b612c5a8989613104565b5151811015612cc85780612cc288612cbd83612cb08e61ffff8f612c8d60019a612c8785612c9e94613104565b51613104565b51965f5261016160205260405f2090565b911661ffff165f5260205260405f2090565b905f5260205260405f2090565b613118565b01612c50565b50600190970196612c45565b919585975097612d49612d639294612d397fa6c1f8f4276dc3f243459e13b557c84e8f4e90b2e09070bad5f6909cee687c92979b612d1d83546001600160401b039060801c1690565b815190919015612d6957612d30906130f7565b51905b8a6148a4565b5460801c6001600160401b031690565b6040516001600160a01b0390941697939485949185613342565b0390a390565b50612d726132c6565b90612d33565b638d48ed3360e01b5f5260045ffd5b6001600160401b03421611612da35750612bfc90989798612bd4565b636f6a0b6560e11b5f526001600160401b031660045260245ffd5b6312dba68f60e01b5f52600485905260245ffd5b92939091612dec60018060a01b0360fb5416612ab0613d87565b8094612dfc6101645461ffff1690565b9161ffff8316156108bc57612e0f613d87565b96612e2b6040516020810190612b0f81612b018d8d8d8761302d565b91612e3f835f5261016260205260405f2090565b94612e57866001600160401b03905460801c16151590565b6130195785546001600160801b0319168655612eba90612e81612e78613b42565b600389016130b2565b6001870180546001600160a01b0319166001600160a01b038d16179055865461ffff60d01b191660d09190911b61ffff60d01b16178655565b6001600160401b03811680612ffd57505050612f056001600160401b0342169796975b845467ffffffffffffffff60801b191660809190911b67ffffffffffffffff60801b16178455565b60028301965f5b8651811015612f325780612f2c612f256001938a613104565b518b6131d7565b01612f0c565b50919492959093965061ffff855111612d78579591600195915b8551871015612fa0575f5b612f618888613104565b5151811015612f945780612f8e87612cbd83612cb08d61ffff612c9e8f60019a612c8785612c8d93613104565b01612f57565b50600190960195612f4c565b918496505f612d49612d6392612d397fa6c1f8f4276dc3f243459e13b557c84e8f4e90b2e09070bad5f6909cee687c92979b9599612fe983546001600160401b039060801c1690565b90805115158614612d6957612d30906130f7565b6001600160401b03421611612da35750612f0590979697612edd565b6312dba68f60e01b5f52600484905260245ffd5b916130579061304960409396959660608652606086019061180e565b9084820360208601526106de565b6001600160a01b03909416910152565b60209060018060a01b038151166001600160601b0360a01b61012d54161761012d5501516002811015610f705761012d5460ff60a01b191660a09190911b60ff60a01b161761012d55565b815181546001600160a01b0319166001600160a01b039190911617815590602001516002811015610f7057815460ff60a01b191660a09190911b60ff60a01b16179055565b8051156123b45760200190565b80518210156123b45760209160051b010190565b91909182516001600160401b03811161098357613139816125c284546123cd565b6020601f82116001146131735781906125f79394955f926131685750508160011b915f199060031b1c19161790565b015190505f806125e3565b601f19821690613186845f5260205f2090565b915f5b8181106131bf575095836001959697106131a757505050811b019055565b01515f1960f88460031b161c191690555f8080612630565b9192602060018192868b015181550194019201613189565b9190918054600160401b811015610983576131f791600182018155612503565b61270157825181546001600160a01b0319166001600160a01b039190911617815560409060029060208501516001820155019201519182516001600160401b0381116109835761324b816125c284546123cd565b6020601f821160011461327a5781906125f79394955f926131685750508160011b915f199060031b1c19161790565b601f1982169061328d845f5260205f2090565b915f5b8181106132ae575095836001959697106131a757505050811b019055565b9192602060018192868b015181550194019201613290565b604051906132d56020836109f6565b5f80835282815b8281106132e857505050565b8060606020809385010152016132dc565b9061330382610aa4565b61331060405191826109f6565b8281528092613321601f1991610aa4565b01905f5b82811061333157505050565b806060602080938501015201613325565b926133899061337b6080946001600160401b036001600160801b03959998991687525f602088015260a0604088015260a08701906106de565b90858203606087015261180e565b9416910152565b1561339757565b60405162461bcd60e51b815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201526b19195b1959d85d1958d85b1b60a21b6064820152608490fd5b156133f857565b60405162461bcd60e51b815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201526b6163746976652070726f787960a01b6064820152608490fd5b604051906134616020836109f6565b5f808352366020840137565b906001600160401b03809116911601906001600160401b0382116124dc57565b6134a0815f5261016260205260405f2090565b80549060e082901c60ff166135e55760e882901c60ff166135dd575460801c6001600160401b0316156135c9576134de60d082901c61ffff166104e5565b9160016135086134f760c085901c61ffff16809661239b565b509360801c6001600160401b031690565b9201549261351f6001600160401b0385168461346d565b6001600160401b03429116106135c0574261355761354b604087901c6001600160401b03165b8661346d565b6001600160401b031690565b116135b85760d084901c61ffff16928361358b575b5061357e9360c01c61ffff1691614edc565b613586575f90565b600390565b6135ad61354b42926135a7886001600160401b039060801c1690565b9061346d565b116135b8575f61356c565b505050505f90565b50505050600490565b630853c2a360e41b5f52600482905260245ffd5b505050600190565b505050600290565b92613601845f5261016260205260405f2090565b9161361c610520846001600160401b03905460801c16151590565b6136cb57825460c01c61ffff1661ffff811661ffff8316116136af575061364e90613645613d87565b948591876150c5565b156136aa5761365c90615139565b1561369c5761366a81613cfb565b80613681575b613678575050565b610a2791615166565b50600361368d8361348d565b61369681610f66565b14613670565b6136a58161375d565b61366a565b505050565b63d0a90c2d60e01b5f5261ffff9081166004521660245260445ffd5b630853c2a360e41b5f52600485905260245ffd5b916106c06137079260ff945f5261016060205260405f209061ffff165f5260205260405f2090565b541690565b908160209103126103ba5751610689816112a7565b6001600160a01b03918216815291166020820152604081019190915260806060820181905261068993910191612706565b6040513d5f823e3d90fd5b60fb546137db916020916001600160a01b0316613778613dc9565b604051637ef7c88360e11b81523060048201526001600160a01b0390941660248501527fb014ce248804cab6a144581acce1eeb70ce5d54f08433b989d73bb0ccee3d3f96044850152608060648501529294859384928392916084840191612706565b03915afa90811561094f575f916137f0575090565b610689915060203d6020116109485761093a81836109f6565b91908260409103126103ba57604051613821816109db565b6020819380356138308161064d565b835201359060028210156103ba5760200152565b1561384b57565b60405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608490fd5b9593916138ef9593915f54976138d560ff8a60081c16151515809a8161396e575b811561394e575b50613844565b886138e6600160ff195f5416175f55565b6139375761397c565b6138f557565b61390361ff00195f54165f55565b604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989080602081015b0390a1565b61394961010061ff00195f5416175f55565b61397c565b303b15915081613960575b505f6138cf565b60ff1660011490505f613959565b600160ff82161091506138c8565b94610a27969491611e1e936139e29561169f986139a860ff5f5460081c166139a3816153db565b6153db565b60018060a01b03166001600160601b0360a01b60fb54161760fb55806139f8575b50506001600160a01b0381166139e9575b503691610a53565b3690613809565b6139f29061543b565b5f6139da565b613a07916108b5913691612989565b5f806139c9565b60405190613a1b826109db565b5f6020838281520152565b908154613a3281610aa4565b92613a4060405194856109f6565b81845260208401905f5260205f205f915b838310613a5e5750505050565b60036020600192604051613a7181610968565b848060a01b0386541681528486015483820152613a9060028701612834565b6040820152815201920192019190613a51565b6002821015610f705752565b60405190613abc826109db565b61012d546001600160a01b0381168352610a279060a01c60ff1660208401613aa3565b90610a27604051613aef816109db565b92546001600160a01b038116845260a01c60ff1660208401613aa3565b805f52610162602052613b2260405f209161348d565b6005811015610f70576003149081613b38575090565b6106899150615139565b613b4a613a0e565b50613b53613aaf565b80516001600160a01b031615613b665790565b5060fb54604051906001600160a01b0316613b80826109db565b81525f602082015290565b9080601f830112156103ba57815191613ba383610aa4565b92613bb160405194856109f6565b80845260208085019160051b830101918383116103ba5760208101915b838310613bdd57505050505090565b82516001600160401b0381116103ba57820185603f820112156103ba57602081015191613c0983610a38565b613c1660405191826109f6565b83815260408385010188106103ba575f602085819660408397018386015e83010152815201920191613bce565b919093929384518501946020818188019703126103ba576020810151906001600160401b0382116103ba57019285603f850112156103ba576020840151613c8981610aa4565b94613c9760405196876109f6565b8186526020808088019360051b83010101918883116103ba5760408201905b838210613ccc5750505050610689949550612dd2565b81516001600160401b0381116103ba57602091613cf08c8480809589010101613b8b565b815201910190613cb6565b60fb546137db916020916001600160a01b0316613d16613dc9565b604051637ef7c88360e11b81523060048201526001600160a01b0390941660248501527ff281525e53675515a6ba7cc7bea8a81e649b3608423ee2d73be1752cea8878896044850152608060648501529294859384928392916084840191612706565b5f198101919082116124dc57565b610164543360109190911c6001600160a01b03161480613dbe575b15613dba5760131936013681116124dc573560601c90565b3390565b506014361015613da2565b610164543360109190911c6001600160a01b03161480613e01575b15613dfb576013193601903682116124dc575f9190565b5f903690565b506014361015613de4565b604051637ef7c88360e11b81526001600160a01b039091169492939192909160209183918291613e62917fa73a22e0fc9b71a5463a75c9711d02d08dae26e85aa1033f4416b719a0239107898960048701613721565b0381875afa90811561094f575f91613ed7575b5015613e8057505050565b604051630cb6f8ed60e21b815260048101939093526001600160a01b0390811660248401521660448201527fa73a22e0fc9b71a5463a75c9711d02d08dae26e85aa1033f4416b719a0239107606482015260849150fd5b613ef0915060203d6020116109485761093a81836109f6565b5f613e75565b604051637ef7c88360e11b81526001600160a01b039091169492939192909160209183918291613f4c917f821b6e3a557148015a918c89e5d092e878a69854a2d1a410635f771bd5a8a3f5898960048701613721565b0381875afa90811561094f575f91613fc1575b5015613f6a57505050565b604051630cb6f8ed60e21b815260048101939093526001600160a01b0390811660248401521660448201527f821b6e3a557148015a918c89e5d092e878a69854a2d1a410635f771bd5a8a3f5606482015260849150fd5b613fda915060203d6020116109485761093a81836109f6565b5f613f5f565b604051637ef7c88360e11b81526001600160a01b039091169492939192909160209183918291614036917fbdfef02014e2b7a6c80226083f80d72d22fcf656d917f92d242c5b61e108bcd3898960048701613721565b0381875afa90811561094f575f916140ab575b501561405457505050565b604051630cb6f8ed60e21b815260048101939093526001600160a01b0390811660248401521660448201527fbdfef02014e2b7a6c80226083f80d72d22fcf656d917f92d242c5b61e108bcd3606482015260849150fd5b6140c4915060203d6020116109485761093a81836109f6565b5f614049565b604051637ef7c88360e11b81526001600160a01b039091169492939192909160209183918291614120917f8c433a4cd6b51969eca37f974940894297b9fcf4b282a213fea5cd8f85289c90898960048701613721565b0381875afa90811561094f575f91614195575b501561413e57505050565b604051630cb6f8ed60e21b815260048101939093526001600160a01b0390811660248401521660448201527f8c433a4cd6b51969eca37f974940894297b9fcf4b282a213fea5cd8f85289c90606482015260849150fd5b6141ae915060203d6020116109485761093a81836109f6565b5f614133565b6005811015610f705760ff600191161b90565b6141d08161348d565b9060086141dc836141b4565b16156141e6575090565b906005811015610f705760ff91632c2eee6560e11b5f5260045216602452600860445260645ffd5b906142188261348d565b9181614223846141b4565b161561422e57505090565b826005811015610f705760ff91632c2eee6560e11b5f526004521660245260445260645ffd5b61ffff1661ffff81146124dc5760010190565b8054600160401b811015610983576142849160018201815561239b565b9091565b90600182018092116124dc57565b51610689816110ce565b80548210156123b4575f5260205f2001905f90565b8054600160401b811015610983576142d2916001820181556142a0565b91909161270157805182546001600160a01b0319166001600160a01b03919091161782556020810151825460ff60a01b191690151560a01b60ff60a01b1617604082015160ff60a81b90151560a81b1660ff60a81b19821681178455606090920151909190614340816110ce565b614349816110ce565b61ffff60a81b199092161760b09190911b60ff60b01b16179055565b61439661437e6143796101645461ffff1690565b614254565b6104e58161ffff1661ffff1961016454161761016455565b5f915b805183101561472a576143ab82614267565b50936143b78483613104565b5151916143d860206143c98784613104565b5101516001600160401b031690565b6143e760406143c98885613104565b916143f760606143c98984613104565b9361441160806144078a85613104565b51015161ffff1690565b61442060a06144078b86613104565b916001600160401b038516806001600160401b0388161090811591614716575b506147075787518061ffff8416119081156146f9575b506146ea575f985b88518a10156145bd576144708a614288565b89518110156144fc57896144b26144a6614492848f6144926144a09187613104565b51516001600160a01b031690565b94613104565b6001600160a01b031690565b6001600160a01b03909116146144ca57600101614470565b6105c98c6144db6144928e8e613104565b635169d4b960e11b5f526004919091526001600160a01b0316602452604490565b50986145186105206020614510848d613104565b510151151590565b8061459f575b614590576145386060614531838c613104565b5101614296565b614541816110ce565b15614565578061455e8d6145576001948d613104565b51906142b5565b019861445e565b6145756144926105c9928b613104565b63385ccd4360e11b5f526001600160a01b0316600452602490565b632c7ca6d760e01b5f5260045ffd5b506145b86105206145b3614492848d613104565b615752565b61451e565b9850989560019750906146556146719261462d6146e2986145fb61468d989f8d01998a906001600160401b03166001600160401b0319825416179055565b88546fffffffffffffffff0000000000000000191660409190911b6fffffffffffffffff000000000000000016178855565b865467ffffffffffffffff60801b191660809190911b67ffffffffffffffff60801b16178655565b845461ffff60c01b191660c09190911b61ffff60c01b16178455565b825461ffff60d01b191660d09190911b61ffff60d01b16178255565b6146b961469f60c0614510868b613104565b825460ff60e01b191690151560e01b60ff60e01b16178255565b6146c860e0614510858a613104565b815460ff60e81b191690151560e81b60ff60e81b16179055565b019192614399565b635813b74160e01b5f5260045ffd5b905061ffff8416115f614456565b631f7b222b60e31b5f5260045ffd5b90506001600160401b03881610155f614440565b7f435d9e99466e98c43eea30339b592c89335a9cd4304822838938882df53308fe9250613932915060405191829182611e97565b604051602081019146835243604083015230606083015260808201526080815261478960a0826109f6565b51902090565b60408051919061479f90836109f6565b6001825281601f196147b16001610aa4565b01905f5b8281106147c157505050565b6020906040516147d081610968565b5f81525f8382015260606040820152828285010152016147b5565b9261ffff606093969592966080860197865216602085015261480c816110ce565b60408401521515910152565b91936001600160401b0361484c61068997959661483e839560a0885260a08801906106de565b90868203602088015261180e565b9516604084015216606082015260808184039101526106de565b3d15614890573d9061487782610a38565b9161488560405193846109f6565b82523d5f602084013e565b606090565b908160209103126103ba575190565b9291906148cf5f6104f86104e56148c4885f5261016260205260405f2090565b5460d01c61ffff1690565b5060018101905f5b8154811015614b8f576148ea81836142a0565b50908154888688876149008560ff9060a01c1690565b614b81575f809492936149f987612b0184976149c36135458798886149568c612b0161492a61478f565b9960ff60b082901c81169160a81c16906040519586946329181cb160e11b6020870152602486016147eb565b61495e610a29565b308152908a60208301526040820152614976876130f7565b52614980866130f7565b50612d396149955a9f6001600160a01b031690565b604080513060208201529081019d909d5261ffff9b909b166060808e01919091528c52999a9960808b6109f6565b908c808251118814614b71576149d891613104565b51905b6040519586946020860199637532d5c160e11b8b5260248701614818565b51925af19289614a07614866565b925a908615614b50575b50508460019590614b45575b15614ad3577fdc04d6b37a483003e6bdc5660d9d9bb22854fffba622b62f658a398efc88ca44614ac9614a5b856020805f9798518301019101614895565b9485614aa4614a8887614a77885f5261015f60205260405f2090565b9061ffff165f5260205260405f2090565b83546001600160a01b03165f9081526020919091526040902090565b555460405195865260a088901b889003166001600160a01b0316949081906020820190565b0390a45b016148d7565b7fe03b818c74400ef42fafb3f6cfa61d8a38950d4f403eee88ec39bc0cafe54d24614b3d5f93614b1c614b16614a8887614a77885f5261015f60205260405f2090565b5f199055565b5460a088901b889003906001600160a01b0316169460405191829182610702565b0390a4614acd565b506020835114614a1d565b60061c119050614b6257895f80614a11565b6307099c5360e21b5f5260045ffd5b5050614b7b613452565b906149db565b505050505060019150614acd565b50505050509050565b939293919091614bbb836104f86104e56148c4855f5261016260205260405f2090565b5060018101905f5b8154811015614e2557614bd681836142a0565b509086825492614bea8460ff9060a01c1690565b614e1a5786614bf761478f565b6040516329181cb160e11b602082015280614c2660ff60a88a901c81169060b08b901c168887602486016147eb565b03601f1981018252614c3890826109f6565b614c40610a29565b308152905f60208301526040820152614c58826130f7565b52614c62816130f7565b508c5a6040805130602082015290810185905261ffff8716606080830191909152815290976001600160a01b031690614c9c6080826109f6565b8a548d9060801c6001600160401b0316614cb59161346d565b928d89808351115f1496612b015f9897899895614cdb948a97614b71576149d891613104565b51925af194614ce8614866565b905a908715614e03575b50508560019690614df8575b15614d845761ffff614d67614d3d836020807fdc04d6b37a483003e6bdc5660d9d9bb22854fffba622b62f658a398efc88ca4496518301019101614895565b9485614d59614a8889614a77895f5261015f60205260405f2090565b55546001600160a01b031690565b60405194855260a088901b88900316941692602090a45b01614bc3565b9161ffff614dd77fe03b818c74400ef42fafb3f6cfa61d8a38950d4f403eee88ec39bc0cafe54d2492614dca614b16614a8889614a77895f5261015f60205260405f2090565b546001600160a01b031690565b614df06040519283928a8060a01b031697169582610702565b0390a4614d7e565b506020815114614cfe565b919450915060061c11614b62578689925f80614cf2565b505060019150614d7e565b5050505050509050565b15614e3657565b60405162461bcd60e51b815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f786044820152681a58589b195555525160ba1b6064820152608490fd5b60809060208152602e60208201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960408201526d6f6e206973206e6f74205555505360901b60608201520190565b90614ee991939293614f28565b90918015159182614f0f575b5050614f095710614f0557600190565b5f90565b50505f90565b101590505f80614ef5565b5f1981146124dc5760010190565b90915f925f92614f4b826104f86104e56148c4855f5261016260205260405f2090565b50918254915f935b838510614f61575050505050565b9091929396614f7088836142a0565b50546001600160a01b03811690614f8882878761280a565b91614f948188886136df565b92614f9e846110ce565b8315614fe25750505080614fb36001926110ce565b03614fcf57614fc3600191614f1a565b975b0193929190614f53565b9695614fdc600191614f1a565b96614fc5565b939a93919250905f19811415806150b6575b615004575b505050600190614fc5565b5f91829160405161502f81612b01602082019463610c609960e11b8652602483019190602083019252565b51915afa61503b614866565b90806150ab575b61504d575b80614ff9565b806020806150609351830101910161370c565b61506b575b80615047565b90979060019060b01c60ff16615080816110ce565b0361509857615090600191614f1a565b975b90615065565b96956150a5600191614f1a565b96615092565b506020815114615042565b5060ff60a084901c1615614ff4565b919261ffff9193835f526101606020526150f2826106c08760405f209061ffff165f5260205260405f2090565b906150fc816110ce565b60ff8019835416911617905560018060a01b03169216907fbfaa970a350cc4e6c21888b5c4b888e2750f035ce824e40cfc7dc5f07e3936c55f80a4565b5461ffff8160d01c165f5261016360205260405f2054905f1982019182116124dc5760c01c61ffff161490565b919061517b835f5261016260205260405f2090565b9283549261519f6151946104e58661ffff9060d01c1690565b9460c01c61ffff1690565b61ffff6151ac8654613d79565b911610156152c95784546151c69060c01c61ffff16614254565b855460c082901b61ffff60c01b1669ffffffffffffffffffff60801b199091161742608081901b67ffffffffffffffff60801b16919091179096556001600160401b03909516949261522261521b858761239b565b50546132f9565b955f5b61522f868861239b565b5054811015615281578560018261526261525d61522f95612cb086614a778d5f5261016160205260405f2090565b612834565b61526c828d613104565b52615277818c613104565b5001915050615225565b5061ffff93949550956152979192968686614b98565b6001600160a01b03169216907fa21690322ce39bce6ee8416aefbe1e66cf767ff37e9db8f708a3c6cbbf17db9b5f80a4565b93509050610a2791506155f7565b80516001600160a01b03166152eb8161596b565b9081615375575b5080615354575b615337576139328161532b7f88e879ae0d71faf3aa708f2978daccb99b95243615dc104835b8c5a21c884ae693613067565b60405191829182611a8c565b60405163266d0fb960e01b8152908190610e879060048301611a8c565b5060208101516002811015610f70578061536f600192611888565b146152f9565b602091505f90604051838101906301ffc9a760e01b8252632a4f53ad60e11b6024820152602481526153a86044826109f6565b5191617530fa5f513d826153cf575b50816153c5575b505f6152f2565b905015155f6153be565b6020111591505f6153b7565b156153e257565b60405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608490fd5b610164805462010000600160b01b031916601083901b62010000600160b01b03161790556001600160a01b03167fa4388ecc389b1390354ae0c65a856c0d7dd4fb648419f5d3ac0b99e38f46fd115f80a2565b908151916001600160401b038311610983576154c0836154bb5f516020615ac55f395f51905f52546123cd565b61251c565b602092601f811160011461553a579061551482613932937fbb39ebb37e60fb5d606ffdb749d2336e56b88e6c88c4bd6513b308f643186eed95965f9161552f575b508160011b915f199060031b1c19161790565b5f516020615ac55f395f51905f525560405191829182610702565b90508301515f615501565b5f516020615ac55f395f51905f525f52601f1981167f20120d26379ad35b0c68e58a20f1251f24acf3aee87d3a8d8759c48671c8cace905f5b8181106155df5750916001917fbb39ebb37e60fb5d606ffdb749d2336e56b88e6c88c4bd6513b308f643186eed9596826139329695106155c7575b5050811b015f516020615ac55f395f51905f5255611501565b8401515f1960f88460031b161c191690555f806155ae565b84870151835560209687019660019093019201615573565b5f81815261016260205260409020805460ff60e01b198116600160e01b178255600382015460a081901c60ff16926001600160a01b03909116916001600160801b03169060019061564a90600201613a26565b9361565481611888565b036156ef57905f92612b01615683859460405192839160208301956331c6fcc960e21b87528a60248501615949565b51915af461568f614866565b90156156d157806020806156a893518301019101615919565b50505b7f712ae1383f79ac853f8d882153778e0260ef8f03b504e2866e0593e04d2b291f5f80a2565b8051156156e057805190602001fd5b6318cecad560e01b5f5260045ffd5b5f9161571393836040518096819582946331c6fcc960e21b84528a60048501615949565b03925af1801561094f575f915f9161572e575b5050506156ab565b905061574c91503d805f833e61574481836109f6565b810190615919565b5f615726565b61575b8161596b565b9081615765575090565b602091505f90604051838101906301ffc9a760e01b8252633f4644d160e21b6024820152602481526157986044826109f6565b5191617530fa5f513d826157b8575b50816157b1575090565b9050151590565b6020111591505f6157a7565b916157ce83615882565b6001600160a01b0383167fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b5f80a28151159081159161587a575b50615811575050565b615877915f80604051936158266060866109f6565b602785527f416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c6020860152660819985a5b195960ca1b6040860152602081519101845af4615871614866565b91615a33565b50565b90505f615808565b803b156158be5760018060a01b03166001600160601b0360a01b5f516020615ae55f395f51905f525416175f516020615ae55f395f51905f5255565b60405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b6064820152608490fd5b91906040838203126103ba5782516001600160401b0381116103ba57602091615943918501613b8b565b92015190565b93929161596690604092865260606020870152606086019061180e565b930152565b60205f604051828101906301ffc9a760e01b82526301ffc9a760e01b60248201526024815261599b6044826109f6565b519084617530fa903d5f519083615a27575b5082615a1d575b50816159be575090565b602091505f90604051838101906301ffc9a760e01b825263ffffffff60e01b6024820152602481526159f16044826109f6565b5191617530fa5f513d82615a11575b5081615a0b57501590565b15919050565b6020111591505f615a00565b151591505f6159b4565b6020111592505f6159ad565b91929015615a955750815115615a47575090565b3b15615a505790565b60405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606490fd5b825190915015615aa85750805190602001fd5b60405162461bcd60e51b8152908190610e87906004830161070256fe47ff9796f72d439c6e5c30a24b9fad985a00c85a9f2258074c400a94f8746b00360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbca264697066735822122007715bb6b38669f83c106899679117f83b81d207060f277593591379a095fb9564736f6c634300081c0033608080604052346105ca57611a5c803803809161001c82856105ce565b833981016040828203126105ca5781516001600160a01b03811692908390036105ca576020810151906001600160401b0382116105ca57019080601f830112156105ca578151906001600160401b03821161028d576040519261008560208460051b01856105ce565b82845260208401916020839460071b830101918183116105ca57602001925b82841061055157505050505f549260ff8460081c161593848095610544575b801561052d575b156104d15760ff1981166001175f55846104bf575b5060ff5f5460081c161561046657603380546001600160a01b0319169190911790558151610157575b505061011e575b60405161138790816106d58239f35b61ff00195f54165f557f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498602060405160018152a161010f565b5f5b82518110156102b05761016c81846105ff565b519060ca60ff83511614610185575b6001915001610159565b60405160209261019584836105ce565b5f8252604051906101e5826101d7878201956302675fdd60e41b87526001602484015260026044840152600160648401526080608484015260a4830190610613565b03601f1981018452836105ce565b604060018060a01b0391015116935f806060946040519461020687876105ce565b602586527f416464726573733a206c6f772d6c6576656c207374617469632063616c6c20668587015264185a5b195960da1b60408701525190885afa923d156102a157503d926001600160401b03841161028d576001956102879483601f19601f830116019061027960405192836105ce565b81525f81943d92013e610637565b5061017b565b634e487b7160e01b5f52604160045260245ffd5b60019561028794919250610637565b50916097545f609755806103f7575b505f5b825181101561035f576102d581846105ff565b5190609754916801000000000000000083101561028d57600183018060975583101561034b5760016060819460975f5260205f2090831b019260ff81511660ff198554161784556020810151845460ff61ff0061ffff19604086015160101b169360081b169116171784550151910155016102c2565b634e487b7160e01b5f52603260045260245ffd5b509160405191602083019060208452518091526040830191905f5b8181106103b25750505090807f6517634f0cf2fee5bec4e10d9a05e7a61f4e8610d8db2b83bc84416b3dc0f666920390a15f80610108565b909192602060806001926060875160ff815116835260ff858201511685840152858060f01b03604082015116604084015201516060820152019401910191909161037a565b6001600160ff1b03811681036104525760975f5260011b7f354a83ed9988f79f6038d4c7a7dadbad8af32f4ad6df893e0e5807a1b1944ff9908101905b81811061044157506102bf565b5f8082556001820155600201610434565b634e487b7160e01b5f52601160045260245ffd5b60405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608490fd5b61ffff1916610101175f9081556100df565b60405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608490fd5b50303b1580156100ca5750600160ff8216146100ca565b50600160ff8216106100c3565b6080848303126105ca5760405190608082016001600160401b0381118382101761028d57604052610581856105f1565b825261058f602086016105f1565b60208301526040850151906001600160f01b03821682036105ca578260209260406080950152606087015160608201528152019301926100a4565b5f80fd5b601f909101601f19168101906001600160401b0382119082101761028d57604052565b519060ff821682036105ca57565b805182101561034b5760209160051b010190565b805180835260209291819084018484015e5f828201840152601f01601f1916010190565b91929015610699575081511561064b575090565b3b156106545790565b60405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606490fd5b8251909150156106ac5750805190602001fd5b60405162461bcd60e51b8152602060048201529081906106d0906024830190610613565b0390fdfe60806040526004361015610011575f80fd5b5f3560e01c806301ffc9a7146100c45780631498b514146100bf57806323e8cefc146100ba5780632675fdd0146100b55780632ae9c600146100b05780634162169f146100ab57806345e2984a146100a65780638306b5f1146100a1578063b580939c1461009c578063d09e5361146100975763e87c7fa814610092575f80fd5b610627565b6104d0565b610496565b610437565b6103be565b61032e565b61029f565b61021b565b6101a2565b61014f565b3461014b57602036600319011261014b5760043563ffffffff60e01b811680910361014b576328fcde5960e21b8114908115610109575b506040519015158152602090f35b6302675fdd60e41b81149150811561013b575b811561012a575b505f6100fb565b6301ffc9a760e01b1490505f610123565b621574e360e91b8114915061011c565b5f80fd5b3461014b57602036600319011261014b57606063ffffffff8061018960043563ffffffff81169163ffffffff808360201c169260401c1690565b9193908160405195168552166020840152166040820152f35b3461014b57606036600319011261014b576004356024356044359060201b82018092116101ea5760401b81018091116101ea576040516001600160f01b039091168152602090f35b61073b565b600435906001600160a01b038216820361014b57565b602435906001600160a01b038216820361014b57565b3461014b57608036600319011261014b576102346101ef565b61023c610205565b9060443560643567ffffffffffffffff811161014b573660238201121561014b57806004013567ffffffffffffffff811161014b573691016024011161014b5761029b926102899261074f565b60405190151581529081906020820190565b0390f35b3461014b575f36600319011261014b5760606040516102be8282610538565b3690376040516060810181811067ffffffffffffffff8211176103295760405260018152600460208201525f604082015260405180916060820190825f905b6003821061030c575050500390f35b825160ff16815285945060209283019260019290920191016102fd565b610508565b3461014b575f36600319011261014b576033546040516001600160a01b039091168152602090f35b60206040818301928281528451809452019201905f5b8181106103795750505090565b909192602060806001926060875160ff815116835260ff858201511685840152858060f01b03604082015116604084015201516060820152019401910191909161036c565b3461014b575f36600319011261014b576097546103da8161055a565b906103e86040519283610538565b8082526020820160975f525f5160206113325f395f51905f525f915b838310610419576040518061029b8782610356565b60026020600192610429856107e4565b815201920192019190610404565b3461014b57602036600319011261014b5760043567ffffffffffffffff811161014b573660238201121561014b57806004013567ffffffffffffffff811161014b573660248260071b8401011161014b576024610494920161081a565b005b3461014b575f36600319011261014b5760206040517fd3d98e95f3486fc234d80c098cf0d2a0a3fb187833d7e9cc930f8c4f8335a0e78152f35b3461014b57604036600319011261014b5760043560243560201b81018091116101ea576040516001600160f01b039091168152602090f35b634e487b7160e01b5f52604160045260245ffd5b6080810190811067ffffffffffffffff82111761032957604052565b90601f8019910116810190811067ffffffffffffffff82111761032957604052565b67ffffffffffffffff81116103295760051b60200190565b359060ff8216820361014b57565b92919261058c8261055a565b9361059a6040519586610538565b602085848152019260071b82019181831161014b57925b8284106105be5750505050565b60808483031261014b57604051906105d58261051c565b6105de85610572565b82526105ec60208601610572565b60208301526040850135906001600160f01b038216820361014b578260209260406080950152606087013560608201528152019301926105b1565b3461014b57604036600319011261014b576106406101ef565b60243567ffffffffffffffff811161014b573660238201121561014b576106746106b3913690602481600401359101610580565b5f549261069960ff600886901c16158095819661072d575b811561070d575b5061095f565b836106aa600160ff195f5416175f55565b6106f6576109c2565b6106b957005b6106c75f5461ff0019165f55565b604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb384740249890602090a1005b6107086101005f5461ff001916175f55565b6109c2565b303b1591508161071f575b505f610693565b60ff1660011490505f610718565b600160ff821610915061068c565b634e487b7160e01b5f52601160045260245ffd5b909160975461075d8161055a565b9061076b6040519283610538565b8082526020820160975f525f5160206113325f395f51905f525f915b8383106107c6575050505051156107be576107bb92604051926107ab602085610538565b5f8085523660208601375f610ae9565b90565b505050600190565b600260206001926107d6856107e4565b815201920192019190610787565b906040516107f18161051c565b606060018294805460ff8116855260ff8160081c16602086015260101c60408501520154910152565b603354604051637ef7c88360e11b81523060048201523360248201527fd3d98e95f3486fc234d80c098cf0d2a0a3fb187833d7e9cc930f8c4f8335a0e760448201526080606482015236608482018190526001600160a01b03909216949392915f60a48301375f60a4368301015260208160a481601f19601f3601168101030181885afa908115610946575f91610917575b50156108bf576108bd92935061094b565b565b604051630cb6f8ed60e21b81526001600160a01b03851660048201523060248201523360448201527fd3d98e95f3486fc234d80c098cf0d2a0a3fb187833d7e9cc930f8c4f8335a0e7606482015280608481015b0390fd5b610939915060203d60201161093f575b6109318183610538565b810190610c99565b5f6108ac565b503d610927565b610cb1565b61095a906108bd923691610580565b610d67565b1561096657565b60405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608490fd5b60ff5f5460081c1615610a015760018060a01b03166bffffffffffffffffffffffff60a01b603354161760335580516109f85750565b6108bd90610d67565b60405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608490fd5b634e487b7160e01b5f52603260045260245ffd5b609754811015610a8a5760975f5260205f209060011b01905f90565b610a5a565b8054821015610a8a575f5260205f209060011b01905f90565b8051821015610a8a5760209160051b010190565b600d1115610ac657565b634e487b7160e01b5f52602160045260245ffd5b60ff16600d811015610ac65790565b610af9610aff9195939495610a6e565b506107e4565b9260cb60ff610b0f865160ff1690565b1614610c8d57604084018051909290610b38906001600160f01b03165b6001600160f01b031690565b95610b44865160ff1690565b60ff811660ca8103610bf457505060608601519351959650610b8f95610b8290610b769081906001600160f01b031681565b6001600160a01b031690565b9380610bec575092610fc7565b15610be45760ff60015b1660206001925b01916007610bb7610bb2855160ff1690565b610ada565b610bc081610abc565b14610bdc57610bd6610bb26107bb945160ff1690565b91611044565b509050151590565b60ff5f610b99565b905092610fc7565b925092505060c881949394145f14610c13575050505060204391610ba0565b60c98103610c28575050505060204291610ba0565b60cc8103610c50575050905160209150610c4a906001600160f01b0316610b2c565b91610ba0565b9091809350511115610c8557610b2c610c78602093610c72610c4a9460ff1690565b90610aa8565b516001600160f01b031690565b505050505f90565b906107bb949293610e0f565b9081602091031261014b5751801515810361014b5790565b6040513d5f823e3d90fd5b67ffffffffffffffff811161032957601f01601f191660200190565b60405190610ce7602083610538565b5f8252565b805180835260209291819084018484015e5f828201840152601f01601f1916010190565b9060806107bb926001815260026020820152600160408201528160608201520190610cec565b6001600160a01b0391821681529116602082015260408101919091526080606082018190526107bb92910190610cec565b905f5b8251811015610e045780610d8060019285610aa8565b5160ca610d97610d91835160ff1690565b60ff1690565b14610da4575b5001610d6a565b610ddc610df8610b76610b766040610dfd95610dea610dc1610cd8565b83516302675fdd60e41b602082015297889160248301610d10565b03601f198101885287610538565b01516001600160f01b031690565b6110d2565b505f610d9d565b50906108bd906111d9565b939091926020850193600c610e28610bb2875160ff1690565b610e3181610abc565b14610f4757610e7a838383610e72610e57610b2c60408b9c9d015160018060f01b031690565b63ffffffff81169163ffffffff808360201c169260401c1690565b509890610ae9565b6008610e8a610bb2895160ff1690565b610e9381610abc565b14610f3c578080610f1c575b610f105715948580610ef0575b610ee557610eb994610ae9565b610eca610bb2600b92945160ff1690565b610ed381610abc565b14610edc575090565b15901515141590565b505050505050505f90565b506009610f01610bb2895160ff1690565b610f0a81610abc565b14610eac565b50505050505050600190565b50600a610f2d610bb2895160ff1690565b610f3681610abc565b14610e9f565b955050505050501590565b829450610f77819383610f6d610e57610b2c60408a9c9a989a015160018060f01b031690565b9a91959095610ae9565b6107bb969015610f875750610ae9565b9050610ae9565b60206040818301928281528451809452019201905f5b818110610fb15750505090565b8251845260209384019390920191600101610fa4565b905f936110178594610feb610feb610ff961101f9a60405192839160208301610f8e565b03601f198101835282610538565b60405194859360208501976302675fdd60e41b895260248601610d36565b51915afa1590565b611040573d6020810361103b57604051905f823e5f8151915290565b505f90565b5f90565b909161104f81610abc565b600181146110cd5761106081610abc565b600281146110c75761107181610abc565b600381146110c25761108281610abc565b600481146110bd5761109381610abc565b600581146110b757806110a7600692610abc565b146110b25750505f90565b111590565b50101590565b501090565b501190565b50141590565b501490565b906107bb915f80604051936110e8606086610538565b602585527f416464726573733a206c6f772d6c6576656c207374617469632063616c6c2066602086015264185a5b195960da1b6040860152602081519101845afa3d15611156573d9161113a83610cbc565b926111486040519485610538565b83523d5f602085013e611298565b606091611298565b634e487b7160e01b5f525f60045260245ffd5b609754680100000000000000008110156103295780600161119792016097556097610a8f565b9190916111d45780516020820151604083015161ffff1960109190911b1660ff90921660089190911b61ff00161717825560600151600190910155565b61115e565b6097545f60975580611245575b505f5b815181101561120e578061120861120260019385610aa8565b51611171565b016111e9565b506112407f6517634f0cf2fee5bec4e10d9a05e7a61f4e8610d8db2b83bc84416b3dc0f6669160405191829182610356565b0390a1565b6001600160ff1b03811681036101ea5760975f5260011b5f5160206113325f395f51905f52015f5160206113325f395f51905f525b81811061128757506111e6565b5f808255600182015560020161127a565b919290156112fa57508151156112ac575090565b3b156112b55790565b60405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606490fd5b82519091501561130d5750805190602001fd5b60405162461bcd60e51b815260206004820152908190610913906024830190610cec56fe354a83ed9988f79f6038d4c7a7dadbad8af32f4ad6df893e0e5807a1b1944ff9a2646970667358221220f6a4d9a0e6665d7f0c42efe7fecd3a28ebb96664195a8956a23d1cdb52f00fb664736f6c634300081c0033
Deployed Bytecode
0x6080806040526004361015610012575f80fd5b5f3560e01c90816301ffc9a71461142a575080632ae9c600146113ad5780635c60da1b146113695780637da5dd7c146113255780639cb0a12414610e59578063a8a9c29e14610df55763f10832f114610069575f80fd5b34610b42576040366003190112610b4257610082611494565b6001600160401b0360243511610b4257366023602435011215610b4257602435600401356001600160401b038111610b4257366024828135010111610b42576100c96115e3565b60a06024358381010312610b42576024803501356001600160401b038111610b4257602435019060248381350101604383011215610b4257602482013561010f816115fc565b9261011d60405194856115ae565b8184526024803586010160448284010111610b4257815f926044602093018387013784010152604460243501356001600160401b038111610b42576024848135010160438260243501011215610b425760248181350101359061017f82611617565b9161018d60405193846115ae565b8083526020830190819260248881350101602060248460051b8482350101010111610b42576044816024350101925b60446024358301600585901b01018410610bb55750505050606460243501356001600160401b038111610b4257602435019560248681350101604388011215610b425760248701359561020e87611617565b9761021c604051998a6115ae565b878952602089019060206024839a60071b8301010190602484813501018211610b4257604401915b818310610b465750505060409060246083199181359082350103010112610b42576040519161027283611578565b6102806084602435016114aa565b835260a46024350135916002831015610b4257602084979592970192835260018060a01b0316956040519463bfde57c360e01b602087015260e48601928860248801525f604488015260c06064880152518093526101048601926101048160051b88010192935f905b828210610a3c575050508582036023190160848701526103099250611539565b91516001600160a01b031660a48401525160028110156108ca5761033c91839160c483015203601f1981018352826115ae565b604051906103c690818301908382106001600160401b03831117610a285760406103a192859461178a86397f0000000000000000000000006ab6528e0d5a0f7c5738adfe6bc92dabc501d5066001600160a01b03168152602081018290520190611539565b03905ff08015610a1d5760018060a09695961b03169360405193846020810192631d0f8ff560e31b8452606482019286602484015260406044840152518093526084820190925f5b8181106109d4575050610405925003601f1981018652856115ae565b6e5af43d82803e903d91602b57fd5bf37f000000000000000000000000feb8a7ed4ab17cd2928f097b6622dc560b576e90763d602d80600a3d3981f3363d3d373d3d3d363d7300000062ffffff8260881c16175f5260781b17602052603760095ff06001600160a01b03811694908515610996578151610913575b505050610140916040519261049581856115ae565b60098452601f19015f5b8181106108de5750506040516104b481611593565b5f81528560208201528160408201525f60608201527f6f36f8bf0398781285f5a40c489dbf3268ce3e205aba87f21e49e6805391b5a160808201526104f88461165d565b526105028361165d565b5060405161050f81611593565b5f808252602082018790526001600160a01b03604083015260608201527ff281525e53675515a6ba7cc7bea8a81e649b3608423ee2d73be1752cea887889608082015261055b8461166a565b526105658361166a565b5060405161057281611593565b5f81528560208201528160408201525f60608201527f06d294bc8cbad2e393408b20dd019a772661f60b8d633e56761157cb1ec85f8c60808201526105b68461167a565b526105c08361167a565b506040516105cd81611593565b5f81528560208201528160408201525f60608201527f568cc693d84eb1901f8bcecba154cbdef23ca3cf67efc0a0b698528a06c660f760808201526106118461168a565b5261061b8361168a565b5060405161062881611593565b5f81528560208201528160408201525f60608201527f4707e94b25cfce1a7c363508fbb838c35864388ad77284b248282b9746982b9b608082015261066c8461169a565b526106768361169a565b5060405161068381611593565b60028152602081018690526001600160a01b036040820152606081018590527f8c433a4cd6b51969eca37f974940894297b9fcf4b282a213fea5cd8f85289c9060808201526106d1846116aa565b526106db836116aa565b506040516106e881611593565b5f808252602082018790526001600160a01b03604083015260608201527fb014ce248804cab6a144581acce1eeb70ce5d54f08433b989d73bb0ccee3d3f96080820152610734846116ba565b5261073e836116ba565b5060405161074b81611593565b5f81528160208201528560408201525f60608201527fbf04b4486c9663d805744005c3da000eda93de6e3308a4a7a812eb565327b78d608082015261078f846116ca565b52610799836116ca565b50604051906107a782611593565b5f8296959493965283602083015260408201525f60608201527fd3d98e95f3486fc234d80c098cf0d2a0a3fb187833d7e9cc930f8c4f8335a0e760808201526107ef826116db565b526107f9816116db565b506020840190815260409161082a835161081385826115ae565b60018152601f19850136602083013780875261165d565b528151938493845282602085015260808401905192808501528251809152602060a085019301905f5b8181106108a8575050505190603f19838203016060840152602080835192838152019201905f5b818110610888575050500390f35b91935091602061089b60019286516114c8565b940191019184939261087a565b82516001600160a01b0316855286955060209485019490920191600101610853565b634e487b7160e01b5f52602160045260245ffd5b6020906040516108ed81611593565b5f81525f838201525f60408201525f60608201525f60808201528282880101520161049f565b5f8061098594604051946109286040876115ae565b601e86527f416464726573733a206c6f772d6c6576656c2063616c6c206661696c656400006020870152519082855af13d1561098e573d91610969836115fc565b9261097760405194856115ae565b83523d5f602085013e6116ec565b505f8080610480565b6060916116ec565b60405162461bcd60e51b8152602060048201526016602482015275115490cc4c4d8dce8818dc99585d194819985a5b195960521b6044820152606490fd5b91600191935060806020916060875160ff815116835260ff858201511685840152858060f01b0360408201511660408401520151606082015201940191019187929391936103e9565b6040513d5f823e3d90fd5b634e487b7160e01b5f52604160045260245ffd5b909192936101031989820301825285519061010081019180519261010083528351809152602061012084019401905f905b808210610af85750505060019260209260e080846001600160401b03878097015116868501526001600160401b0360408201511660408501526001600160401b03606082015116606085015261ffff608082015116608085015261ffff60a08201511660a085015260c0810151151560c08501520151151591015297019201920190949392916102e9565b9091946020608060019260608951858060a01b038151168352848101511515858401526040810151151560408401520151610b32816114be565b6060820152019601920190610a6d565b5f80fd5b608060248486823501030112610b425760405190610b638261155d565b610b6c8461164f565b8252610b7a6020850161164f565b60208301526040840135906001600160f01b0382168203610b4257826020926040608095015260608601356060820152815201920191610244565b83356001600160401b038111610b42576101006024358085018301908c0103601f190112610b42576040519061010082018281106001600160401b03821117610a285760405260446024358501820101356001600160401b038111610b425760248c81350101601f6020836024868a82350101010101011215610b42576044602435860183018201013590610c4982611617565b91610c5760405193846115ae565b8083528d6024602085019181350101602089818660248a8860071b9482350101010101010111610b4257908e83926020808b979660248a8a8235010101010101915b6064602435880189018601600786901b01018310610d795750505050509383610d66610100602486610d5560e08360209c9a8d9b9a8c9b839e52610ce6604084848482350101010161163b565b8c8b0152610cfd606084848482350101010161163b565b60408b0152610d15608084848482350101010161163b565b60608b0152610d2d60a084848482350101010161152a565b60808b0152610d4560c084848482350101010161152a565b60a08b015282350101010161162e565b60c08601528a82350101010161162e565b60e08201528152019501949150506101bc565b82608092939495969750602491823501030112610b425760405190610d9d8261155d565b610da6836114aa565b8252610db46020840161162e565b6020830152610dc56040840161162e565b60408301526060830135906003821015610b4257826020926060608095015281520191018f918995949392610c99565b34610b42576060366003190112610b4257610e0e611494565b50610e17611519565b506044356001600160401b038111610b42576060906003199036030112610b4257610e406115e3565b5063098990c560e11b5f525f600452600160245260445ffd5b34610b42576040366003190112610b4257610e72611494565b6024356001600160401b038111610b42578036036060600319820112610b4257610e9e826004016115cf565b9160248101359160221901821215610b4257016004810135906001600160401b038211610b4257602401908060051b36038213610b42571561131157610ee3906115cf565b60405191610140610ef481856115ae565b60098452601f19015f5b8181106112dc57505060405190610f1482611593565b600182526001600160a01b03908116602083018190529416604082018190525f60608301527f6f36f8bf0398781285f5a40c489dbf3268ce3e205aba87f21e49e6805391b5a1608083015290610f698461165d565b52610f738361165d565b50604051610f8081611593565b60018152602081018590526001600160a01b0360408201525f60608201527ff281525e53675515a6ba7cc7bea8a81e649b3608423ee2d73be1752cea8878896080820152610fcd8461166a565b52610fd78361166a565b50604051610fe481611593565b600181528460208201528160408201525f60608201527f06d294bc8cbad2e393408b20dd019a772661f60b8d633e56761157cb1ec85f8c60808201526110298461167a565b526110338361167a565b5060405161104081611593565b600181528460208201528160408201525f60608201527f568cc693d84eb1901f8bcecba154cbdef23ca3cf67efc0a0b698528a06c660f760808201526110858461168a565b5261108f8361168a565b5060405161109c81611593565b600181528460208201528160408201525f60608201527f4707e94b25cfce1a7c363508fbb838c35864388ad77284b248282b9746982b9b60808201526110e18461169a565b526110eb8361169a565b50600193604051926110fc84611593565b60038610156108ca57858452602084018290526001600160a01b036040850181905216606084018190527f8c433a4cd6b51969eca37f974940894297b9fcf4b282a213fea5cd8f85289c90608085015292611156856116aa565b52611160846116aa565b5060405161116d81611593565b60038610156108ca57858152602081018290526001600160a01b0360408201525f60608201527fb014ce248804cab6a144581acce1eeb70ce5d54f08433b989d73bb0ccee3d3f960808201526111c2856116ba565b526111cc846116ba565b50604051906111da82611593565b60038610156108ca5785825282602083015260408201525f60608201527fbf04b4486c9663d805744005c3da000eda93de6e3308a4a7a812eb565327b78d6080820152611226846116ca565b52611230836116ca565b506040519161123e83611593565b60038510156108ca57848395949552602083015260408201525f60608201527fd3d98e95f3486fc234d80c098cf0d2a0a3fb187833d7e9cc930f8c4f8335a0e7608082015261128c836116db565b52611296826116db565b5060405190602082016020835283518091526020604084019401905f5b8181106112c05784860385f35b90919260206112d1829786516114c8565b9694019291016112b3565b6020906040516112eb81611593565b5f81525f838201525f60408201525f60608201525f608082015282828801015201610efe565b634e487b7160e01b5f52603260045260245ffd5b34610b42575f366003190112610b42576040517f000000000000000000000000feb8a7ed4ab17cd2928f097b6622dc560b576e906001600160a01b03168152602090f35b34610b42575f366003190112610b42576040517f0000000000000000000000006ab6528e0d5a0f7c5738adfe6bc92dabc501d5066001600160a01b03168152602090f35b34610b42575f366003190112610b42576060806040516113cd82826115ae565b3690376040518181018181106001600160401b03821117610a285760405260018152600460208201525f604082015260405190815f905b6003821061141157505050f35b60208060019260ff865116815201930191019091611404565b34610b42576020366003190112610b42576004359063ffffffff60e01b8216809203610b425760209163099718b560e41b8114908115611484575b8115611473575b5015158152f35b6301ffc9a760e01b1490508361146c565b621574e360e91b81149150611465565b600435906001600160a01b0382168203610b4257565b35906001600160a01b0382168203610b4257565b600311156108ca57565b90608060a09280516114d9816114be565b8352600180851b036020820151166020840152600180851b036040820151166040840152600180851b036060820151166060840152015160808201520190565b6024359061ffff82168203610b4257565b359061ffff82168203610b4257565b805180835260209291819084018484015e5f828201840152601f01601f1916010190565b608081019081106001600160401b03821117610a2857604052565b604081019081106001600160401b03821117610a2857604052565b60a081019081106001600160401b03821117610a2857604052565b90601f801991011681019081106001600160401b03821117610a2857604052565b356001600160a01b0381168103610b425790565b604051906115f082611578565b60606020838281520152565b6001600160401b038111610a2857601f01601f191660200190565b6001600160401b038111610a285760051b60200190565b35908115158203610b4257565b35906001600160401b0382168203610b4257565b359060ff82168203610b4257565b8051156113115760200190565b8051600110156113115760400190565b8051600210156113115760600190565b8051600310156113115760800190565b8051600410156113115760a00190565b8051600510156113115760c00190565b8051600610156113115760e00190565b805160071015611311576101000190565b805160081015611311576101200190565b9192901561174e5750815115611700575090565b3b156117095790565b60405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606490fd5b8251909150156117615750805190602001fd5b60405162461bcd60e51b815260206004820152908190611785906024830190611539565b0390fdfe60806040526103c680380380610014816101f2565b9283398101906040818303126101ee5780516001600160a01b038116918282036101ee576020810151906001600160401b0382116101ee57019183601f840112156101ee57825161006c6100678261022b565b6101f2565b938185526020850195602083830101116101ee57815f926020809301885e85010152813b15610193577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80546001600160a01b031916821790557fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b5f80a281511580159061018c575b610108575b60405160cb90816102fb8239f35b5f8061017b9461011860606101f2565b94602786527f416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c6020870152660819985a5b195960ca1b60408701525190845af43d15610184573d9161016c6100678461022b565b9283523d5f602085013e610246565b505f80806100fa565b606091610246565b505f6100f5565b60405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b6064820152608490fd5b5f80fd5b6040519190601f01601f191682016001600160401b0381118382101761021757604052565b634e487b7160e01b5f52604160045260245ffd5b6001600160401b03811161021757601f01601f191660200190565b919290156102a8575081511561025a575090565b3b156102635790565b60405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606490fd5b8251909150156102bb5750805190602001fd5b604460209160405192839162461bcd60e51b83528160048401528051918291826024860152018484015e5f828201840152601f01601f19168101030190fdfe608060405236156051577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc545f9081906001600160a01b0316368280378136915af43d5f803e15604d573d5ff35b3d5ffd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc545f9081906001600160a01b0316368280378136915af43d5f803e15604d573d5ff3fea26469706673582212203bf93d98380d30a31ff94676bcd53f6cf4fd06145a15d34fda5d76afee117ce864736f6c634300081c0033a2646970667358221220d549dc05acebacd8e98bd12d54be05c98c16b1115bf8330bcbd5aeac4f46f58d64736f6c634300081c0033
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 34 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
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.