Source Code
Overview
ETH Balance
0 ETH
Eth Value
$0.00| Transaction Hash |
Method
|
Block
|
From
|
|
To
|
||||
|---|---|---|---|---|---|---|---|---|---|
Latest 1 internal transaction
Advanced mode:
| Parent Transaction Hash | Method | Block |
From
|
|
To
|
||
|---|---|---|---|---|---|---|---|
| 0x60806040 | 24397304 | 33 days ago | Contract Creation | 0 ETH |
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Name:
DAOGovernor
Compiler Version
v0.8.28+commit.7893614a
Optimization Enabled:
Yes with 1 runs
Other Settings:
cancun EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.28;
import "@openzeppelin/contracts-upgradeable/governance/GovernorUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/governance/extensions/GovernorSettingsUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/governance/extensions/GovernorCountingSimpleUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/governance/extensions/GovernorVotesUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/governance/extensions/GovernorVotesQuorumFractionUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/governance/extensions/GovernorTimelockControlUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
/**
* @title DAOGovernor
* @notice Governor contract for DAO governance with timelock integration and manager role
* @dev Implementation contract for EIP-1167 minimal proxy deployment
*
* Combines multiple OpenZeppelin governance extensions:
* - GovernorSettings: Configurable voting delay, voting period, and proposal threshold
* - GovernorCountingSimple: Simple For/Against/Abstain voting
* - GovernorVotes: Voting power from ERC20Votes token
* - GovernorVotesQuorumFraction: Quorum as percentage of total supply (1%)
* - GovernorTimelockControl: Execution through TimelockController
*
* Manager Role:
* - A single address designated as the DAO manager
* - Set during initialization (defaults to DAO creator)
* - Can be changed through governance proposals
* - Useful for backend systems to verify authorized addresses via RPC
*
* Architecture decisions:
* - Quorum: 1% of total supply (creator receives 1% and can meet quorum alone)
* - Proposal threshold: 1% of total supply (only significant holders can propose)
* - All proposals execute through timelock for security
* - Uses initializer pattern for minimal proxy deployment
*/
contract DAOGovernor is
Initializable,
GovernorUpgradeable,
GovernorSettingsUpgradeable,
GovernorCountingSimpleUpgradeable,
GovernorVotesUpgradeable,
GovernorVotesQuorumFractionUpgradeable,
GovernorTimelockControlUpgradeable
{
// ============ Manager Role Storage ============
/// @notice The address designated as the DAO manager
/// @dev Can be queried via RPC for backend authorization checks
address private _manager;
/// @notice Emitted when the manager address is changed
/// @param previousManager The address of the previous manager
/// @param newManager The address of the new manager
event ManagerChanged(address indexed previousManager, address indexed newManager);
/// @notice Error thrown when a non-governance caller tries to set manager
error OnlyGovernance();
/**
* @notice Disables initialization on the implementation contract
* @custom:oz-upgrades-unsafe-allow constructor
*/
constructor() {
_disableInitializers();
}
/**
* @notice Initializes a new DAO Governor (called once per clone)
* @param name_ The name of the DAO (e.g., "MyDAO")
* @param token_ The governance token (DAOToken) address
* @param timelock_ The TimelockController address
* @param votingDelay_ Delay in blocks before voting starts after proposal
* @param votingPeriod_ Duration in blocks for voting period
* @param proposalThreshold_ Minimum tokens required to create a proposal (in wei)
* @param initialManager_ The initial manager address (typically the DAO creator)
*/
function initialize(
string memory name_,
IVotes token_,
TimelockControllerUpgradeable timelock_,
uint48 votingDelay_,
uint32 votingPeriod_,
uint256 proposalThreshold_,
address initialManager_
) external initializer {
__Governor_init(name_);
__GovernorSettings_init(votingDelay_, votingPeriod_, proposalThreshold_);
__GovernorCountingSimple_init();
__GovernorVotes_init(token_);
__GovernorVotesQuorumFraction_init(1); // 1% quorum
__GovernorTimelockControl_init(timelock_);
// Set initial manager
_manager = initialManager_;
emit ManagerChanged(address(0), initialManager_);
}
// ============ Version Function ============
/**
* @notice Returns the DAOGovernor contract version
* @dev Separate from OpenZeppelin's version() which returns the Governor version
* @return The version string "1.0.0"
*/
function daoVersion() public pure returns (string memory) {
return "1.0.0";
}
// ============ Manager Role Functions ============
/**
* @notice Returns the current manager address
* @dev Can be called via RPC to verify authorization in backend systems
* @return The address of the current manager
*/
function manager() public view returns (address) {
return _manager;
}
/**
* @notice Sets a new manager address
* @dev Can only be called through governance (via timelock execution)
* @param newManager The address to set as the new manager
*
* To change the manager, create a proposal with:
* - target: governor address
* - value: 0
* - calldata: abi.encodeWithSignature("setManager(address)", newManagerAddress)
*/
function setManager(address newManager) external {
// Only the timelock (executor) can call this function
// This ensures changes go through governance proposals
if (msg.sender != _executor()) {
revert OnlyGovernance();
}
address oldManager = _manager;
_manager = newManager;
emit ManagerChanged(oldManager, newManager);
}
// ============ Clock Functions (Timestamp-Based) ============
/**
* @notice Returns the current clock value for governance (timestamp)
* @dev Required by ERC6372. Must match the token's clock mode.
* Uses timestamps for predictable timing across all chains.
* @return Current block timestamp as uint48
*/
function clock() public view override(GovernorUpgradeable, GovernorVotesUpgradeable) returns (uint48) {
return uint48(block.timestamp);
}
/**
* @notice Returns the clock mode description
* @dev Required by ERC6372. Must match the token's clock mode.
* @return Mode string indicating timestamp-based timing
*/
// solhint-disable-next-line func-name-mixedcase
function CLOCK_MODE() public pure override(GovernorUpgradeable, GovernorVotesUpgradeable) returns (string memory) {
return "mode=timestamp";
}
// ============ Required Overrides ============
function votingDelay()
public
view
override(GovernorUpgradeable, GovernorSettingsUpgradeable)
returns (uint256)
{
return super.votingDelay();
}
function votingPeriod()
public
view
override(GovernorUpgradeable, GovernorSettingsUpgradeable)
returns (uint256)
{
return super.votingPeriod();
}
function quorum(uint256 blockNumber)
public
view
override(GovernorUpgradeable, GovernorVotesQuorumFractionUpgradeable)
returns (uint256)
{
return super.quorum(blockNumber);
}
function state(uint256 proposalId)
public
view
override(GovernorUpgradeable, GovernorTimelockControlUpgradeable)
returns (ProposalState)
{
return super.state(proposalId);
}
function proposalNeedsQueuing(uint256 proposalId)
public
view
override(GovernorUpgradeable, GovernorTimelockControlUpgradeable)
returns (bool)
{
return super.proposalNeedsQueuing(proposalId);
}
function proposalThreshold()
public
view
override(GovernorUpgradeable, GovernorSettingsUpgradeable)
returns (uint256)
{
return super.proposalThreshold();
}
function _propose(
address[] memory targets,
uint256[] memory values,
bytes[] memory calldatas,
string memory description,
address proposer
) internal override(GovernorUpgradeable) returns (uint256) {
return super._propose(targets, values, calldatas, description, proposer);
}
function _queueOperations(
uint256 proposalId,
address[] memory targets,
uint256[] memory values,
bytes[] memory calldatas,
bytes32 descriptionHash
) internal override(GovernorUpgradeable, GovernorTimelockControlUpgradeable) returns (uint48) {
return super._queueOperations(proposalId, targets, values, calldatas, descriptionHash);
}
function _executeOperations(
uint256 proposalId,
address[] memory targets,
uint256[] memory values,
bytes[] memory calldatas,
bytes32 descriptionHash
) internal override(GovernorUpgradeable, GovernorTimelockControlUpgradeable) {
super._executeOperations(proposalId, targets, values, calldatas, descriptionHash);
}
function _cancel(
address[] memory targets,
uint256[] memory values,
bytes[] memory calldatas,
bytes32 descriptionHash
) internal override(GovernorUpgradeable, GovernorTimelockControlUpgradeable) returns (uint256) {
return super._cancel(targets, values, calldatas, descriptionHash);
}
function _executor()
internal
view
override(GovernorUpgradeable, GovernorTimelockControlUpgradeable)
returns (address)
{
return super._executor();
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (access/AccessControl.sol)
pragma solidity ^0.8.20;
import {IAccessControl} from "@openzeppelin/contracts/access/IAccessControl.sol";
import {ContextUpgradeable} from "../utils/ContextUpgradeable.sol";
import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol";
import {ERC165Upgradeable} from "../utils/introspection/ERC165Upgradeable.sol";
import {Initializable} from "../proxy/utils/Initializable.sol";
/**
* @dev Contract module that allows children to implement role-based access
* control mechanisms. This is a lightweight version that doesn't allow enumerating role
* members except through off-chain means by accessing the contract event logs. Some
* applications may benefit from on-chain enumerability, for those cases see
* {AccessControlEnumerable}.
*
* Roles are referred to by their `bytes32` identifier. These should be exposed
* in the external API and be unique. The best way to achieve this is by
* using `public constant` hash digests:
*
* ```solidity
* bytes32 public constant MY_ROLE = keccak256("MY_ROLE");
* ```
*
* Roles can be used to represent a set of permissions. To restrict access to a
* function call, use {hasRole}:
*
* ```solidity
* function foo() public {
* require(hasRole(MY_ROLE, msg.sender));
* ...
* }
* ```
*
* Roles can be granted and revoked dynamically via the {grantRole} and
* {revokeRole} functions. Each role has an associated admin role, and only
* accounts that have a role's admin role can call {grantRole} and {revokeRole}.
*
* By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means
* that only accounts with this role will be able to grant or revoke other
* roles. More complex role relationships can be created by using
* {_setRoleAdmin}.
*
* WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to
* grant and revoke this role. Extra precautions should be taken to secure
* accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}
* to enforce additional security measures for this role.
*/
abstract contract AccessControlUpgradeable is Initializable, ContextUpgradeable, IAccessControl, ERC165Upgradeable {
struct RoleData {
mapping(address account => bool) hasRole;
bytes32 adminRole;
}
bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;
/// @custom:storage-location erc7201:openzeppelin.storage.AccessControl
struct AccessControlStorage {
mapping(bytes32 role => RoleData) _roles;
}
// keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.AccessControl")) - 1)) & ~bytes32(uint256(0xff))
bytes32 private constant AccessControlStorageLocation = 0x02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800;
function _getAccessControlStorage() private pure returns (AccessControlStorage storage $) {
assembly {
$.slot := AccessControlStorageLocation
}
}
/**
* @dev Modifier that checks that an account has a specific role. Reverts
* with an {AccessControlUnauthorizedAccount} error including the required role.
*/
modifier onlyRole(bytes32 role) {
_checkRole(role);
_;
}
function __AccessControl_init() internal onlyInitializing {
}
function __AccessControl_init_unchained() internal onlyInitializing {
}
/// @inheritdoc IERC165
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);
}
/**
* @dev Returns `true` if `account` has been granted `role`.
*/
function hasRole(bytes32 role, address account) public view virtual returns (bool) {
AccessControlStorage storage $ = _getAccessControlStorage();
return $._roles[role].hasRole[account];
}
/**
* @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()`
* is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier.
*/
function _checkRole(bytes32 role) internal view virtual {
_checkRole(role, _msgSender());
}
/**
* @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account`
* is missing `role`.
*/
function _checkRole(bytes32 role, address account) internal view virtual {
if (!hasRole(role, account)) {
revert AccessControlUnauthorizedAccount(account, role);
}
}
/**
* @dev Returns the admin role that controls `role`. See {grantRole} and
* {revokeRole}.
*
* To change a role's admin, use {_setRoleAdmin}.
*/
function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) {
AccessControlStorage storage $ = _getAccessControlStorage();
return $._roles[role].adminRole;
}
/**
* @dev Grants `role` to `account`.
*
* If `account` had not been already granted `role`, emits a {RoleGranted}
* event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*
* May emit a {RoleGranted} event.
*/
function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {
_grantRole(role, account);
}
/**
* @dev Revokes `role` from `account`.
*
* If `account` had been granted `role`, emits a {RoleRevoked} event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*
* May emit a {RoleRevoked} event.
*/
function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {
_revokeRole(role, account);
}
/**
* @dev Revokes `role` from the calling account.
*
* Roles are often managed via {grantRole} and {revokeRole}: this function's
* purpose is to provide a mechanism for accounts to lose their privileges
* if they are compromised (such as when a trusted device is misplaced).
*
* If the calling account had been revoked `role`, emits a {RoleRevoked}
* event.
*
* Requirements:
*
* - the caller must be `callerConfirmation`.
*
* May emit a {RoleRevoked} event.
*/
function renounceRole(bytes32 role, address callerConfirmation) public virtual {
if (callerConfirmation != _msgSender()) {
revert AccessControlBadConfirmation();
}
_revokeRole(role, callerConfirmation);
}
/**
* @dev Sets `adminRole` as ``role``'s admin role.
*
* Emits a {RoleAdminChanged} event.
*/
function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {
AccessControlStorage storage $ = _getAccessControlStorage();
bytes32 previousAdminRole = getRoleAdmin(role);
$._roles[role].adminRole = adminRole;
emit RoleAdminChanged(role, previousAdminRole, adminRole);
}
/**
* @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted.
*
* Internal function without access restriction.
*
* May emit a {RoleGranted} event.
*/
function _grantRole(bytes32 role, address account) internal virtual returns (bool) {
AccessControlStorage storage $ = _getAccessControlStorage();
if (!hasRole(role, account)) {
$._roles[role].hasRole[account] = true;
emit RoleGranted(role, account, _msgSender());
return true;
} else {
return false;
}
}
/**
* @dev Attempts to revoke `role` from `account` and returns a boolean indicating if `role` was revoked.
*
* Internal function without access restriction.
*
* May emit a {RoleRevoked} event.
*/
function _revokeRole(bytes32 role, address account) internal virtual returns (bool) {
AccessControlStorage storage $ = _getAccessControlStorage();
if (hasRole(role, account)) {
$._roles[role].hasRole[account] = false;
emit RoleRevoked(role, account, _msgSender());
return true;
} else {
return false;
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (governance/extensions/GovernorCountingSimple.sol)
pragma solidity ^0.8.24;
import {IGovernor} from "@openzeppelin/contracts/governance/IGovernor.sol";
import {GovernorUpgradeable} from "../GovernorUpgradeable.sol";
import {Initializable} from "../../proxy/utils/Initializable.sol";
/**
* @dev Extension of {Governor} for simple, 3 options, vote counting.
*/
abstract contract GovernorCountingSimpleUpgradeable is Initializable, GovernorUpgradeable {
/**
* @dev Supported vote types. Matches Governor Bravo ordering.
*/
enum VoteType {
Against,
For,
Abstain
}
struct ProposalVote {
uint256 againstVotes;
uint256 forVotes;
uint256 abstainVotes;
mapping(address voter => bool) hasVoted;
}
/// @custom:storage-location erc7201:openzeppelin.storage.GovernorCountingSimple
struct GovernorCountingSimpleStorage {
mapping(uint256 proposalId => ProposalVote) _proposalVotes;
}
// keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.GovernorCountingSimple")) - 1)) & ~bytes32(uint256(0xff))
bytes32 private constant GovernorCountingSimpleStorageLocation = 0xa1cefa0f43667ef127a258e673c94202a79b656e62899531c4376d87a7f39800;
function _getGovernorCountingSimpleStorage() private pure returns (GovernorCountingSimpleStorage storage $) {
assembly {
$.slot := GovernorCountingSimpleStorageLocation
}
}
function __GovernorCountingSimple_init() internal onlyInitializing {
}
function __GovernorCountingSimple_init_unchained() internal onlyInitializing {
}
/// @inheritdoc IGovernor
// solhint-disable-next-line func-name-mixedcase
function COUNTING_MODE() public pure virtual override returns (string memory) {
return "support=bravo&quorum=for,abstain";
}
/// @inheritdoc IGovernor
function hasVoted(uint256 proposalId, address account) public view virtual override returns (bool) {
GovernorCountingSimpleStorage storage $ = _getGovernorCountingSimpleStorage();
return $._proposalVotes[proposalId].hasVoted[account];
}
/**
* @dev Accessor to the internal vote counts.
*/
function proposalVotes(
uint256 proposalId
) public view virtual returns (uint256 againstVotes, uint256 forVotes, uint256 abstainVotes) {
GovernorCountingSimpleStorage storage $ = _getGovernorCountingSimpleStorage();
ProposalVote storage proposalVote = $._proposalVotes[proposalId];
return (proposalVote.againstVotes, proposalVote.forVotes, proposalVote.abstainVotes);
}
/// @inheritdoc GovernorUpgradeable
function _quorumReached(uint256 proposalId) internal view virtual override returns (bool) {
GovernorCountingSimpleStorage storage $ = _getGovernorCountingSimpleStorage();
ProposalVote storage proposalVote = $._proposalVotes[proposalId];
return quorum(proposalSnapshot(proposalId)) <= proposalVote.forVotes + proposalVote.abstainVotes;
}
/**
* @dev See {Governor-_voteSucceeded}. In this module, the forVotes must be strictly over the againstVotes.
*/
function _voteSucceeded(uint256 proposalId) internal view virtual override returns (bool) {
GovernorCountingSimpleStorage storage $ = _getGovernorCountingSimpleStorage();
ProposalVote storage proposalVote = $._proposalVotes[proposalId];
return proposalVote.forVotes > proposalVote.againstVotes;
}
/**
* @dev See {Governor-_countVote}. In this module, the support follows the `VoteType` enum (from Governor Bravo).
*/
function _countVote(
uint256 proposalId,
address account,
uint8 support,
uint256 totalWeight,
bytes memory // params
) internal virtual override returns (uint256) {
GovernorCountingSimpleStorage storage $ = _getGovernorCountingSimpleStorage();
ProposalVote storage proposalVote = $._proposalVotes[proposalId];
if (proposalVote.hasVoted[account]) {
revert GovernorAlreadyCastVote(account);
}
proposalVote.hasVoted[account] = true;
if (support == uint8(VoteType.Against)) {
proposalVote.againstVotes += totalWeight;
} else if (support == uint8(VoteType.For)) {
proposalVote.forVotes += totalWeight;
} else if (support == uint8(VoteType.Abstain)) {
proposalVote.abstainVotes += totalWeight;
} else {
revert GovernorInvalidVoteType();
}
return totalWeight;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (governance/extensions/GovernorSettings.sol)
pragma solidity ^0.8.24;
import {IGovernor} from "@openzeppelin/contracts/governance/IGovernor.sol";
import {GovernorUpgradeable} from "../GovernorUpgradeable.sol";
import {Initializable} from "../../proxy/utils/Initializable.sol";
/**
* @dev Extension of {Governor} for settings updatable through governance.
*/
abstract contract GovernorSettingsUpgradeable is Initializable, GovernorUpgradeable {
/// @custom:storage-location erc7201:openzeppelin.storage.GovernorSettings
struct GovernorSettingsStorage {
// amount of token
uint256 _proposalThreshold;
// timepoint: limited to uint48 in core (same as clock() type)
uint48 _votingDelay;
// duration: limited to uint32 in core
uint32 _votingPeriod;
}
// keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.GovernorSettings")) - 1)) & ~bytes32(uint256(0xff))
bytes32 private constant GovernorSettingsStorageLocation = 0x00d7616c8fe29c6c2fbe1d0c5bc8f2faa4c35b43746e70b24b4d532752affd00;
function _getGovernorSettingsStorage() private pure returns (GovernorSettingsStorage storage $) {
assembly {
$.slot := GovernorSettingsStorageLocation
}
}
event VotingDelaySet(uint256 oldVotingDelay, uint256 newVotingDelay);
event VotingPeriodSet(uint256 oldVotingPeriod, uint256 newVotingPeriod);
event ProposalThresholdSet(uint256 oldProposalThreshold, uint256 newProposalThreshold);
/**
* @dev Initialize the governance parameters.
*/
function __GovernorSettings_init(uint48 initialVotingDelay, uint32 initialVotingPeriod, uint256 initialProposalThreshold) internal onlyInitializing {
__GovernorSettings_init_unchained(initialVotingDelay, initialVotingPeriod, initialProposalThreshold);
}
function __GovernorSettings_init_unchained(uint48 initialVotingDelay, uint32 initialVotingPeriod, uint256 initialProposalThreshold) internal onlyInitializing {
_setVotingDelay(initialVotingDelay);
_setVotingPeriod(initialVotingPeriod);
_setProposalThreshold(initialProposalThreshold);
}
/// @inheritdoc IGovernor
function votingDelay() public view virtual override returns (uint256) {
GovernorSettingsStorage storage $ = _getGovernorSettingsStorage();
return $._votingDelay;
}
/// @inheritdoc IGovernor
function votingPeriod() public view virtual override returns (uint256) {
GovernorSettingsStorage storage $ = _getGovernorSettingsStorage();
return $._votingPeriod;
}
/// @inheritdoc GovernorUpgradeable
function proposalThreshold() public view virtual override returns (uint256) {
GovernorSettingsStorage storage $ = _getGovernorSettingsStorage();
return $._proposalThreshold;
}
/**
* @dev Update the voting delay. This operation can only be performed through a governance proposal.
*
* Emits a {VotingDelaySet} event.
*/
function setVotingDelay(uint48 newVotingDelay) public virtual onlyGovernance {
_setVotingDelay(newVotingDelay);
}
/**
* @dev Update the voting period. This operation can only be performed through a governance proposal.
*
* Emits a {VotingPeriodSet} event.
*/
function setVotingPeriod(uint32 newVotingPeriod) public virtual onlyGovernance {
_setVotingPeriod(newVotingPeriod);
}
/**
* @dev Update the proposal threshold. This operation can only be performed through a governance proposal.
*
* Emits a {ProposalThresholdSet} event.
*/
function setProposalThreshold(uint256 newProposalThreshold) public virtual onlyGovernance {
_setProposalThreshold(newProposalThreshold);
}
/**
* @dev Internal setter for the voting delay.
*
* Emits a {VotingDelaySet} event.
*/
function _setVotingDelay(uint48 newVotingDelay) internal virtual {
GovernorSettingsStorage storage $ = _getGovernorSettingsStorage();
emit VotingDelaySet($._votingDelay, newVotingDelay);
$._votingDelay = newVotingDelay;
}
/**
* @dev Internal setter for the voting period.
*
* Emits a {VotingPeriodSet} event.
*/
function _setVotingPeriod(uint32 newVotingPeriod) internal virtual {
GovernorSettingsStorage storage $ = _getGovernorSettingsStorage();
if (newVotingPeriod == 0) {
revert GovernorInvalidVotingPeriod(0);
}
emit VotingPeriodSet($._votingPeriod, newVotingPeriod);
$._votingPeriod = newVotingPeriod;
}
/**
* @dev Internal setter for the proposal threshold.
*
* Emits a {ProposalThresholdSet} event.
*/
function _setProposalThreshold(uint256 newProposalThreshold) internal virtual {
GovernorSettingsStorage storage $ = _getGovernorSettingsStorage();
emit ProposalThresholdSet($._proposalThreshold, newProposalThreshold);
$._proposalThreshold = newProposalThreshold;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (governance/extensions/GovernorTimelockControl.sol)
pragma solidity ^0.8.24;
import {IGovernor} from "@openzeppelin/contracts/governance/IGovernor.sol";
import {GovernorUpgradeable} from "../GovernorUpgradeable.sol";
import {TimelockControllerUpgradeable} from "../TimelockControllerUpgradeable.sol";
import {SafeCast} from "@openzeppelin/contracts/utils/math/SafeCast.sol";
import {Initializable} from "../../proxy/utils/Initializable.sol";
/**
* @dev Extension of {Governor} that binds the execution process to an instance of {TimelockController}. This adds a
* delay, enforced by the {TimelockController} to all successful proposal (in addition to the voting duration). The
* {Governor} needs the proposer (and ideally the executor and canceller) roles for the {Governor} to work properly.
*
* Using this model means the proposal will be operated by the {TimelockController} and not by the {Governor}. Thus,
* the assets and permissions must be attached to the {TimelockController}. Any asset sent to the {Governor} will be
* inaccessible from a proposal, unless executed via {Governor-relay}.
*
* WARNING: Setting up the TimelockController to have additional proposers or cancelers besides the governor is very
* risky, as it grants them the ability to: 1) execute operations as the timelock, and thus possibly performing
* operations or accessing funds that are expected to only be accessible through a vote, and 2) block governance
* proposals that have been approved by the voters, effectively executing a Denial of Service attack.
*/
abstract contract GovernorTimelockControlUpgradeable is Initializable, GovernorUpgradeable {
/// @custom:storage-location erc7201:openzeppelin.storage.GovernorTimelockControl
struct GovernorTimelockControlStorage {
TimelockControllerUpgradeable _timelock;
mapping(uint256 proposalId => bytes32) _timelockIds;
}
// keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.GovernorTimelockControl")) - 1)) & ~bytes32(uint256(0xff))
bytes32 private constant GovernorTimelockControlStorageLocation = 0x0d5829787b8befdbc6044ef7457d8a95c2a04bc99235349f1a212c063e59d400;
function _getGovernorTimelockControlStorage() private pure returns (GovernorTimelockControlStorage storage $) {
assembly {
$.slot := GovernorTimelockControlStorageLocation
}
}
/**
* @dev Emitted when the timelock controller used for proposal execution is modified.
*/
event TimelockChange(address oldTimelock, address newTimelock);
/**
* @dev Set the timelock.
*/
function __GovernorTimelockControl_init(TimelockControllerUpgradeable timelockAddress) internal onlyInitializing {
__GovernorTimelockControl_init_unchained(timelockAddress);
}
function __GovernorTimelockControl_init_unchained(TimelockControllerUpgradeable timelockAddress) internal onlyInitializing {
_updateTimelock(timelockAddress);
}
/**
* @dev Overridden version of the {Governor-state} function that considers the status reported by the timelock.
*/
function state(uint256 proposalId) public view virtual override returns (ProposalState) {
GovernorTimelockControlStorage storage $ = _getGovernorTimelockControlStorage();
ProposalState currentState = super.state(proposalId);
if (currentState != ProposalState.Queued) {
return currentState;
}
bytes32 queueid = $._timelockIds[proposalId];
if ($._timelock.isOperationPending(queueid)) {
return ProposalState.Queued;
} else if ($._timelock.isOperationDone(queueid)) {
// This can happen if the proposal is executed directly on the timelock.
return ProposalState.Executed;
} else {
// This can happen if the proposal is canceled directly on the timelock.
return ProposalState.Canceled;
}
}
/**
* @dev Public accessor to check the address of the timelock
*/
function timelock() public view virtual returns (address) {
GovernorTimelockControlStorage storage $ = _getGovernorTimelockControlStorage();
return address($._timelock);
}
/// @inheritdoc IGovernor
function proposalNeedsQueuing(uint256) public view virtual override returns (bool) {
return true;
}
/**
* @dev Function to queue a proposal to the timelock.
*/
function _queueOperations(
uint256 proposalId,
address[] memory targets,
uint256[] memory values,
bytes[] memory calldatas,
bytes32 descriptionHash
) internal virtual override returns (uint48) {
GovernorTimelockControlStorage storage $ = _getGovernorTimelockControlStorage();
uint256 delay = $._timelock.getMinDelay();
bytes32 salt = _timelockSalt(descriptionHash);
$._timelockIds[proposalId] = $._timelock.hashOperationBatch(targets, values, calldatas, 0, salt);
$._timelock.scheduleBatch(targets, values, calldatas, 0, salt, delay);
return SafeCast.toUint48(block.timestamp + delay);
}
/**
* @dev Overridden version of the {Governor-_executeOperations} function that runs the already queued proposal
* through the timelock.
*/
function _executeOperations(
uint256 proposalId,
address[] memory targets,
uint256[] memory values,
bytes[] memory calldatas,
bytes32 descriptionHash
) internal virtual override {
GovernorTimelockControlStorage storage $ = _getGovernorTimelockControlStorage();
// execute
$._timelock.executeBatch{value: msg.value}(targets, values, calldatas, 0, _timelockSalt(descriptionHash));
// cleanup for refund
delete $._timelockIds[proposalId];
}
/**
* @dev Overridden version of the {Governor-_cancel} function to cancel the timelocked proposal if it has already
* been queued.
*/
// This function can reenter through the external call to the timelock, but we assume the timelock is trusted and
// well behaved (according to TimelockController) and this will not happen.
// slither-disable-next-line reentrancy-no-eth
function _cancel(
address[] memory targets,
uint256[] memory values,
bytes[] memory calldatas,
bytes32 descriptionHash
) internal virtual override returns (uint256) {
GovernorTimelockControlStorage storage $ = _getGovernorTimelockControlStorage();
uint256 proposalId = super._cancel(targets, values, calldatas, descriptionHash);
bytes32 timelockId = $._timelockIds[proposalId];
if (timelockId != 0) {
// cancel
$._timelock.cancel(timelockId);
// cleanup
delete $._timelockIds[proposalId];
}
return proposalId;
}
/**
* @dev Address through which the governor executes action. In this case, the timelock.
*/
function _executor() internal view virtual override returns (address) {
GovernorTimelockControlStorage storage $ = _getGovernorTimelockControlStorage();
return address($._timelock);
}
/**
* @dev Public endpoint to update the underlying timelock instance. Restricted to the timelock itself, so updates
* must be proposed, scheduled, and executed through governance proposals.
*
* CAUTION: It is not recommended to change the timelock while there are other queued governance proposals.
*/
function updateTimelock(TimelockControllerUpgradeable newTimelock) external virtual onlyGovernance {
_updateTimelock(newTimelock);
}
function _updateTimelock(TimelockControllerUpgradeable newTimelock) private {
GovernorTimelockControlStorage storage $ = _getGovernorTimelockControlStorage();
emit TimelockChange(address($._timelock), address(newTimelock));
$._timelock = newTimelock;
}
/**
* @dev Computes the {TimelockController} operation salt.
*
* It is computed with the governor address itself to avoid collisions across governor instances using the
* same timelock.
*/
function _timelockSalt(bytes32 descriptionHash) private view returns (bytes32) {
return bytes20(address(this)) ^ descriptionHash;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (governance/extensions/GovernorVotesQuorumFraction.sol)
pragma solidity ^0.8.24;
import {GovernorVotesUpgradeable} from "./GovernorVotesUpgradeable.sol";
import {Math} from "@openzeppelin/contracts/utils/math/Math.sol";
import {SafeCast} from "@openzeppelin/contracts/utils/math/SafeCast.sol";
import {Checkpoints} from "@openzeppelin/contracts/utils/structs/Checkpoints.sol";
import {Initializable} from "../../proxy/utils/Initializable.sol";
/**
* @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token and a quorum expressed as a
* fraction of the total supply.
*/
abstract contract GovernorVotesQuorumFractionUpgradeable is Initializable, GovernorVotesUpgradeable {
using Checkpoints for Checkpoints.Trace208;
/// @custom:storage-location erc7201:openzeppelin.storage.GovernorVotesQuorumFraction
struct GovernorVotesQuorumFractionStorage {
Checkpoints.Trace208 _quorumNumeratorHistory;
}
// keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.GovernorVotesQuorumFraction")) - 1)) & ~bytes32(uint256(0xff))
bytes32 private constant GovernorVotesQuorumFractionStorageLocation = 0xe770710421fd2cad75ad828c61aa98f2d77d423a440b67872d0f65554148e000;
function _getGovernorVotesQuorumFractionStorage() private pure returns (GovernorVotesQuorumFractionStorage storage $) {
assembly {
$.slot := GovernorVotesQuorumFractionStorageLocation
}
}
event QuorumNumeratorUpdated(uint256 oldQuorumNumerator, uint256 newQuorumNumerator);
/**
* @dev The quorum set is not a valid fraction.
*/
error GovernorInvalidQuorumFraction(uint256 quorumNumerator, uint256 quorumDenominator);
/**
* @dev Initialize quorum as a fraction of the token's total supply.
*
* The fraction is specified as `numerator / denominator`. By default the denominator is 100, so quorum is
* specified as a percent: a numerator of 10 corresponds to quorum being 10% of total supply. The denominator can be
* customized by overriding {quorumDenominator}.
*/
function __GovernorVotesQuorumFraction_init(uint256 quorumNumeratorValue) internal onlyInitializing {
__GovernorVotesQuorumFraction_init_unchained(quorumNumeratorValue);
}
function __GovernorVotesQuorumFraction_init_unchained(uint256 quorumNumeratorValue) internal onlyInitializing {
_updateQuorumNumerator(quorumNumeratorValue);
}
/**
* @dev Returns the current quorum numerator. See {quorumDenominator}.
*/
function quorumNumerator() public view virtual returns (uint256) {
GovernorVotesQuorumFractionStorage storage $ = _getGovernorVotesQuorumFractionStorage();
return $._quorumNumeratorHistory.latest();
}
/**
* @dev Returns the quorum numerator at a specific timepoint. See {quorumDenominator}.
*/
function quorumNumerator(uint256 timepoint) public view virtual returns (uint256) {
GovernorVotesQuorumFractionStorage storage $ = _getGovernorVotesQuorumFractionStorage();
return _optimisticUpperLookupRecent($._quorumNumeratorHistory, timepoint);
}
/**
* @dev Returns the quorum denominator. Defaults to 100, but may be overridden.
*/
function quorumDenominator() public view virtual returns (uint256) {
return 100;
}
/**
* @dev Returns the quorum for a timepoint, in terms of number of votes: `supply * numerator / denominator`.
*/
function quorum(uint256 timepoint) public view virtual override returns (uint256) {
return Math.mulDiv(token().getPastTotalSupply(timepoint), quorumNumerator(timepoint), quorumDenominator());
}
/**
* @dev Changes the quorum numerator.
*
* Emits a {QuorumNumeratorUpdated} event.
*
* Requirements:
*
* - Must be called through a governance proposal.
* - New numerator must be smaller or equal to the denominator.
*/
function updateQuorumNumerator(uint256 newQuorumNumerator) external virtual onlyGovernance {
_updateQuorumNumerator(newQuorumNumerator);
}
/**
* @dev Changes the quorum numerator.
*
* Emits a {QuorumNumeratorUpdated} event.
*
* Requirements:
*
* - New numerator must be smaller or equal to the denominator.
*/
function _updateQuorumNumerator(uint256 newQuorumNumerator) internal virtual {
GovernorVotesQuorumFractionStorage storage $ = _getGovernorVotesQuorumFractionStorage();
uint256 denominator = quorumDenominator();
if (newQuorumNumerator > denominator) {
revert GovernorInvalidQuorumFraction(newQuorumNumerator, denominator);
}
uint256 oldQuorumNumerator = quorumNumerator();
$._quorumNumeratorHistory.push(clock(), SafeCast.toUint208(newQuorumNumerator));
emit QuorumNumeratorUpdated(oldQuorumNumerator, newQuorumNumerator);
}
/**
* @dev Returns the numerator at a specific timepoint.
*/
function _optimisticUpperLookupRecent(
Checkpoints.Trace208 storage ckpts,
uint256 timepoint
) internal view returns (uint256) {
// If trace is empty, key and value are both equal to 0.
// In that case `key <= timepoint` is true, and it is ok to return 0.
(, uint48 key, uint208 value) = ckpts.latestCheckpoint();
return key <= timepoint ? value : ckpts.upperLookupRecent(SafeCast.toUint48(timepoint));
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (governance/extensions/GovernorVotes.sol)
pragma solidity ^0.8.24;
import {GovernorUpgradeable} from "../GovernorUpgradeable.sol";
import {IVotes} from "@openzeppelin/contracts/governance/utils/IVotes.sol";
import {IERC5805} from "@openzeppelin/contracts/interfaces/IERC5805.sol";
import {Time} from "@openzeppelin/contracts/utils/types/Time.sol";
import {Initializable} from "../../proxy/utils/Initializable.sol";
/**
* @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token, or since v4.5 an {ERC721Votes}
* token.
*/
abstract contract GovernorVotesUpgradeable is Initializable, GovernorUpgradeable {
/// @custom:storage-location erc7201:openzeppelin.storage.GovernorVotes
struct GovernorVotesStorage {
IERC5805 _token;
}
// keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.GovernorVotes")) - 1)) & ~bytes32(uint256(0xff))
bytes32 private constant GovernorVotesStorageLocation = 0x3ba4977254e415696610a40ebf2258dbfa0ec6a2ff64e84bfe715ff16977cc00;
function _getGovernorVotesStorage() private pure returns (GovernorVotesStorage storage $) {
assembly {
$.slot := GovernorVotesStorageLocation
}
}
function __GovernorVotes_init(IVotes tokenAddress) internal onlyInitializing {
__GovernorVotes_init_unchained(tokenAddress);
}
function __GovernorVotes_init_unchained(IVotes tokenAddress) internal onlyInitializing {
GovernorVotesStorage storage $ = _getGovernorVotesStorage();
$._token = IERC5805(address(tokenAddress));
}
/**
* @dev The token that voting power is sourced from.
*/
function token() public view virtual returns (IERC5805) {
GovernorVotesStorage storage $ = _getGovernorVotesStorage();
return $._token;
}
/**
* @dev Clock (as specified in ERC-6372) is set to match the token's clock. Fallback to block numbers if the token
* does not implement ERC-6372.
*/
function clock() public view virtual override returns (uint48) {
try token().clock() returns (uint48 timepoint) {
return timepoint;
} catch {
return Time.blockNumber();
}
}
/**
* @dev Machine-readable description of the clock as specified in ERC-6372.
*/
// solhint-disable-next-line func-name-mixedcase
function CLOCK_MODE() public view virtual override returns (string memory) {
try token().CLOCK_MODE() returns (string memory clockmode) {
return clockmode;
} catch {
return "mode=blocknumber&from=default";
}
}
/**
* Read the voting weight from the token's built in snapshot mechanism (see {Governor-_getVotes}).
*/
function _getVotes(
address account,
uint256 timepoint,
bytes memory /*params*/
) internal view virtual override returns (uint256) {
return token().getPastVotes(account, timepoint);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (governance/Governor.sol)
pragma solidity ^0.8.24;
import {IERC721Receiver} from "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol";
import {IERC1155Receiver} from "@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol";
import {EIP712Upgradeable} from "../utils/cryptography/EIP712Upgradeable.sol";
import {SignatureChecker} from "@openzeppelin/contracts/utils/cryptography/SignatureChecker.sol";
import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol";
import {ERC165Upgradeable} from "../utils/introspection/ERC165Upgradeable.sol";
import {SafeCast} from "@openzeppelin/contracts/utils/math/SafeCast.sol";
import {DoubleEndedQueue} from "@openzeppelin/contracts/utils/structs/DoubleEndedQueue.sol";
import {Address} from "@openzeppelin/contracts/utils/Address.sol";
import {ContextUpgradeable} from "../utils/ContextUpgradeable.sol";
import {NoncesUpgradeable} from "../utils/NoncesUpgradeable.sol";
import {Strings} from "@openzeppelin/contracts/utils/Strings.sol";
import {IGovernor} from "@openzeppelin/contracts/governance/IGovernor.sol";
import {IERC6372} from "@openzeppelin/contracts/interfaces/IERC6372.sol";
import {Initializable} from "../proxy/utils/Initializable.sol";
/**
* @dev Core of the governance system, designed to be extended through various modules.
*
* This contract is abstract and requires several functions to be implemented in various modules:
*
* - A counting module must implement {_quorumReached}, {_voteSucceeded} and {_countVote}
* - A voting module must implement {_getVotes}
* - Additionally, {votingPeriod}, {votingDelay}, and {quorum} must also be implemented
*/
abstract contract GovernorUpgradeable is Initializable, ContextUpgradeable, ERC165Upgradeable, EIP712Upgradeable, NoncesUpgradeable, IGovernor, IERC721Receiver, IERC1155Receiver {
using DoubleEndedQueue for DoubleEndedQueue.Bytes32Deque;
bytes32 public constant BALLOT_TYPEHASH =
keccak256("Ballot(uint256 proposalId,uint8 support,address voter,uint256 nonce)");
bytes32 public constant EXTENDED_BALLOT_TYPEHASH =
keccak256(
"ExtendedBallot(uint256 proposalId,uint8 support,address voter,uint256 nonce,string reason,bytes params)"
);
struct ProposalCore {
address proposer;
uint48 voteStart;
uint32 voteDuration;
bool executed;
bool canceled;
uint48 etaSeconds;
}
bytes32 private constant ALL_PROPOSAL_STATES_BITMAP = bytes32((2 ** (uint8(type(ProposalState).max) + 1)) - 1);
/// @custom:storage-location erc7201:openzeppelin.storage.Governor
struct GovernorStorage {
string _name;
mapping(uint256 proposalId => ProposalCore) _proposals;
// This queue keeps track of the governor operating on itself. Calls to functions protected by the {onlyGovernance}
// modifier needs to be whitelisted in this queue. Whitelisting is set in {execute}, consumed by the
// {onlyGovernance} modifier and eventually reset after {_executeOperations} completes. This ensures that the
// execution of {onlyGovernance} protected calls can only be achieved through successful proposals.
DoubleEndedQueue.Bytes32Deque _governanceCall;
}
// keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Governor")) - 1)) & ~bytes32(uint256(0xff))
bytes32 private constant GovernorStorageLocation = 0x7c712897014dbe49c045ef1299aa2d5f9e67e48eea4403efa21f1e0f3ac0cb00;
function _getGovernorStorage() private pure returns (GovernorStorage storage $) {
assembly {
$.slot := GovernorStorageLocation
}
}
/**
* @dev Restricts a function so it can only be executed through governance proposals. For example, governance
* parameter setters in {GovernorSettings} are protected using this modifier.
*
* The governance executing address may be different from the Governor's own address, for example it could be a
* timelock. This can be customized by modules by overriding {_executor}. The executor is only able to invoke these
* functions during the execution of the governor's {execute} function, and not under any other circumstances. Thus,
* for example, additional timelock proposers are not able to change governance parameters without going through the
* governance protocol (since v4.6).
*/
modifier onlyGovernance() {
_checkGovernance();
_;
}
/**
* @dev Sets the value for {name} and {version}
*/
function __Governor_init(string memory name_) internal onlyInitializing {
__EIP712_init_unchained(name_, version());
__Governor_init_unchained(name_);
}
function __Governor_init_unchained(string memory name_) internal onlyInitializing {
GovernorStorage storage $ = _getGovernorStorage();
$._name = name_;
}
/**
* @dev Function to receive ETH that will be handled by the governor (disabled if executor is a third party contract)
*/
receive() external payable virtual {
if (_executor() != address(this)) {
revert GovernorDisabledDeposit();
}
}
/// @inheritdoc IERC165
function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC165Upgradeable) returns (bool) {
return
interfaceId == type(IGovernor).interfaceId ||
interfaceId == type(IGovernor).interfaceId ^ IGovernor.getProposalId.selector ||
interfaceId == type(IERC1155Receiver).interfaceId ||
super.supportsInterface(interfaceId);
}
/// @inheritdoc IGovernor
function name() public view virtual returns (string memory) {
GovernorStorage storage $ = _getGovernorStorage();
return $._name;
}
/// @inheritdoc IGovernor
function version() public view virtual returns (string memory) {
return "1";
}
/**
* @dev See {IGovernor-hashProposal}.
*
* The proposal id is produced by hashing the ABI encoded `targets` array, the `values` array, the `calldatas` array
* and the descriptionHash (bytes32 which itself is the keccak256 hash of the description string). This proposal id
* can be produced from the proposal data which is part of the {ProposalCreated} event. It can even be computed in
* advance, before the proposal is submitted.
*
* Note that the chainId and the governor address are not part of the proposal id computation. Consequently, the
* same proposal (with same operation and same description) will have the same id if submitted on multiple governors
* across multiple networks. This also means that in order to execute the same operation twice (on the same
* governor) the proposer will have to change the description in order to avoid proposal id conflicts.
*/
function hashProposal(
address[] memory targets,
uint256[] memory values,
bytes[] memory calldatas,
bytes32 descriptionHash
) public pure virtual returns (uint256) {
return uint256(keccak256(abi.encode(targets, values, calldatas, descriptionHash)));
}
/// @inheritdoc IGovernor
function getProposalId(
address[] memory targets,
uint256[] memory values,
bytes[] memory calldatas,
bytes32 descriptionHash
) public view virtual returns (uint256) {
return hashProposal(targets, values, calldatas, descriptionHash);
}
/// @inheritdoc IGovernor
function state(uint256 proposalId) public view virtual returns (ProposalState) {
GovernorStorage storage $ = _getGovernorStorage();
// We read the struct fields into the stack at once so Solidity emits a single SLOAD
ProposalCore storage proposal = $._proposals[proposalId];
bool proposalExecuted = proposal.executed;
bool proposalCanceled = proposal.canceled;
if (proposalExecuted) {
return ProposalState.Executed;
}
if (proposalCanceled) {
return ProposalState.Canceled;
}
uint256 snapshot = proposalSnapshot(proposalId);
if (snapshot == 0) {
revert GovernorNonexistentProposal(proposalId);
}
uint256 currentTimepoint = clock();
if (snapshot >= currentTimepoint) {
return ProposalState.Pending;
}
uint256 deadline = proposalDeadline(proposalId);
if (deadline >= currentTimepoint) {
return ProposalState.Active;
} else if (!_quorumReached(proposalId) || !_voteSucceeded(proposalId)) {
return ProposalState.Defeated;
} else if (proposalEta(proposalId) == 0) {
return ProposalState.Succeeded;
} else {
return ProposalState.Queued;
}
}
/// @inheritdoc IGovernor
function proposalThreshold() public view virtual returns (uint256) {
return 0;
}
/// @inheritdoc IGovernor
function proposalSnapshot(uint256 proposalId) public view virtual returns (uint256) {
GovernorStorage storage $ = _getGovernorStorage();
return $._proposals[proposalId].voteStart;
}
/// @inheritdoc IGovernor
function proposalDeadline(uint256 proposalId) public view virtual returns (uint256) {
GovernorStorage storage $ = _getGovernorStorage();
return $._proposals[proposalId].voteStart + $._proposals[proposalId].voteDuration;
}
/// @inheritdoc IGovernor
function proposalProposer(uint256 proposalId) public view virtual returns (address) {
GovernorStorage storage $ = _getGovernorStorage();
return $._proposals[proposalId].proposer;
}
/// @inheritdoc IGovernor
function proposalEta(uint256 proposalId) public view virtual returns (uint256) {
GovernorStorage storage $ = _getGovernorStorage();
return $._proposals[proposalId].etaSeconds;
}
/// @inheritdoc IGovernor
function proposalNeedsQueuing(uint256) public view virtual returns (bool) {
return false;
}
/**
* @dev Reverts if the `msg.sender` is not the executor. In case the executor is not this contract
* itself, the function reverts if `msg.data` is not whitelisted as a result of an {execute}
* operation. See {onlyGovernance}.
*/
function _checkGovernance() internal virtual {
GovernorStorage storage $ = _getGovernorStorage();
if (_executor() != _msgSender()) {
revert GovernorOnlyExecutor(_msgSender());
}
if (_executor() != address(this)) {
bytes32 msgDataHash = keccak256(_msgData());
// loop until popping the expected operation - throw if deque is empty (operation not authorized)
while ($._governanceCall.popFront() != msgDataHash) {}
}
}
/**
* @dev Amount of votes already cast passes the threshold limit.
*/
function _quorumReached(uint256 proposalId) internal view virtual returns (bool);
/**
* @dev Is the proposal successful or not.
*/
function _voteSucceeded(uint256 proposalId) internal view virtual returns (bool);
/**
* @dev Get the voting weight of `account` at a specific `timepoint`, for a vote as described by `params`.
*/
function _getVotes(address account, uint256 timepoint, bytes memory params) internal view virtual returns (uint256);
/**
* @dev Register a vote for `proposalId` by `account` with a given `support`, voting `weight` and voting `params`.
*
* Note: Support is generic and can represent various things depending on the voting system used.
*/
function _countVote(
uint256 proposalId,
address account,
uint8 support,
uint256 totalWeight,
bytes memory params
) internal virtual returns (uint256);
/**
* @dev Hook that should be called every time the tally for a proposal is updated.
*
* Note: This function must run successfully. Reverts will result in the bricking of governance
*/
function _tallyUpdated(uint256 proposalId) internal virtual {}
/**
* @dev Default additional encoded parameters used by castVote methods that don't include them
*
* Note: Should be overridden by specific implementations to use an appropriate value, the
* meaning of the additional params, in the context of that implementation
*/
function _defaultParams() internal view virtual returns (bytes memory) {
return "";
}
/**
* @dev See {IGovernor-propose}. This function has opt-in frontrunning protection, described in {_isValidDescriptionForProposer}.
*/
function propose(
address[] memory targets,
uint256[] memory values,
bytes[] memory calldatas,
string memory description
) public virtual returns (uint256) {
address proposer = _msgSender();
// check description restriction
if (!_isValidDescriptionForProposer(proposer, description)) {
revert GovernorRestrictedProposer(proposer);
}
// check proposal threshold
uint256 votesThreshold = proposalThreshold();
if (votesThreshold > 0) {
uint256 proposerVotes = getVotes(proposer, clock() - 1);
if (proposerVotes < votesThreshold) {
revert GovernorInsufficientProposerVotes(proposer, proposerVotes, votesThreshold);
}
}
return _propose(targets, values, calldatas, description, proposer);
}
/**
* @dev Internal propose mechanism. Can be overridden to add more logic on proposal creation.
*
* Emits a {IGovernor-ProposalCreated} event.
*/
function _propose(
address[] memory targets,
uint256[] memory values,
bytes[] memory calldatas,
string memory description,
address proposer
) internal virtual returns (uint256 proposalId) {
GovernorStorage storage $ = _getGovernorStorage();
proposalId = getProposalId(targets, values, calldatas, keccak256(bytes(description)));
if (targets.length != values.length || targets.length != calldatas.length || targets.length == 0) {
revert GovernorInvalidProposalLength(targets.length, calldatas.length, values.length);
}
if ($._proposals[proposalId].voteStart != 0) {
revert GovernorUnexpectedProposalState(proposalId, state(proposalId), bytes32(0));
}
uint256 snapshot = clock() + votingDelay();
uint256 duration = votingPeriod();
ProposalCore storage proposal = $._proposals[proposalId];
proposal.proposer = proposer;
proposal.voteStart = SafeCast.toUint48(snapshot);
proposal.voteDuration = SafeCast.toUint32(duration);
emit ProposalCreated(
proposalId,
proposer,
targets,
values,
new string[](targets.length),
calldatas,
snapshot,
snapshot + duration,
description
);
// Using a named return variable to avoid stack too deep errors
}
/// @inheritdoc IGovernor
function queue(
address[] memory targets,
uint256[] memory values,
bytes[] memory calldatas,
bytes32 descriptionHash
) public virtual returns (uint256) {
GovernorStorage storage $ = _getGovernorStorage();
uint256 proposalId = getProposalId(targets, values, calldatas, descriptionHash);
_validateStateBitmap(proposalId, _encodeStateBitmap(ProposalState.Succeeded));
uint48 etaSeconds = _queueOperations(proposalId, targets, values, calldatas, descriptionHash);
if (etaSeconds != 0) {
$._proposals[proposalId].etaSeconds = etaSeconds;
emit ProposalQueued(proposalId, etaSeconds);
} else {
revert GovernorQueueNotImplemented();
}
return proposalId;
}
/**
* @dev Internal queuing mechanism. Can be overridden (without a super call) to modify the way queuing is
* performed (for example adding a vault/timelock).
*
* This is empty by default, and must be overridden to implement queuing.
*
* This function returns a timestamp that describes the expected ETA for execution. If the returned value is 0
* (which is the default value), the core will consider queueing did not succeed, and the public {queue} function
* will revert.
*
* NOTE: Calling this function directly will NOT check the current state of the proposal, or emit the
* `ProposalQueued` event. Queuing a proposal should be done using {queue}.
*/
function _queueOperations(
uint256 /*proposalId*/,
address[] memory /*targets*/,
uint256[] memory /*values*/,
bytes[] memory /*calldatas*/,
bytes32 /*descriptionHash*/
) internal virtual returns (uint48) {
return 0;
}
/// @inheritdoc IGovernor
function execute(
address[] memory targets,
uint256[] memory values,
bytes[] memory calldatas,
bytes32 descriptionHash
) public payable virtual returns (uint256) {
GovernorStorage storage $ = _getGovernorStorage();
uint256 proposalId = getProposalId(targets, values, calldatas, descriptionHash);
_validateStateBitmap(
proposalId,
_encodeStateBitmap(ProposalState.Succeeded) | _encodeStateBitmap(ProposalState.Queued)
);
// mark as executed before calls to avoid reentrancy
$._proposals[proposalId].executed = true;
// before execute: register governance call in queue.
if (_executor() != address(this)) {
for (uint256 i = 0; i < targets.length; ++i) {
if (targets[i] == address(this)) {
$._governanceCall.pushBack(keccak256(calldatas[i]));
}
}
}
_executeOperations(proposalId, targets, values, calldatas, descriptionHash);
// after execute: cleanup governance call queue.
if (_executor() != address(this) && !$._governanceCall.empty()) {
$._governanceCall.clear();
}
emit ProposalExecuted(proposalId);
return proposalId;
}
/**
* @dev Internal execution mechanism. Can be overridden (without a super call) to modify the way execution is
* performed (for example adding a vault/timelock).
*
* NOTE: Calling this function directly will NOT check the current state of the proposal, set the executed flag to
* true or emit the `ProposalExecuted` event. Executing a proposal should be done using {execute}.
*/
function _executeOperations(
uint256 /* proposalId */,
address[] memory targets,
uint256[] memory values,
bytes[] memory calldatas,
bytes32 /*descriptionHash*/
) internal virtual {
for (uint256 i = 0; i < targets.length; ++i) {
(bool success, bytes memory returndata) = targets[i].call{value: values[i]}(calldatas[i]);
Address.verifyCallResult(success, returndata);
}
}
/// @inheritdoc IGovernor
function cancel(
address[] memory targets,
uint256[] memory values,
bytes[] memory calldatas,
bytes32 descriptionHash
) public virtual returns (uint256) {
// The proposalId will be recomputed in the `_cancel` call further down. However we need the value before we
// do the internal call, because we need to check the proposal state BEFORE the internal `_cancel` call
// changes it. The `getProposalId` duplication has a cost that is limited, and that we accept.
uint256 proposalId = getProposalId(targets, values, calldatas, descriptionHash);
address caller = _msgSender();
if (!_validateCancel(proposalId, caller)) revert GovernorUnableToCancel(proposalId, caller);
return _cancel(targets, values, calldatas, descriptionHash);
}
/**
* @dev Internal cancel mechanism with minimal restrictions. A proposal can be cancelled in any state other than
* Canceled, Expired, or Executed. Once cancelled a proposal can't be re-submitted.
*
* Emits a {IGovernor-ProposalCanceled} event.
*/
function _cancel(
address[] memory targets,
uint256[] memory values,
bytes[] memory calldatas,
bytes32 descriptionHash
) internal virtual returns (uint256) {
GovernorStorage storage $ = _getGovernorStorage();
uint256 proposalId = getProposalId(targets, values, calldatas, descriptionHash);
_validateStateBitmap(
proposalId,
ALL_PROPOSAL_STATES_BITMAP ^
_encodeStateBitmap(ProposalState.Canceled) ^
_encodeStateBitmap(ProposalState.Expired) ^
_encodeStateBitmap(ProposalState.Executed)
);
$._proposals[proposalId].canceled = true;
emit ProposalCanceled(proposalId);
return proposalId;
}
/// @inheritdoc IGovernor
function getVotes(address account, uint256 timepoint) public view virtual returns (uint256) {
return _getVotes(account, timepoint, _defaultParams());
}
/// @inheritdoc IGovernor
function getVotesWithParams(
address account,
uint256 timepoint,
bytes memory params
) public view virtual returns (uint256) {
return _getVotes(account, timepoint, params);
}
/// @inheritdoc IGovernor
function castVote(uint256 proposalId, uint8 support) public virtual returns (uint256) {
address voter = _msgSender();
return _castVote(proposalId, voter, support, "");
}
/// @inheritdoc IGovernor
function castVoteWithReason(
uint256 proposalId,
uint8 support,
string calldata reason
) public virtual returns (uint256) {
address voter = _msgSender();
return _castVote(proposalId, voter, support, reason);
}
/// @inheritdoc IGovernor
function castVoteWithReasonAndParams(
uint256 proposalId,
uint8 support,
string calldata reason,
bytes memory params
) public virtual returns (uint256) {
address voter = _msgSender();
return _castVote(proposalId, voter, support, reason, params);
}
/// @inheritdoc IGovernor
function castVoteBySig(
uint256 proposalId,
uint8 support,
address voter,
bytes memory signature
) public virtual returns (uint256) {
if (!_validateVoteSig(proposalId, support, voter, signature)) {
revert GovernorInvalidSignature(voter);
}
return _castVote(proposalId, voter, support, "");
}
/// @inheritdoc IGovernor
function castVoteWithReasonAndParamsBySig(
uint256 proposalId,
uint8 support,
address voter,
string calldata reason,
bytes memory params,
bytes memory signature
) public virtual returns (uint256) {
if (!_validateExtendedVoteSig(proposalId, support, voter, reason, params, signature)) {
revert GovernorInvalidSignature(voter);
}
return _castVote(proposalId, voter, support, reason, params);
}
/// @dev Validate the `signature` used in {castVoteBySig} function.
function _validateVoteSig(
uint256 proposalId,
uint8 support,
address voter,
bytes memory signature
) internal virtual returns (bool) {
return
SignatureChecker.isValidSignatureNow(
voter,
_hashTypedDataV4(keccak256(abi.encode(BALLOT_TYPEHASH, proposalId, support, voter, _useNonce(voter)))),
signature
);
}
/// @dev Validate the `signature` used in {castVoteWithReasonAndParamsBySig} function.
function _validateExtendedVoteSig(
uint256 proposalId,
uint8 support,
address voter,
string memory reason,
bytes memory params,
bytes memory signature
) internal virtual returns (bool) {
return
SignatureChecker.isValidSignatureNow(
voter,
_hashTypedDataV4(
keccak256(
abi.encode(
EXTENDED_BALLOT_TYPEHASH,
proposalId,
support,
voter,
_useNonce(voter),
keccak256(bytes(reason)),
keccak256(params)
)
)
),
signature
);
}
/**
* @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve
* voting weight using {IGovernor-getVotes} and call the {_countVote} internal function. Uses the _defaultParams().
*
* Emits a {IGovernor-VoteCast} event.
*/
function _castVote(
uint256 proposalId,
address account,
uint8 support,
string memory reason
) internal virtual returns (uint256) {
return _castVote(proposalId, account, support, reason, _defaultParams());
}
/**
* @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve
* voting weight using {IGovernor-getVotes} and call the {_countVote} internal function.
*
* Emits a {IGovernor-VoteCast} event.
*/
function _castVote(
uint256 proposalId,
address account,
uint8 support,
string memory reason,
bytes memory params
) internal virtual returns (uint256) {
_validateStateBitmap(proposalId, _encodeStateBitmap(ProposalState.Active));
uint256 totalWeight = _getVotes(account, proposalSnapshot(proposalId), params);
uint256 votedWeight = _countVote(proposalId, account, support, totalWeight, params);
if (params.length == 0) {
emit VoteCast(account, proposalId, support, votedWeight, reason);
} else {
emit VoteCastWithParams(account, proposalId, support, votedWeight, reason, params);
}
_tallyUpdated(proposalId);
return votedWeight;
}
/**
* @dev Relays a transaction or function call to an arbitrary target. In cases where the governance executor
* is some contract other than the governor itself, like when using a timelock, this function can be invoked
* in a governance proposal to recover tokens or Ether that was sent to the governor contract by mistake.
* Note that if the executor is simply the governor itself, use of `relay` is redundant.
*/
function relay(address target, uint256 value, bytes calldata data) external payable virtual onlyGovernance {
(bool success, bytes memory returndata) = target.call{value: value}(data);
Address.verifyCallResult(success, returndata);
}
/**
* @dev Address through which the governor executes action. Will be overloaded by module that execute actions
* through another contract such as a timelock.
*/
function _executor() internal view virtual returns (address) {
return address(this);
}
/**
* @dev See {IERC721Receiver-onERC721Received}.
* Receiving tokens is disabled if the governance executor is other than the governor itself (eg. when using with a timelock).
*/
function onERC721Received(address, address, uint256, bytes memory) public virtual returns (bytes4) {
if (_executor() != address(this)) {
revert GovernorDisabledDeposit();
}
return this.onERC721Received.selector;
}
/**
* @dev See {IERC1155Receiver-onERC1155Received}.
* Receiving tokens is disabled if the governance executor is other than the governor itself (eg. when using with a timelock).
*/
function onERC1155Received(address, address, uint256, uint256, bytes memory) public virtual returns (bytes4) {
if (_executor() != address(this)) {
revert GovernorDisabledDeposit();
}
return this.onERC1155Received.selector;
}
/**
* @dev See {IERC1155Receiver-onERC1155BatchReceived}.
* Receiving tokens is disabled if the governance executor is other than the governor itself (eg. when using with a timelock).
*/
function onERC1155BatchReceived(
address,
address,
uint256[] memory,
uint256[] memory,
bytes memory
) public virtual returns (bytes4) {
if (_executor() != address(this)) {
revert GovernorDisabledDeposit();
}
return this.onERC1155BatchReceived.selector;
}
/**
* @dev Encodes a `ProposalState` into a `bytes32` representation where each bit enabled corresponds to
* the underlying position in the `ProposalState` enum. For example:
*
* 0x000...10000
* ^^^^^^------ ...
* ^----- Succeeded
* ^---- Defeated
* ^--- Canceled
* ^-- Active
* ^- Pending
*/
function _encodeStateBitmap(ProposalState proposalState) internal pure returns (bytes32) {
return bytes32(1 << uint8(proposalState));
}
/**
* @dev Check that the current state of a proposal matches the requirements described by the `allowedStates` bitmap.
* This bitmap should be built using `_encodeStateBitmap`.
*
* If requirements are not met, reverts with a {GovernorUnexpectedProposalState} error.
*/
function _validateStateBitmap(uint256 proposalId, bytes32 allowedStates) internal view returns (ProposalState) {
ProposalState currentState = state(proposalId);
if (_encodeStateBitmap(currentState) & allowedStates == bytes32(0)) {
revert GovernorUnexpectedProposalState(proposalId, currentState, allowedStates);
}
return currentState;
}
/*
* @dev Check if the proposer is authorized to submit a proposal with the given description.
*
* If the proposal description ends with `#proposer=0x???`, where `0x???` is an address written as a hex string
* (case insensitive), then the submission of this proposal will only be authorized to said address.
*
* This is used for frontrunning protection. By adding this pattern at the end of their proposal, one can ensure
* that no other address can submit the same proposal. An attacker would have to either remove or change that part,
* which would result in a different proposal id.
*
* If the description does not match this pattern, it is unrestricted and anyone can submit it. This includes:
* - If the `0x???` part is not a valid hex string.
* - If the `0x???` part is a valid hex string, but does not contain exactly 40 hex digits.
* - If it ends with the expected suffix followed by newlines or other whitespace.
* - If it ends with some other similar suffix, e.g. `#other=abc`.
* - If it does not end with any such suffix.
*/
function _isValidDescriptionForProposer(
address proposer,
string memory description
) internal view virtual returns (bool) {
unchecked {
uint256 length = bytes(description).length;
// Length is too short to contain a valid proposer suffix
if (length < 52) {
return true;
}
// Extract what would be the `#proposer=` marker beginning the suffix
bytes10 marker = bytes10(_unsafeReadBytesOffset(bytes(description), length - 52));
// If the marker is not found, there is no proposer suffix to check
if (marker != bytes10("#proposer=")) {
return true;
}
// Check that the last 42 characters (after the marker) are a properly formatted address.
(bool success, address recovered) = Strings.tryParseAddress(description, length - 42, length);
return !success || recovered == proposer;
}
}
/**
* @dev Check if the `caller` can cancel the proposal with the given `proposalId`.
*
* The default implementation allows the proposal proposer to cancel the proposal during the pending state.
*/
function _validateCancel(uint256 proposalId, address caller) internal view virtual returns (bool) {
return (state(proposalId) == ProposalState.Pending) && caller == proposalProposer(proposalId);
}
/// @inheritdoc IERC6372
function clock() public view virtual returns (uint48);
/// @inheritdoc IERC6372
// solhint-disable-next-line func-name-mixedcase
function CLOCK_MODE() public view virtual returns (string memory);
/// @inheritdoc IGovernor
function votingDelay() public view virtual returns (uint256);
/// @inheritdoc IGovernor
function votingPeriod() public view virtual returns (uint256);
/// @inheritdoc IGovernor
function quorum(uint256 timepoint) public view virtual returns (uint256);
/**
* @dev Reads a bytes32 from a bytes array without bounds checking.
*
* NOTE: making this function internal would mean it could be used with memory unsafe offset, and marking the
* assembly block as such would prevent some optimizations.
*/
function _unsafeReadBytesOffset(bytes memory buffer, uint256 offset) private pure returns (bytes32 value) {
// This is not memory safe in the general case, but all calls to this private function are within bounds.
assembly ("memory-safe") {
value := mload(add(add(buffer, 0x20), offset))
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (governance/TimelockController.sol)
pragma solidity ^0.8.20;
import {AccessControlUpgradeable} from "../access/AccessControlUpgradeable.sol";
import {ERC721HolderUpgradeable} from "../token/ERC721/utils/ERC721HolderUpgradeable.sol";
import {ERC1155HolderUpgradeable} from "../token/ERC1155/utils/ERC1155HolderUpgradeable.sol";
import {Address} from "@openzeppelin/contracts/utils/Address.sol";
import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol";
import {Initializable} from "../proxy/utils/Initializable.sol";
/**
* @dev Contract module which acts as a timelocked controller. When set as the
* owner of an `Ownable` smart contract, it enforces a timelock on all
* `onlyOwner` maintenance operations. This gives time for users of the
* controlled contract to exit before a potentially dangerous maintenance
* operation is applied.
*
* By default, this contract is self administered, meaning administration tasks
* have to go through the timelock process. The proposer (resp executor) role
* is in charge of proposing (resp executing) operations. A common use case is
* to position this {TimelockController} as the owner of a smart contract, with
* a multisig or a DAO as the sole proposer.
*/
contract TimelockControllerUpgradeable is Initializable, AccessControlUpgradeable, ERC721HolderUpgradeable, ERC1155HolderUpgradeable {
bytes32 public constant PROPOSER_ROLE = keccak256("PROPOSER_ROLE");
bytes32 public constant EXECUTOR_ROLE = keccak256("EXECUTOR_ROLE");
bytes32 public constant CANCELLER_ROLE = keccak256("CANCELLER_ROLE");
uint256 internal constant _DONE_TIMESTAMP = uint256(1);
/// @custom:storage-location erc7201:openzeppelin.storage.TimelockController
struct TimelockControllerStorage {
mapping(bytes32 id => uint256) _timestamps;
uint256 _minDelay;
}
// keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.TimelockController")) - 1)) & ~bytes32(uint256(0xff))
bytes32 private constant TimelockControllerStorageLocation = 0x9a37c2aa9d186a0969ff8a8267bf4e07e864c2f2768f5040949e28a624fb3600;
function _getTimelockControllerStorage() private pure returns (TimelockControllerStorage storage $) {
assembly {
$.slot := TimelockControllerStorageLocation
}
}
enum OperationState {
Unset,
Waiting,
Ready,
Done
}
/**
* @dev Mismatch between the parameters length for an operation call.
*/
error TimelockInvalidOperationLength(uint256 targets, uint256 payloads, uint256 values);
/**
* @dev The schedule operation doesn't meet the minimum delay.
*/
error TimelockInsufficientDelay(uint256 delay, uint256 minDelay);
/**
* @dev The current state of an operation is not as required.
* The `expectedStates` is a bitmap with the bits enabled for each OperationState enum position
* counting from right to left.
*
* See {_encodeStateBitmap}.
*/
error TimelockUnexpectedOperationState(bytes32 operationId, bytes32 expectedStates);
/**
* @dev The predecessor to an operation not yet done.
*/
error TimelockUnexecutedPredecessor(bytes32 predecessorId);
/**
* @dev The caller account is not authorized.
*/
error TimelockUnauthorizedCaller(address caller);
/**
* @dev Emitted when a call is scheduled as part of operation `id`.
*/
event CallScheduled(
bytes32 indexed id,
uint256 indexed index,
address target,
uint256 value,
bytes data,
bytes32 predecessor,
uint256 delay
);
/**
* @dev Emitted when a call is performed as part of operation `id`.
*/
event CallExecuted(bytes32 indexed id, uint256 indexed index, address target, uint256 value, bytes data);
/**
* @dev Emitted when new proposal is scheduled with non-zero salt.
*/
event CallSalt(bytes32 indexed id, bytes32 salt);
/**
* @dev Emitted when operation `id` is cancelled.
*/
event Cancelled(bytes32 indexed id);
/**
* @dev Emitted when the minimum delay for future operations is modified.
*/
event MinDelayChange(uint256 oldDuration, uint256 newDuration);
function initialize(uint256 minDelay, address[] memory proposers, address[] memory executors, address admin) public virtual initializer {
__TimelockController_init(minDelay, proposers, executors, admin);
}
/**
* @dev Initializes the contract with the following parameters:
*
* - `minDelay`: initial minimum delay in seconds for operations
* - `proposers`: accounts to be granted proposer and canceller roles
* - `executors`: accounts to be granted executor role
* - `admin`: optional account to be granted admin role; disable with zero address
*
* IMPORTANT: The optional admin can aid with initial configuration of roles after deployment
* without being subject to delay, but this role should be subsequently renounced in favor of
* administration through timelocked proposals. Previous versions of this contract would assign
* this admin to the deployer automatically and should be renounced as well.
*/
function __TimelockController_init(uint256 minDelay, address[] memory proposers, address[] memory executors, address admin) internal onlyInitializing {
__TimelockController_init_unchained(minDelay, proposers, executors, admin);
}
function __TimelockController_init_unchained(uint256 minDelay, address[] memory proposers, address[] memory executors, address admin) internal onlyInitializing {
TimelockControllerStorage storage $ = _getTimelockControllerStorage();
// self administration
_grantRole(DEFAULT_ADMIN_ROLE, address(this));
// optional admin
if (admin != address(0)) {
_grantRole(DEFAULT_ADMIN_ROLE, admin);
}
// register proposers and cancellers
for (uint256 i = 0; i < proposers.length; ++i) {
_grantRole(PROPOSER_ROLE, proposers[i]);
_grantRole(CANCELLER_ROLE, proposers[i]);
}
// register executors
for (uint256 i = 0; i < executors.length; ++i) {
_grantRole(EXECUTOR_ROLE, executors[i]);
}
$._minDelay = minDelay;
emit MinDelayChange(0, minDelay);
}
/**
* @dev Modifier to make a function callable only by a certain role. In
* addition to checking the sender's role, `address(0)` 's role is also
* considered. Granting a role to `address(0)` is equivalent to enabling
* this role for everyone.
*/
modifier onlyRoleOrOpenRole(bytes32 role) {
if (!hasRole(role, address(0))) {
_checkRole(role, _msgSender());
}
_;
}
/**
* @dev Contract might receive/hold ETH as part of the maintenance process.
*/
receive() external payable virtual {}
/// @inheritdoc IERC165
function supportsInterface(
bytes4 interfaceId
) public view virtual override(AccessControlUpgradeable, ERC1155HolderUpgradeable) returns (bool) {
return super.supportsInterface(interfaceId);
}
/**
* @dev Returns whether an id corresponds to a registered operation. This
* includes both Waiting, Ready, and Done operations.
*/
function isOperation(bytes32 id) public view returns (bool) {
return getOperationState(id) != OperationState.Unset;
}
/**
* @dev Returns whether an operation is pending or not. Note that a "pending" operation may also be "ready".
*/
function isOperationPending(bytes32 id) public view returns (bool) {
OperationState state = getOperationState(id);
return state == OperationState.Waiting || state == OperationState.Ready;
}
/**
* @dev Returns whether an operation is ready for execution. Note that a "ready" operation is also "pending".
*/
function isOperationReady(bytes32 id) public view returns (bool) {
return getOperationState(id) == OperationState.Ready;
}
/**
* @dev Returns whether an operation is done or not.
*/
function isOperationDone(bytes32 id) public view returns (bool) {
return getOperationState(id) == OperationState.Done;
}
/**
* @dev Returns the timestamp at which an operation becomes ready (0 for
* unset operations, 1 for done operations).
*/
function getTimestamp(bytes32 id) public view virtual returns (uint256) {
TimelockControllerStorage storage $ = _getTimelockControllerStorage();
return $._timestamps[id];
}
/**
* @dev Returns operation state.
*/
function getOperationState(bytes32 id) public view virtual returns (OperationState) {
uint256 timestamp = getTimestamp(id);
if (timestamp == 0) {
return OperationState.Unset;
} else if (timestamp == _DONE_TIMESTAMP) {
return OperationState.Done;
} else if (timestamp > block.timestamp) {
return OperationState.Waiting;
} else {
return OperationState.Ready;
}
}
/**
* @dev Returns the minimum delay in seconds for an operation to become valid.
*
* This value can be changed by executing an operation that calls `updateDelay`.
*/
function getMinDelay() public view virtual returns (uint256) {
TimelockControllerStorage storage $ = _getTimelockControllerStorage();
return $._minDelay;
}
/**
* @dev Returns the identifier of an operation containing a single
* transaction.
*/
function hashOperation(
address target,
uint256 value,
bytes calldata data,
bytes32 predecessor,
bytes32 salt
) public pure virtual returns (bytes32) {
return keccak256(abi.encode(target, value, data, predecessor, salt));
}
/**
* @dev Returns the identifier of an operation containing a batch of
* transactions.
*/
function hashOperationBatch(
address[] calldata targets,
uint256[] calldata values,
bytes[] calldata payloads,
bytes32 predecessor,
bytes32 salt
) public pure virtual returns (bytes32) {
return keccak256(abi.encode(targets, values, payloads, predecessor, salt));
}
/**
* @dev Schedule an operation containing a single transaction.
*
* Emits {CallSalt} if salt is nonzero, and {CallScheduled}.
*
* Requirements:
*
* - the caller must have the 'proposer' role.
*/
function schedule(
address target,
uint256 value,
bytes calldata data,
bytes32 predecessor,
bytes32 salt,
uint256 delay
) public virtual onlyRole(PROPOSER_ROLE) {
bytes32 id = hashOperation(target, value, data, predecessor, salt);
_schedule(id, delay);
emit CallScheduled(id, 0, target, value, data, predecessor, delay);
if (salt != bytes32(0)) {
emit CallSalt(id, salt);
}
}
/**
* @dev Schedule an operation containing a batch of transactions.
*
* Emits {CallSalt} if salt is nonzero, and one {CallScheduled} event per transaction in the batch.
*
* Requirements:
*
* - the caller must have the 'proposer' role.
*/
function scheduleBatch(
address[] calldata targets,
uint256[] calldata values,
bytes[] calldata payloads,
bytes32 predecessor,
bytes32 salt,
uint256 delay
) public virtual onlyRole(PROPOSER_ROLE) {
if (targets.length != values.length || targets.length != payloads.length) {
revert TimelockInvalidOperationLength(targets.length, payloads.length, values.length);
}
bytes32 id = hashOperationBatch(targets, values, payloads, predecessor, salt);
_schedule(id, delay);
for (uint256 i = 0; i < targets.length; ++i) {
emit CallScheduled(id, i, targets[i], values[i], payloads[i], predecessor, delay);
}
if (salt != bytes32(0)) {
emit CallSalt(id, salt);
}
}
/**
* @dev Schedule an operation that is to become valid after a given delay.
*/
function _schedule(bytes32 id, uint256 delay) private {
TimelockControllerStorage storage $ = _getTimelockControllerStorage();
if (isOperation(id)) {
revert TimelockUnexpectedOperationState(id, _encodeStateBitmap(OperationState.Unset));
}
uint256 minDelay = getMinDelay();
if (delay < minDelay) {
revert TimelockInsufficientDelay(delay, minDelay);
}
$._timestamps[id] = block.timestamp + delay;
}
/**
* @dev Cancel an operation.
*
* Requirements:
*
* - the caller must have the 'canceller' role.
*/
function cancel(bytes32 id) public virtual onlyRole(CANCELLER_ROLE) {
TimelockControllerStorage storage $ = _getTimelockControllerStorage();
if (!isOperationPending(id)) {
revert TimelockUnexpectedOperationState(
id,
_encodeStateBitmap(OperationState.Waiting) | _encodeStateBitmap(OperationState.Ready)
);
}
delete $._timestamps[id];
emit Cancelled(id);
}
/**
* @dev Execute an (ready) operation containing a single transaction.
*
* Emits a {CallExecuted} event.
*
* Requirements:
*
* - the caller must have the 'executor' role.
*/
// This function can reenter, but it doesn't pose a risk because _afterCall checks that the proposal is pending,
// thus any modifications to the operation during reentrancy should be caught.
// slither-disable-next-line reentrancy-eth
function execute(
address target,
uint256 value,
bytes calldata payload,
bytes32 predecessor,
bytes32 salt
) public payable virtual onlyRoleOrOpenRole(EXECUTOR_ROLE) {
bytes32 id = hashOperation(target, value, payload, predecessor, salt);
_beforeCall(id, predecessor);
_execute(target, value, payload);
emit CallExecuted(id, 0, target, value, payload);
_afterCall(id);
}
/**
* @dev Execute an (ready) operation containing a batch of transactions.
*
* Emits one {CallExecuted} event per transaction in the batch.
*
* Requirements:
*
* - the caller must have the 'executor' role.
*/
// This function can reenter, but it doesn't pose a risk because _afterCall checks that the proposal is pending,
// thus any modifications to the operation during reentrancy should be caught.
// slither-disable-next-line reentrancy-eth
function executeBatch(
address[] calldata targets,
uint256[] calldata values,
bytes[] calldata payloads,
bytes32 predecessor,
bytes32 salt
) public payable virtual onlyRoleOrOpenRole(EXECUTOR_ROLE) {
if (targets.length != values.length || targets.length != payloads.length) {
revert TimelockInvalidOperationLength(targets.length, payloads.length, values.length);
}
bytes32 id = hashOperationBatch(targets, values, payloads, predecessor, salt);
_beforeCall(id, predecessor);
for (uint256 i = 0; i < targets.length; ++i) {
address target = targets[i];
uint256 value = values[i];
bytes calldata payload = payloads[i];
_execute(target, value, payload);
emit CallExecuted(id, i, target, value, payload);
}
_afterCall(id);
}
/**
* @dev Execute an operation's call.
*/
function _execute(address target, uint256 value, bytes calldata data) internal virtual {
(bool success, bytes memory returndata) = target.call{value: value}(data);
Address.verifyCallResult(success, returndata);
}
/**
* @dev Checks before execution of an operation's calls.
*/
function _beforeCall(bytes32 id, bytes32 predecessor) private view {
if (!isOperationReady(id)) {
revert TimelockUnexpectedOperationState(id, _encodeStateBitmap(OperationState.Ready));
}
if (predecessor != bytes32(0) && !isOperationDone(predecessor)) {
revert TimelockUnexecutedPredecessor(predecessor);
}
}
/**
* @dev Checks after execution of an operation's calls.
*/
function _afterCall(bytes32 id) private {
TimelockControllerStorage storage $ = _getTimelockControllerStorage();
if (!isOperationReady(id)) {
revert TimelockUnexpectedOperationState(id, _encodeStateBitmap(OperationState.Ready));
}
$._timestamps[id] = _DONE_TIMESTAMP;
}
/**
* @dev Changes the minimum timelock duration for future operations.
*
* Emits a {MinDelayChange} event.
*
* Requirements:
*
* - the caller must be the timelock itself. This can only be achieved by scheduling and later executing
* an operation where the timelock is the target and the data is the ABI-encoded call to this function.
*/
function updateDelay(uint256 newDelay) external virtual {
TimelockControllerStorage storage $ = _getTimelockControllerStorage();
address sender = _msgSender();
if (sender != address(this)) {
revert TimelockUnauthorizedCaller(sender);
}
emit MinDelayChange($._minDelay, newDelay);
$._minDelay = newDelay;
}
/**
* @dev Encodes a `OperationState` into a `bytes32` representation where each bit enabled corresponds to
* the underlying position in the `OperationState` enum. For example:
*
* 0x000...1000
* ^^^^^^----- ...
* ^---- Done
* ^--- Ready
* ^-- Waiting
* ^- Unset
*/
function _encodeStateBitmap(OperationState operationState) internal pure returns (bytes32) {
return bytes32(1 << uint8(operationState));
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.2.0) (governance/utils/Votes.sol)
pragma solidity ^0.8.20;
import {IERC5805} from "@openzeppelin/contracts/interfaces/IERC5805.sol";
import {ContextUpgradeable} from "../../utils/ContextUpgradeable.sol";
import {NoncesUpgradeable} from "../../utils/NoncesUpgradeable.sol";
import {EIP712Upgradeable} from "../../utils/cryptography/EIP712Upgradeable.sol";
import {Checkpoints} from "@openzeppelin/contracts/utils/structs/Checkpoints.sol";
import {SafeCast} from "@openzeppelin/contracts/utils/math/SafeCast.sol";
import {ECDSA} from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
import {Time} from "@openzeppelin/contracts/utils/types/Time.sol";
import {Initializable} from "../../proxy/utils/Initializable.sol";
/**
* @dev This is a base abstract contract that tracks voting units, which are a measure of voting power that can be
* transferred, and provides a system of vote delegation, where an account can delegate its voting units to a sort of
* "representative" that will pool delegated voting units from different accounts and can then use it to vote in
* decisions. In fact, voting units _must_ be delegated in order to count as actual votes, and an account has to
* delegate those votes to itself if it wishes to participate in decisions and does not have a trusted representative.
*
* This contract is often combined with a token contract such that voting units correspond to token units. For an
* example, see {ERC721Votes}.
*
* The full history of delegate votes is tracked on-chain so that governance protocols can consider votes as distributed
* at a particular block number to protect against flash loans and double voting. The opt-in delegate system makes the
* cost of this history tracking optional.
*
* When using this module the derived contract must implement {_getVotingUnits} (for example, make it return
* {ERC721-balanceOf}), and can use {_transferVotingUnits} to track a change in the distribution of those units (in the
* previous example, it would be included in {ERC721-_update}).
*/
abstract contract VotesUpgradeable is Initializable, ContextUpgradeable, EIP712Upgradeable, NoncesUpgradeable, IERC5805 {
using Checkpoints for Checkpoints.Trace208;
bytes32 private constant DELEGATION_TYPEHASH =
keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)");
/// @custom:storage-location erc7201:openzeppelin.storage.Votes
struct VotesStorage {
mapping(address account => address) _delegatee;
mapping(address delegatee => Checkpoints.Trace208) _delegateCheckpoints;
Checkpoints.Trace208 _totalCheckpoints;
}
// keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Votes")) - 1)) & ~bytes32(uint256(0xff))
bytes32 private constant VotesStorageLocation = 0xe8b26c30fad74198956032a3533d903385d56dd795af560196f9c78d4af40d00;
function _getVotesStorage() private pure returns (VotesStorage storage $) {
assembly {
$.slot := VotesStorageLocation
}
}
/**
* @dev The clock was incorrectly modified.
*/
error ERC6372InconsistentClock();
/**
* @dev Lookup to future votes is not available.
*/
error ERC5805FutureLookup(uint256 timepoint, uint48 clock);
function __Votes_init() internal onlyInitializing {
}
function __Votes_init_unchained() internal onlyInitializing {
}
/**
* @dev Clock used for flagging checkpoints. Can be overridden to implement timestamp based
* checkpoints (and voting), in which case {CLOCK_MODE} should be overridden as well to match.
*/
function clock() public view virtual returns (uint48) {
return Time.blockNumber();
}
/**
* @dev Machine-readable description of the clock as specified in ERC-6372.
*/
// solhint-disable-next-line func-name-mixedcase
function CLOCK_MODE() public view virtual returns (string memory) {
// Check that the clock was not modified
if (clock() != Time.blockNumber()) {
revert ERC6372InconsistentClock();
}
return "mode=blocknumber&from=default";
}
/**
* @dev Validate that a timepoint is in the past, and return it as a uint48.
*/
function _validateTimepoint(uint256 timepoint) internal view returns (uint48) {
uint48 currentTimepoint = clock();
if (timepoint >= currentTimepoint) revert ERC5805FutureLookup(timepoint, currentTimepoint);
return SafeCast.toUint48(timepoint);
}
/**
* @dev Returns the current amount of votes that `account` has.
*/
function getVotes(address account) public view virtual returns (uint256) {
VotesStorage storage $ = _getVotesStorage();
return $._delegateCheckpoints[account].latest();
}
/**
* @dev Returns the amount of votes that `account` had at a specific moment in the past. If the `clock()` is
* configured to use block numbers, this will return the value at the end of the corresponding block.
*
* Requirements:
*
* - `timepoint` must be in the past. If operating using block numbers, the block must be already mined.
*/
function getPastVotes(address account, uint256 timepoint) public view virtual returns (uint256) {
VotesStorage storage $ = _getVotesStorage();
return $._delegateCheckpoints[account].upperLookupRecent(_validateTimepoint(timepoint));
}
/**
* @dev Returns the total supply of votes available at a specific moment in the past. If the `clock()` is
* configured to use block numbers, this will return the value at the end of the corresponding block.
*
* NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes.
* Votes that have not been delegated are still part of total supply, even though they would not participate in a
* vote.
*
* Requirements:
*
* - `timepoint` must be in the past. If operating using block numbers, the block must be already mined.
*/
function getPastTotalSupply(uint256 timepoint) public view virtual returns (uint256) {
VotesStorage storage $ = _getVotesStorage();
return $._totalCheckpoints.upperLookupRecent(_validateTimepoint(timepoint));
}
/**
* @dev Returns the current total supply of votes.
*/
function _getTotalSupply() internal view virtual returns (uint256) {
VotesStorage storage $ = _getVotesStorage();
return $._totalCheckpoints.latest();
}
/**
* @dev Returns the delegate that `account` has chosen.
*/
function delegates(address account) public view virtual returns (address) {
VotesStorage storage $ = _getVotesStorage();
return $._delegatee[account];
}
/**
* @dev Delegates votes from the sender to `delegatee`.
*/
function delegate(address delegatee) public virtual {
address account = _msgSender();
_delegate(account, delegatee);
}
/**
* @dev Delegates votes from signer to `delegatee`.
*/
function delegateBySig(
address delegatee,
uint256 nonce,
uint256 expiry,
uint8 v,
bytes32 r,
bytes32 s
) public virtual {
if (block.timestamp > expiry) {
revert VotesExpiredSignature(expiry);
}
address signer = ECDSA.recover(
_hashTypedDataV4(keccak256(abi.encode(DELEGATION_TYPEHASH, delegatee, nonce, expiry))),
v,
r,
s
);
_useCheckedNonce(signer, nonce);
_delegate(signer, delegatee);
}
/**
* @dev Delegate all of `account`'s voting units to `delegatee`.
*
* Emits events {IVotes-DelegateChanged} and {IVotes-DelegateVotesChanged}.
*/
function _delegate(address account, address delegatee) internal virtual {
VotesStorage storage $ = _getVotesStorage();
address oldDelegate = delegates(account);
$._delegatee[account] = delegatee;
emit DelegateChanged(account, oldDelegate, delegatee);
_moveDelegateVotes(oldDelegate, delegatee, _getVotingUnits(account));
}
/**
* @dev Transfers, mints, or burns voting units. To register a mint, `from` should be zero. To register a burn, `to`
* should be zero. Total supply of voting units will be adjusted with mints and burns.
*/
function _transferVotingUnits(address from, address to, uint256 amount) internal virtual {
VotesStorage storage $ = _getVotesStorage();
if (from == address(0)) {
_push($._totalCheckpoints, _add, SafeCast.toUint208(amount));
}
if (to == address(0)) {
_push($._totalCheckpoints, _subtract, SafeCast.toUint208(amount));
}
_moveDelegateVotes(delegates(from), delegates(to), amount);
}
/**
* @dev Moves delegated votes from one delegate to another.
*/
function _moveDelegateVotes(address from, address to, uint256 amount) internal virtual {
VotesStorage storage $ = _getVotesStorage();
if (from != to && amount > 0) {
if (from != address(0)) {
(uint256 oldValue, uint256 newValue) = _push(
$._delegateCheckpoints[from],
_subtract,
SafeCast.toUint208(amount)
);
emit DelegateVotesChanged(from, oldValue, newValue);
}
if (to != address(0)) {
(uint256 oldValue, uint256 newValue) = _push(
$._delegateCheckpoints[to],
_add,
SafeCast.toUint208(amount)
);
emit DelegateVotesChanged(to, oldValue, newValue);
}
}
}
/**
* @dev Get number of checkpoints for `account`.
*/
function _numCheckpoints(address account) internal view virtual returns (uint32) {
VotesStorage storage $ = _getVotesStorage();
return SafeCast.toUint32($._delegateCheckpoints[account].length());
}
/**
* @dev Get the `pos`-th checkpoint for `account`.
*/
function _checkpoints(
address account,
uint32 pos
) internal view virtual returns (Checkpoints.Checkpoint208 memory) {
VotesStorage storage $ = _getVotesStorage();
return $._delegateCheckpoints[account].at(pos);
}
function _push(
Checkpoints.Trace208 storage store,
function(uint208, uint208) view returns (uint208) op,
uint208 delta
) private returns (uint208 oldValue, uint208 newValue) {
return store.push(clock(), op(store.latest(), delta));
}
function _add(uint208 a, uint208 b) private pure returns (uint208) {
return a + b;
}
function _subtract(uint208 a, uint208 b) private pure returns (uint208) {
return a - b;
}
/**
* @dev Must return the voting units held by an account.
*/
function _getVotingUnits(address) internal view virtual returns (uint256);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.3.0) (proxy/utils/Initializable.sol)
pragma solidity ^0.8.20;
/**
* @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
* behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an
* external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
* function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
*
* The initialization functions use a version number. Once a version number is used, it is consumed and cannot be
* reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in
* case an upgrade adds a module that needs to be initialized.
*
* For example:
*
* [.hljs-theme-light.nopadding]
* ```solidity
* contract MyToken is ERC20Upgradeable {
* function initialize() initializer public {
* __ERC20_init("MyToken", "MTK");
* }
* }
*
* contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {
* function initializeV2() reinitializer(2) public {
* __ERC20Permit_init("MyToken");
* }
* }
* ```
*
* TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
* possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.
*
* CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
* that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
*
* [CAUTION]
* ====
* Avoid leaving a contract uninitialized.
*
* An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation
* contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke
* the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:
*
* [.hljs-theme-light.nopadding]
* ```
* /// @custom:oz-upgrades-unsafe-allow constructor
* constructor() {
* _disableInitializers();
* }
* ```
* ====
*/
abstract contract Initializable {
/**
* @dev Storage of the initializable contract.
*
* It's implemented on a custom ERC-7201 namespace to reduce the risk of storage collisions
* when using with upgradeable contracts.
*
* @custom:storage-location erc7201:openzeppelin.storage.Initializable
*/
struct InitializableStorage {
/**
* @dev Indicates that the contract has been initialized.
*/
uint64 _initialized;
/**
* @dev Indicates that the contract is in the process of being initialized.
*/
bool _initializing;
}
// keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Initializable")) - 1)) & ~bytes32(uint256(0xff))
bytes32 private constant INITIALIZABLE_STORAGE = 0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00;
/**
* @dev The contract is already initialized.
*/
error InvalidInitialization();
/**
* @dev The contract is not initializing.
*/
error NotInitializing();
/**
* @dev Triggered when the contract has been initialized or reinitialized.
*/
event Initialized(uint64 version);
/**
* @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,
* `onlyInitializing` functions can be used to initialize parent contracts.
*
* Similar to `reinitializer(1)`, except that in the context of a constructor an `initializer` may be invoked any
* number of times. This behavior in the constructor can be useful during testing and is not expected to be used in
* production.
*
* Emits an {Initialized} event.
*/
modifier initializer() {
// solhint-disable-next-line var-name-mixedcase
InitializableStorage storage $ = _getInitializableStorage();
// Cache values to avoid duplicated sloads
bool isTopLevelCall = !$._initializing;
uint64 initialized = $._initialized;
// Allowed calls:
// - initialSetup: the contract is not in the initializing state and no previous version was
// initialized
// - construction: the contract is initialized at version 1 (no reinitialization) and the
// current contract is just being deployed
bool initialSetup = initialized == 0 && isTopLevelCall;
bool construction = initialized == 1 && address(this).code.length == 0;
if (!initialSetup && !construction) {
revert InvalidInitialization();
}
$._initialized = 1;
if (isTopLevelCall) {
$._initializing = true;
}
_;
if (isTopLevelCall) {
$._initializing = false;
emit Initialized(1);
}
}
/**
* @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the
* contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be
* used to initialize parent contracts.
*
* A reinitializer may be used after the original initialization step. This is essential to configure modules that
* are added through upgrades and that require initialization.
*
* When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`
* cannot be nested. If one is invoked in the context of another, execution will revert.
*
* Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in
* a contract, executing them in the right order is up to the developer or operator.
*
* WARNING: Setting the version to 2**64 - 1 will prevent any future reinitialization.
*
* Emits an {Initialized} event.
*/
modifier reinitializer(uint64 version) {
// solhint-disable-next-line var-name-mixedcase
InitializableStorage storage $ = _getInitializableStorage();
if ($._initializing || $._initialized >= version) {
revert InvalidInitialization();
}
$._initialized = version;
$._initializing = true;
_;
$._initializing = false;
emit Initialized(version);
}
/**
* @dev Modifier to protect an initialization function so that it can only be invoked by functions with the
* {initializer} and {reinitializer} modifiers, directly or indirectly.
*/
modifier onlyInitializing() {
_checkInitializing();
_;
}
/**
* @dev Reverts if the contract is not in an initializing state. See {onlyInitializing}.
*/
function _checkInitializing() internal view virtual {
if (!_isInitializing()) {
revert NotInitializing();
}
}
/**
* @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.
* Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized
* to any version. It is recommended to use this to lock implementation contracts that are designed to be called
* through proxies.
*
* Emits an {Initialized} event the first time it is successfully executed.
*/
function _disableInitializers() internal virtual {
// solhint-disable-next-line var-name-mixedcase
InitializableStorage storage $ = _getInitializableStorage();
if ($._initializing) {
revert InvalidInitialization();
}
if ($._initialized != type(uint64).max) {
$._initialized = type(uint64).max;
emit Initialized(type(uint64).max);
}
}
/**
* @dev Returns the highest version that has been initialized. See {reinitializer}.
*/
function _getInitializedVersion() internal view returns (uint64) {
return _getInitializableStorage()._initialized;
}
/**
* @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.
*/
function _isInitializing() internal view returns (bool) {
return _getInitializableStorage()._initializing;
}
/**
* @dev Pointer to storage slot. Allows integrators to override it with a custom storage location.
*
* NOTE: Consider following the ERC-7201 formula to derive storage locations.
*/
function _initializableStorageSlot() internal pure virtual returns (bytes32) {
return INITIALIZABLE_STORAGE;
}
/**
* @dev Returns a pointer to the storage namespace.
*/
// solhint-disable-next-line var-name-mixedcase
function _getInitializableStorage() private pure returns (InitializableStorage storage $) {
bytes32 slot = _initializableStorageSlot();
assembly {
$.slot := slot
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC1155/utils/ERC1155Holder.sol)
pragma solidity ^0.8.20;
import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol";
import {ERC165Upgradeable} from "../../../utils/introspection/ERC165Upgradeable.sol";
import {IERC1155Receiver} from "@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol";
import {Initializable} from "../../../proxy/utils/Initializable.sol";
/**
* @dev Simple implementation of `IERC1155Receiver` that will allow a contract to hold ERC-1155 tokens.
*
* IMPORTANT: When inheriting this contract, you must include a way to use the received tokens, otherwise they will be
* stuck.
*/
abstract contract ERC1155HolderUpgradeable is Initializable, ERC165Upgradeable, IERC1155Receiver {
function __ERC1155Holder_init() internal onlyInitializing {
}
function __ERC1155Holder_init_unchained() internal onlyInitializing {
}
/// @inheritdoc IERC165
function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165Upgradeable, IERC165) returns (bool) {
return interfaceId == type(IERC1155Receiver).interfaceId || super.supportsInterface(interfaceId);
}
function onERC1155Received(
address,
address,
uint256,
uint256,
bytes memory
) public virtual override returns (bytes4) {
return this.onERC1155Received.selector;
}
function onERC1155BatchReceived(
address,
address,
uint256[] memory,
uint256[] memory,
bytes memory
) public virtual override returns (bytes4) {
return this.onERC1155BatchReceived.selector;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC20/ERC20.sol)
pragma solidity ^0.8.20;
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {IERC20Metadata} from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
import {ContextUpgradeable} from "../../utils/ContextUpgradeable.sol";
import {IERC20Errors} from "@openzeppelin/contracts/interfaces/draft-IERC6093.sol";
import {Initializable} from "../../proxy/utils/Initializable.sol";
/**
* @dev Implementation of the {IERC20} interface.
*
* This implementation is agnostic to the way tokens are created. This means
* that a supply mechanism has to be added in a derived contract using {_mint}.
*
* TIP: For a detailed writeup see our guide
* https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How
* to implement supply mechanisms].
*
* The default value of {decimals} is 18. To change this, you should override
* this function so it returns a different value.
*
* We have followed general OpenZeppelin Contracts guidelines: functions revert
* instead returning `false` on failure. This behavior is nonetheless
* conventional and does not conflict with the expectations of ERC-20
* applications.
*/
abstract contract ERC20Upgradeable is Initializable, ContextUpgradeable, IERC20, IERC20Metadata, IERC20Errors {
/// @custom:storage-location erc7201:openzeppelin.storage.ERC20
struct ERC20Storage {
mapping(address account => uint256) _balances;
mapping(address account => mapping(address spender => uint256)) _allowances;
uint256 _totalSupply;
string _name;
string _symbol;
}
// keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.ERC20")) - 1)) & ~bytes32(uint256(0xff))
bytes32 private constant ERC20StorageLocation = 0x52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace00;
function _getERC20Storage() private pure returns (ERC20Storage storage $) {
assembly {
$.slot := ERC20StorageLocation
}
}
/**
* @dev Sets the values for {name} and {symbol}.
*
* Both values are immutable: they can only be set once during construction.
*/
function __ERC20_init(string memory name_, string memory symbol_) internal onlyInitializing {
__ERC20_init_unchained(name_, symbol_);
}
function __ERC20_init_unchained(string memory name_, string memory symbol_) internal onlyInitializing {
ERC20Storage storage $ = _getERC20Storage();
$._name = name_;
$._symbol = symbol_;
}
/**
* @dev Returns the name of the token.
*/
function name() public view virtual returns (string memory) {
ERC20Storage storage $ = _getERC20Storage();
return $._name;
}
/**
* @dev Returns the symbol of the token, usually a shorter version of the
* name.
*/
function symbol() public view virtual returns (string memory) {
ERC20Storage storage $ = _getERC20Storage();
return $._symbol;
}
/**
* @dev Returns the number of decimals used to get its user representation.
* For example, if `decimals` equals `2`, a balance of `505` tokens should
* be displayed to a user as `5.05` (`505 / 10 ** 2`).
*
* Tokens usually opt for a value of 18, imitating the relationship between
* Ether and Wei. This is the default value returned by this function, unless
* it's overridden.
*
* NOTE: This information is only used for _display_ purposes: it in
* no way affects any of the arithmetic of the contract, including
* {IERC20-balanceOf} and {IERC20-transfer}.
*/
function decimals() public view virtual returns (uint8) {
return 18;
}
/// @inheritdoc IERC20
function totalSupply() public view virtual returns (uint256) {
ERC20Storage storage $ = _getERC20Storage();
return $._totalSupply;
}
/// @inheritdoc IERC20
function balanceOf(address account) public view virtual returns (uint256) {
ERC20Storage storage $ = _getERC20Storage();
return $._balances[account];
}
/**
* @dev See {IERC20-transfer}.
*
* Requirements:
*
* - `to` cannot be the zero address.
* - the caller must have a balance of at least `value`.
*/
function transfer(address to, uint256 value) public virtual returns (bool) {
address owner = _msgSender();
_transfer(owner, to, value);
return true;
}
/// @inheritdoc IERC20
function allowance(address owner, address spender) public view virtual returns (uint256) {
ERC20Storage storage $ = _getERC20Storage();
return $._allowances[owner][spender];
}
/**
* @dev See {IERC20-approve}.
*
* NOTE: If `value` is the maximum `uint256`, the allowance is not updated on
* `transferFrom`. This is semantically equivalent to an infinite approval.
*
* Requirements:
*
* - `spender` cannot be the zero address.
*/
function approve(address spender, uint256 value) public virtual returns (bool) {
address owner = _msgSender();
_approve(owner, spender, value);
return true;
}
/**
* @dev See {IERC20-transferFrom}.
*
* Skips emitting an {Approval} event indicating an allowance update. This is not
* required by the ERC. See {xref-ERC20-_approve-address-address-uint256-bool-}[_approve].
*
* NOTE: Does not update the allowance if the current allowance
* is the maximum `uint256`.
*
* Requirements:
*
* - `from` and `to` cannot be the zero address.
* - `from` must have a balance of at least `value`.
* - the caller must have allowance for ``from``'s tokens of at least
* `value`.
*/
function transferFrom(address from, address to, uint256 value) public virtual returns (bool) {
address spender = _msgSender();
_spendAllowance(from, spender, value);
_transfer(from, to, value);
return true;
}
/**
* @dev Moves a `value` amount of tokens from `from` to `to`.
*
* This internal function is equivalent to {transfer}, and can be used to
* e.g. implement automatic token fees, slashing mechanisms, etc.
*
* Emits a {Transfer} event.
*
* NOTE: This function is not virtual, {_update} should be overridden instead.
*/
function _transfer(address from, address to, uint256 value) internal {
if (from == address(0)) {
revert ERC20InvalidSender(address(0));
}
if (to == address(0)) {
revert ERC20InvalidReceiver(address(0));
}
_update(from, to, value);
}
/**
* @dev Transfers a `value` amount of tokens from `from` to `to`, or alternatively mints (or burns) if `from`
* (or `to`) is the zero address. All customizations to transfers, mints, and burns should be done by overriding
* this function.
*
* Emits a {Transfer} event.
*/
function _update(address from, address to, uint256 value) internal virtual {
ERC20Storage storage $ = _getERC20Storage();
if (from == address(0)) {
// Overflow check required: The rest of the code assumes that totalSupply never overflows
$._totalSupply += value;
} else {
uint256 fromBalance = $._balances[from];
if (fromBalance < value) {
revert ERC20InsufficientBalance(from, fromBalance, value);
}
unchecked {
// Overflow not possible: value <= fromBalance <= totalSupply.
$._balances[from] = fromBalance - value;
}
}
if (to == address(0)) {
unchecked {
// Overflow not possible: value <= totalSupply or value <= fromBalance <= totalSupply.
$._totalSupply -= value;
}
} else {
unchecked {
// Overflow not possible: balance + value is at most totalSupply, which we know fits into a uint256.
$._balances[to] += value;
}
}
emit Transfer(from, to, value);
}
/**
* @dev Creates a `value` amount of tokens and assigns them to `account`, by transferring it from address(0).
* Relies on the `_update` mechanism
*
* Emits a {Transfer} event with `from` set to the zero address.
*
* NOTE: This function is not virtual, {_update} should be overridden instead.
*/
function _mint(address account, uint256 value) internal {
if (account == address(0)) {
revert ERC20InvalidReceiver(address(0));
}
_update(address(0), account, value);
}
/**
* @dev Destroys a `value` amount of tokens from `account`, lowering the total supply.
* Relies on the `_update` mechanism.
*
* Emits a {Transfer} event with `to` set to the zero address.
*
* NOTE: This function is not virtual, {_update} should be overridden instead
*/
function _burn(address account, uint256 value) internal {
if (account == address(0)) {
revert ERC20InvalidSender(address(0));
}
_update(account, address(0), value);
}
/**
* @dev Sets `value` as the allowance of `spender` over the `owner`'s tokens.
*
* This internal function is equivalent to `approve`, and can be used to
* e.g. set automatic allowances for certain subsystems, etc.
*
* Emits an {Approval} event.
*
* Requirements:
*
* - `owner` cannot be the zero address.
* - `spender` cannot be the zero address.
*
* Overrides to this logic should be done to the variant with an additional `bool emitEvent` argument.
*/
function _approve(address owner, address spender, uint256 value) internal {
_approve(owner, spender, value, true);
}
/**
* @dev Variant of {_approve} with an optional flag to enable or disable the {Approval} event.
*
* By default (when calling {_approve}) the flag is set to true. On the other hand, approval changes made by
* `_spendAllowance` during the `transferFrom` operation set the flag to false. This saves gas by not emitting any
* `Approval` event during `transferFrom` operations.
*
* Anyone who wishes to continue emitting `Approval` events on the`transferFrom` operation can force the flag to
* true using the following override:
*
* ```solidity
* function _approve(address owner, address spender, uint256 value, bool) internal virtual override {
* super._approve(owner, spender, value, true);
* }
* ```
*
* Requirements are the same as {_approve}.
*/
function _approve(address owner, address spender, uint256 value, bool emitEvent) internal virtual {
ERC20Storage storage $ = _getERC20Storage();
if (owner == address(0)) {
revert ERC20InvalidApprover(address(0));
}
if (spender == address(0)) {
revert ERC20InvalidSpender(address(0));
}
$._allowances[owner][spender] = value;
if (emitEvent) {
emit Approval(owner, spender, value);
}
}
/**
* @dev Updates `owner`'s allowance for `spender` based on spent `value`.
*
* Does not update the allowance value in case of infinite allowance.
* Revert if not enough allowance is available.
*
* Does not emit an {Approval} event.
*/
function _spendAllowance(address owner, address spender, uint256 value) internal virtual {
uint256 currentAllowance = allowance(owner, spender);
if (currentAllowance < type(uint256).max) {
if (currentAllowance < value) {
revert ERC20InsufficientAllowance(spender, currentAllowance, value);
}
unchecked {
_approve(owner, spender, currentAllowance - value, false);
}
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC20/extensions/ERC20Permit.sol)
pragma solidity ^0.8.20;
import {IERC20Permit} from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol";
import {ERC20Upgradeable} from "../ERC20Upgradeable.sol";
import {ECDSA} from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
import {EIP712Upgradeable} from "../../../utils/cryptography/EIP712Upgradeable.sol";
import {NoncesUpgradeable} from "../../../utils/NoncesUpgradeable.sol";
import {Initializable} from "../../../proxy/utils/Initializable.sol";
/**
* @dev Implementation of the ERC-20 Permit extension allowing approvals to be made via signatures, as defined in
* https://eips.ethereum.org/EIPS/eip-2612[ERC-2612].
*
* Adds the {permit} method, which can be used to change an account's ERC-20 allowance (see {IERC20-allowance}) by
* presenting a message signed by the account. By not relying on `{IERC20-approve}`, the token holder account doesn't
* need to send a transaction, and thus is not required to hold Ether at all.
*/
abstract contract ERC20PermitUpgradeable is Initializable, ERC20Upgradeable, IERC20Permit, EIP712Upgradeable, NoncesUpgradeable {
bytes32 private constant PERMIT_TYPEHASH =
keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)");
/**
* @dev Permit deadline has expired.
*/
error ERC2612ExpiredSignature(uint256 deadline);
/**
* @dev Mismatched signature.
*/
error ERC2612InvalidSigner(address signer, address owner);
/**
* @dev Initializes the {EIP712} domain separator using the `name` parameter, and setting `version` to `"1"`.
*
* It's a good idea to use the same `name` that is defined as the ERC-20 token name.
*/
function __ERC20Permit_init(string memory name) internal onlyInitializing {
__EIP712_init_unchained(name, "1");
}
function __ERC20Permit_init_unchained(string memory) internal onlyInitializing {}
/// @inheritdoc IERC20Permit
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) public virtual {
if (block.timestamp > deadline) {
revert ERC2612ExpiredSignature(deadline);
}
bytes32 structHash = keccak256(abi.encode(PERMIT_TYPEHASH, owner, spender, value, _useNonce(owner), deadline));
bytes32 hash = _hashTypedDataV4(structHash);
address signer = ECDSA.recover(hash, v, r, s);
if (signer != owner) {
revert ERC2612InvalidSigner(signer, owner);
}
_approve(owner, spender, value);
}
/// @inheritdoc IERC20Permit
function nonces(address owner) public view virtual override(IERC20Permit, NoncesUpgradeable) returns (uint256) {
return super.nonces(owner);
}
/// @inheritdoc IERC20Permit
// solhint-disable-next-line func-name-mixedcase
function DOMAIN_SEPARATOR() external view virtual returns (bytes32) {
return _domainSeparatorV4();
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/extensions/ERC20Votes.sol)
pragma solidity ^0.8.20;
import {ERC20Upgradeable} from "../ERC20Upgradeable.sol";
import {VotesUpgradeable} from "../../../governance/utils/VotesUpgradeable.sol";
import {Checkpoints} from "@openzeppelin/contracts/utils/structs/Checkpoints.sol";
import {Initializable} from "../../../proxy/utils/Initializable.sol";
/**
* @dev Extension of ERC-20 to support Compound-like voting and delegation. This version is more generic than Compound's,
* and supports token supply up to 2^208^ - 1, while COMP is limited to 2^96^ - 1.
*
* NOTE: This contract does not provide interface compatibility with Compound's COMP token.
*
* This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either
* by calling the {Votes-delegate} function directly, or by providing a signature to be used with {Votes-delegateBySig}. Voting
* power can be queried through the public accessors {Votes-getVotes} and {Votes-getPastVotes}.
*
* By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it
* requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked.
*/
abstract contract ERC20VotesUpgradeable is Initializable, ERC20Upgradeable, VotesUpgradeable {
/**
* @dev Total supply cap has been exceeded, introducing a risk of votes overflowing.
*/
error ERC20ExceededSafeSupply(uint256 increasedSupply, uint256 cap);
function __ERC20Votes_init() internal onlyInitializing {
}
function __ERC20Votes_init_unchained() internal onlyInitializing {
}
/**
* @dev Maximum token supply. Defaults to `type(uint208).max` (2^208^ - 1).
*
* This maximum is enforced in {_update}. It limits the total supply of the token, which is otherwise a uint256,
* so that checkpoints can be stored in the Trace208 structure used by {Votes}. Increasing this value will not
* remove the underlying limitation, and will cause {_update} to fail because of a math overflow in
* {Votes-_transferVotingUnits}. An override could be used to further restrict the total supply (to a lower value) if
* additional logic requires it. When resolving override conflicts on this function, the minimum should be
* returned.
*/
function _maxSupply() internal view virtual returns (uint256) {
return type(uint208).max;
}
/**
* @dev Move voting power when tokens are transferred.
*
* Emits a {IVotes-DelegateVotesChanged} event.
*/
function _update(address from, address to, uint256 value) internal virtual override {
super._update(from, to, value);
if (from == address(0)) {
uint256 supply = totalSupply();
uint256 cap = _maxSupply();
if (supply > cap) {
revert ERC20ExceededSafeSupply(supply, cap);
}
}
_transferVotingUnits(from, to, value);
}
/**
* @dev Returns the voting units of an `account`.
*
* WARNING: Overriding this function may compromise the internal vote accounting.
* `ERC20Votes` assumes tokens map to voting units 1:1 and this is not easy to change.
*/
function _getVotingUnits(address account) internal view virtual override returns (uint256) {
return balanceOf(account);
}
/**
* @dev Get number of checkpoints for `account`.
*/
function numCheckpoints(address account) public view virtual returns (uint32) {
return _numCheckpoints(account);
}
/**
* @dev Get the `pos`-th checkpoint for `account`.
*/
function checkpoints(address account, uint32 pos) public view virtual returns (Checkpoints.Checkpoint208 memory) {
return _checkpoints(account, pos);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/utils/ERC721Holder.sol)
pragma solidity ^0.8.20;
import {IERC721Receiver} from "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol";
import {Initializable} from "../../../proxy/utils/Initializable.sol";
/**
* @dev Implementation of the {IERC721Receiver} interface.
*
* Accepts all token transfers.
* Make sure the contract is able to use its token with {IERC721-safeTransferFrom}, {IERC721-approve} or
* {IERC721-setApprovalForAll}.
*/
abstract contract ERC721HolderUpgradeable is Initializable, IERC721Receiver {
function __ERC721Holder_init() internal onlyInitializing {
}
function __ERC721Holder_init_unchained() internal onlyInitializing {
}
/**
* @dev See {IERC721Receiver-onERC721Received}.
*
* Always returns `IERC721Receiver.onERC721Received.selector`.
*/
function onERC721Received(address, address, uint256, bytes memory) public virtual returns (bytes4) {
return this.onERC721Received.selector;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)
pragma solidity ^0.8.20;
import {Initializable} from "../proxy/utils/Initializable.sol";
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract ContextUpgradeable is Initializable {
function __Context_init() internal onlyInitializing {
}
function __Context_init_unchained() internal onlyInitializing {
}
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
function _contextSuffixLength() internal view virtual returns (uint256) {
return 0;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (utils/cryptography/EIP712.sol)
pragma solidity ^0.8.20;
import {MessageHashUtils} from "@openzeppelin/contracts/utils/cryptography/MessageHashUtils.sol";
import {IERC5267} from "@openzeppelin/contracts/interfaces/IERC5267.sol";
import {Initializable} from "../../proxy/utils/Initializable.sol";
/**
* @dev https://eips.ethereum.org/EIPS/eip-712[EIP-712] is a standard for hashing and signing of typed structured data.
*
* The encoding scheme specified in the EIP requires a domain separator and a hash of the typed structured data, whose
* encoding is very generic and therefore its implementation in Solidity is not feasible, thus this contract
* does not implement the encoding itself. Protocols need to implement the type-specific encoding they need in order to
* produce the hash of their typed data using a combination of `abi.encode` and `keccak256`.
*
* This contract implements the EIP-712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding
* scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA
* ({_hashTypedDataV4}).
*
* The implementation of the domain separator was designed to be as efficient as possible while still properly updating
* the chain id to protect against replay attacks on an eventual fork of the chain.
*
* NOTE: This contract implements the version of the encoding known as "v4", as implemented by the JSON RPC method
* https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].
*
* NOTE: The upgradeable version of this contract does not use an immutable cache and recomputes the domain separator
* each time {_domainSeparatorV4} is called. That is cheaper than accessing a cached version in cold storage.
*/
abstract contract EIP712Upgradeable is Initializable, IERC5267 {
bytes32 private constant TYPE_HASH =
keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)");
/// @custom:storage-location erc7201:openzeppelin.storage.EIP712
struct EIP712Storage {
/// @custom:oz-renamed-from _HASHED_NAME
bytes32 _hashedName;
/// @custom:oz-renamed-from _HASHED_VERSION
bytes32 _hashedVersion;
string _name;
string _version;
}
// keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.EIP712")) - 1)) & ~bytes32(uint256(0xff))
bytes32 private constant EIP712StorageLocation = 0xa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d100;
function _getEIP712Storage() private pure returns (EIP712Storage storage $) {
assembly {
$.slot := EIP712StorageLocation
}
}
/**
* @dev Initializes the domain separator and parameter caches.
*
* The meaning of `name` and `version` is specified in
* https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP-712]:
*
* - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.
* - `version`: the current major version of the signing domain.
*
* NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart
* contract upgrade].
*/
function __EIP712_init(string memory name, string memory version) internal onlyInitializing {
__EIP712_init_unchained(name, version);
}
function __EIP712_init_unchained(string memory name, string memory version) internal onlyInitializing {
EIP712Storage storage $ = _getEIP712Storage();
$._name = name;
$._version = version;
// Reset prior values in storage if upgrading
$._hashedName = 0;
$._hashedVersion = 0;
}
/**
* @dev Returns the domain separator for the current chain.
*/
function _domainSeparatorV4() internal view returns (bytes32) {
return _buildDomainSeparator();
}
function _buildDomainSeparator() private view returns (bytes32) {
return keccak256(abi.encode(TYPE_HASH, _EIP712NameHash(), _EIP712VersionHash(), block.chainid, address(this)));
}
/**
* @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this
* function returns the hash of the fully encoded EIP712 message for this domain.
*
* This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:
*
* ```solidity
* bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(
* keccak256("Mail(address to,string contents)"),
* mailTo,
* keccak256(bytes(mailContents))
* )));
* address signer = ECDSA.recover(digest, signature);
* ```
*/
function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {
return MessageHashUtils.toTypedDataHash(_domainSeparatorV4(), structHash);
}
/// @inheritdoc IERC5267
function eip712Domain()
public
view
virtual
returns (
bytes1 fields,
string memory name,
string memory version,
uint256 chainId,
address verifyingContract,
bytes32 salt,
uint256[] memory extensions
)
{
EIP712Storage storage $ = _getEIP712Storage();
// If the hashed name and version in storage are non-zero, the contract hasn't been properly initialized
// and the EIP712 domain is not reliable, as it will be missing name and version.
require($._hashedName == 0 && $._hashedVersion == 0, "EIP712: Uninitialized");
return (
hex"0f", // 01111
_EIP712Name(),
_EIP712Version(),
block.chainid,
address(this),
bytes32(0),
new uint256[](0)
);
}
/**
* @dev The name parameter for the EIP712 domain.
*
* NOTE: This function reads from storage by default, but can be redefined to return a constant value if gas costs
* are a concern.
*/
function _EIP712Name() internal view virtual returns (string memory) {
EIP712Storage storage $ = _getEIP712Storage();
return $._name;
}
/**
* @dev The version parameter for the EIP712 domain.
*
* NOTE: This function reads from storage by default, but can be redefined to return a constant value if gas costs
* are a concern.
*/
function _EIP712Version() internal view virtual returns (string memory) {
EIP712Storage storage $ = _getEIP712Storage();
return $._version;
}
/**
* @dev The hash of the name parameter for the EIP712 domain.
*
* NOTE: In previous versions this function was virtual. In this version you should override `_EIP712Name` instead.
*/
function _EIP712NameHash() internal view returns (bytes32) {
EIP712Storage storage $ = _getEIP712Storage();
string memory name = _EIP712Name();
if (bytes(name).length > 0) {
return keccak256(bytes(name));
} else {
// If the name is empty, the contract may have been upgraded without initializing the new storage.
// We return the name hash in storage if non-zero, otherwise we assume the name is empty by design.
bytes32 hashedName = $._hashedName;
if (hashedName != 0) {
return hashedName;
} else {
return keccak256("");
}
}
}
/**
* @dev The hash of the version parameter for the EIP712 domain.
*
* NOTE: In previous versions this function was virtual. In this version you should override `_EIP712Version` instead.
*/
function _EIP712VersionHash() internal view returns (bytes32) {
EIP712Storage storage $ = _getEIP712Storage();
string memory version = _EIP712Version();
if (bytes(version).length > 0) {
return keccak256(bytes(version));
} else {
// If the version is empty, the contract may have been upgraded without initializing the new storage.
// We return the version hash in storage if non-zero, otherwise we assume the version is empty by design.
bytes32 hashedVersion = $._hashedVersion;
if (hashedVersion != 0) {
return hashedVersion;
} else {
return keccak256("");
}
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (utils/introspection/ERC165.sol)
pragma solidity ^0.8.20;
import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol";
import {Initializable} from "../../proxy/utils/Initializable.sol";
/**
* @dev Implementation of the {IERC165} interface.
*
* Contracts that want to implement ERC-165 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);
* }
* ```
*/
abstract contract ERC165Upgradeable is Initializable, IERC165 {
function __ERC165_init() internal onlyInitializing {
}
function __ERC165_init_unchained() internal onlyInitializing {
}
/// @inheritdoc IERC165
function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {
return interfaceId == type(IERC165).interfaceId;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/Nonces.sol)
pragma solidity ^0.8.20;
import {Initializable} from "../proxy/utils/Initializable.sol";
/**
* @dev Provides tracking nonces for addresses. Nonces will only increment.
*/
abstract contract NoncesUpgradeable is Initializable {
/**
* @dev The nonce used for an `account` is not the expected current nonce.
*/
error InvalidAccountNonce(address account, uint256 currentNonce);
/// @custom:storage-location erc7201:openzeppelin.storage.Nonces
struct NoncesStorage {
mapping(address account => uint256) _nonces;
}
// keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Nonces")) - 1)) & ~bytes32(uint256(0xff))
bytes32 private constant NoncesStorageLocation = 0x5ab42ced628888259c08ac98db1eb0cf702fc1501344311d8b100cd1bfe4bb00;
function _getNoncesStorage() private pure returns (NoncesStorage storage $) {
assembly {
$.slot := NoncesStorageLocation
}
}
function __Nonces_init() internal onlyInitializing {
}
function __Nonces_init_unchained() internal onlyInitializing {
}
/**
* @dev Returns the next unused nonce for an address.
*/
function nonces(address owner) public view virtual returns (uint256) {
NoncesStorage storage $ = _getNoncesStorage();
return $._nonces[owner];
}
/**
* @dev Consumes a nonce.
*
* Returns the current value and increments nonce.
*/
function _useNonce(address owner) internal virtual returns (uint256) {
NoncesStorage storage $ = _getNoncesStorage();
// For each account, the nonce has an initial value of 0, can only be incremented by one, and cannot be
// decremented or reset. This guarantees that the nonce never overflows.
unchecked {
// It is important to do x++ and not ++x here.
return $._nonces[owner]++;
}
}
/**
* @dev Same as {_useNonce} but checking that `nonce` is the next valid for `owner`.
*/
function _useCheckedNonce(address owner, uint256 nonce) internal virtual {
uint256 current = _useNonce(owner);
if (nonce != current) {
revert InvalidAccountNonce(owner, current);
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (access/AccessControl.sol)
pragma solidity ^0.8.20;
import {IAccessControl} from "./IAccessControl.sol";
import {Context} from "../utils/Context.sol";
import {IERC165, ERC165} from "../utils/introspection/ERC165.sol";
/**
* @dev Contract module that allows children to implement role-based access
* control mechanisms. This is a lightweight version that doesn't allow enumerating role
* members except through off-chain means by accessing the contract event logs. Some
* applications may benefit from on-chain enumerability, for those cases see
* {AccessControlEnumerable}.
*
* Roles are referred to by their `bytes32` identifier. These should be exposed
* in the external API and be unique. The best way to achieve this is by
* using `public constant` hash digests:
*
* ```solidity
* bytes32 public constant MY_ROLE = keccak256("MY_ROLE");
* ```
*
* Roles can be used to represent a set of permissions. To restrict access to a
* function call, use {hasRole}:
*
* ```solidity
* function foo() public {
* require(hasRole(MY_ROLE, msg.sender));
* ...
* }
* ```
*
* Roles can be granted and revoked dynamically via the {grantRole} and
* {revokeRole} functions. Each role has an associated admin role, and only
* accounts that have a role's admin role can call {grantRole} and {revokeRole}.
*
* By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means
* that only accounts with this role will be able to grant or revoke other
* roles. More complex role relationships can be created by using
* {_setRoleAdmin}.
*
* WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to
* grant and revoke this role. Extra precautions should be taken to secure
* accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}
* to enforce additional security measures for this role.
*/
abstract contract AccessControl is Context, IAccessControl, ERC165 {
struct RoleData {
mapping(address account => bool) hasRole;
bytes32 adminRole;
}
mapping(bytes32 role => RoleData) private _roles;
bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;
/**
* @dev Modifier that checks that an account has a specific role. Reverts
* with an {AccessControlUnauthorizedAccount} error including the required role.
*/
modifier onlyRole(bytes32 role) {
_checkRole(role);
_;
}
/// @inheritdoc IERC165
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);
}
/**
* @dev Returns `true` if `account` has been granted `role`.
*/
function hasRole(bytes32 role, address account) public view virtual returns (bool) {
return _roles[role].hasRole[account];
}
/**
* @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()`
* is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier.
*/
function _checkRole(bytes32 role) internal view virtual {
_checkRole(role, _msgSender());
}
/**
* @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account`
* is missing `role`.
*/
function _checkRole(bytes32 role, address account) internal view virtual {
if (!hasRole(role, account)) {
revert AccessControlUnauthorizedAccount(account, role);
}
}
/**
* @dev Returns the admin role that controls `role`. See {grantRole} and
* {revokeRole}.
*
* To change a role's admin, use {_setRoleAdmin}.
*/
function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) {
return _roles[role].adminRole;
}
/**
* @dev Grants `role` to `account`.
*
* If `account` had not been already granted `role`, emits a {RoleGranted}
* event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*
* May emit a {RoleGranted} event.
*/
function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {
_grantRole(role, account);
}
/**
* @dev Revokes `role` from `account`.
*
* If `account` had been granted `role`, emits a {RoleRevoked} event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*
* May emit a {RoleRevoked} event.
*/
function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {
_revokeRole(role, account);
}
/**
* @dev Revokes `role` from the calling account.
*
* Roles are often managed via {grantRole} and {revokeRole}: this function's
* purpose is to provide a mechanism for accounts to lose their privileges
* if they are compromised (such as when a trusted device is misplaced).
*
* If the calling account had been revoked `role`, emits a {RoleRevoked}
* event.
*
* Requirements:
*
* - the caller must be `callerConfirmation`.
*
* May emit a {RoleRevoked} event.
*/
function renounceRole(bytes32 role, address callerConfirmation) public virtual {
if (callerConfirmation != _msgSender()) {
revert AccessControlBadConfirmation();
}
_revokeRole(role, callerConfirmation);
}
/**
* @dev Sets `adminRole` as ``role``'s admin role.
*
* Emits a {RoleAdminChanged} event.
*/
function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {
bytes32 previousAdminRole = getRoleAdmin(role);
_roles[role].adminRole = adminRole;
emit RoleAdminChanged(role, previousAdminRole, adminRole);
}
/**
* @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted.
*
* Internal function without access restriction.
*
* May emit a {RoleGranted} event.
*/
function _grantRole(bytes32 role, address account) internal virtual returns (bool) {
if (!hasRole(role, account)) {
_roles[role].hasRole[account] = true;
emit RoleGranted(role, account, _msgSender());
return true;
} else {
return false;
}
}
/**
* @dev Attempts to revoke `role` from `account` and returns a boolean indicating if `role` was revoked.
*
* Internal function without access restriction.
*
* May emit a {RoleRevoked} event.
*/
function _revokeRole(bytes32 role, address account) internal virtual returns (bool) {
if (hasRole(role, account)) {
_roles[role].hasRole[account] = false;
emit RoleRevoked(role, account, _msgSender());
return true;
} else {
return false;
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (access/IAccessControl.sol)
pragma solidity >=0.8.4;
/**
* @dev External interface of AccessControl declared to support ERC-165 detection.
*/
interface IAccessControl {
/**
* @dev The `account` is missing a role.
*/
error AccessControlUnauthorizedAccount(address account, bytes32 neededRole);
/**
* @dev The caller of a function is not the expected one.
*
* NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.
*/
error AccessControlBadConfirmation();
/**
* @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`
*
* `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite
* {RoleAdminChanged} not being emitted to signal this.
*/
event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);
/**
* @dev Emitted when `account` is granted `role`.
*
* `sender` is the account that originated the contract call. This account bears the admin role (for the granted role).
* Expected in cases where the role was granted using the internal {AccessControl-_grantRole}.
*/
event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);
/**
* @dev Emitted when `account` is revoked `role`.
*
* `sender` is the account that originated the contract call:
* - if using `revokeRole`, it is the admin role bearer
* - if using `renounceRole`, it is the role bearer (i.e. `account`)
*/
event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);
/**
* @dev Returns `true` if `account` has been granted `role`.
*/
function hasRole(bytes32 role, address account) external view returns (bool);
/**
* @dev Returns the admin role that controls `role`. See {grantRole} and
* {revokeRole}.
*
* To change a role's admin, use {AccessControl-_setRoleAdmin}.
*/
function getRoleAdmin(bytes32 role) external view returns (bytes32);
/**
* @dev Grants `role` to `account`.
*
* If `account` had not been already granted `role`, emits a {RoleGranted}
* event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*/
function grantRole(bytes32 role, address account) external;
/**
* @dev Revokes `role` from `account`.
*
* If `account` had been granted `role`, emits a {RoleRevoked} event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*/
function revokeRole(bytes32 role, address account) external;
/**
* @dev Revokes `role` from the calling account.
*
* Roles are often managed via {grantRole} and {revokeRole}: this function's
* purpose is to provide a mechanism for accounts to lose their privileges
* if they are compromised (such as when a trusted device is misplaced).
*
* If the calling account had been granted `role`, emits a {RoleRevoked}
* event.
*
* Requirements:
*
* - the caller must be `callerConfirmation`.
*/
function renounceRole(bytes32 role, address callerConfirmation) external;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (governance/IGovernor.sol)
pragma solidity >=0.8.4;
import {IERC165} from "../interfaces/IERC165.sol";
import {IERC6372} from "../interfaces/IERC6372.sol";
/**
* @dev Interface of the {Governor} core.
*
* NOTE: Event parameters lack the `indexed` keyword for compatibility with GovernorBravo events.
* Making event parameters `indexed` affects how events are decoded, potentially breaking existing indexers.
*/
interface IGovernor is IERC165, IERC6372 {
enum ProposalState {
Pending,
Active,
Canceled,
Defeated,
Succeeded,
Queued,
Expired,
Executed
}
/**
* @dev Empty proposal or a mismatch between the parameters length for a proposal call.
*/
error GovernorInvalidProposalLength(uint256 targets, uint256 calldatas, uint256 values);
/**
* @dev The vote was already cast.
*/
error GovernorAlreadyCastVote(address voter);
/**
* @dev Token deposits are disabled in this contract.
*/
error GovernorDisabledDeposit();
/**
* @dev The `account` is not the governance executor.
*/
error GovernorOnlyExecutor(address account);
/**
* @dev The `proposalId` doesn't exist.
*/
error GovernorNonexistentProposal(uint256 proposalId);
/**
* @dev The current state of a proposal is not the required for performing an operation.
* The `expectedStates` is a bitmap with the bits enabled for each ProposalState enum position
* counting from right to left.
*
* NOTE: If `expectedState` is `bytes32(0)`, the proposal is expected to not be in any state (i.e. not exist).
* This is the case when a proposal that is expected to be unset is already initiated (the proposal is duplicated).
*
* See {Governor-_encodeStateBitmap}.
*/
error GovernorUnexpectedProposalState(uint256 proposalId, ProposalState current, bytes32 expectedStates);
/**
* @dev The voting period set is not a valid period.
*/
error GovernorInvalidVotingPeriod(uint256 votingPeriod);
/**
* @dev The `proposer` does not have the required votes to create a proposal.
*/
error GovernorInsufficientProposerVotes(address proposer, uint256 votes, uint256 threshold);
/**
* @dev The `proposer` is not allowed to create a proposal.
*/
error GovernorRestrictedProposer(address proposer);
/**
* @dev The vote type used is not valid for the corresponding counting module.
*/
error GovernorInvalidVoteType();
/**
* @dev The provided params buffer is not supported by the counting module.
*/
error GovernorInvalidVoteParams();
/**
* @dev Queue operation is not implemented for this governor. Execute should be called directly.
*/
error GovernorQueueNotImplemented();
/**
* @dev The proposal hasn't been queued yet.
*/
error GovernorNotQueuedProposal(uint256 proposalId);
/**
* @dev The proposal has already been queued.
*/
error GovernorAlreadyQueuedProposal(uint256 proposalId);
/**
* @dev The provided signature is not valid for the expected `voter`.
* If the `voter` is a contract, the signature is not valid using {IERC1271-isValidSignature}.
*/
error GovernorInvalidSignature(address voter);
/**
* @dev The given `account` is unable to cancel the proposal with given `proposalId`.
*/
error GovernorUnableToCancel(uint256 proposalId, address account);
/**
* @dev Emitted when a proposal is created.
*/
event ProposalCreated(
uint256 proposalId,
address proposer,
address[] targets,
uint256[] values,
string[] signatures,
bytes[] calldatas,
uint256 voteStart,
uint256 voteEnd,
string description
);
/**
* @dev Emitted when a proposal is queued.
*/
event ProposalQueued(uint256 proposalId, uint256 etaSeconds);
/**
* @dev Emitted when a proposal is executed.
*/
event ProposalExecuted(uint256 proposalId);
/**
* @dev Emitted when a proposal is canceled.
*/
event ProposalCanceled(uint256 proposalId);
/**
* @dev Emitted when a vote is cast without params.
*
* Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.
*/
event VoteCast(address indexed voter, uint256 proposalId, uint8 support, uint256 weight, string reason);
/**
* @dev Emitted when a vote is cast with params.
*
* Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.
* `params` are additional encoded parameters. Their interpretation also depends on the voting module used.
*/
event VoteCastWithParams(
address indexed voter,
uint256 proposalId,
uint8 support,
uint256 weight,
string reason,
bytes params
);
/**
* @notice module:core
* @dev Name of the governor instance (used in building the EIP-712 domain separator).
*/
function name() external view returns (string memory);
/**
* @notice module:core
* @dev Version of the governor instance (used in building the EIP-712 domain separator). Default: "1"
*/
function version() external view returns (string memory);
/**
* @notice module:voting
* @dev A description of the possible `support` values for {castVote} and the way these votes are counted, meant to
* be consumed by UIs to show correct vote options and interpret the results. The string is a URL-encoded sequence of
* key-value pairs that each describe one aspect, for example `support=bravo&quorum=for,abstain`.
*
* There are 2 standard keys: `support` and `quorum`.
*
* - `support=bravo` refers to the vote options 0 = Against, 1 = For, 2 = Abstain, as in `GovernorBravo`.
* - `quorum=bravo` means that only For votes are counted towards quorum.
* - `quorum=for,abstain` means that both For and Abstain votes are counted towards quorum.
*
* If a counting module makes use of encoded `params`, it should include this under a `params` key with a unique
* name that describes the behavior. For example:
*
* - `params=fractional` might refer to a scheme where votes are divided fractionally between for/against/abstain.
* - `params=erc721` might refer to a scheme where specific NFTs are delegated to vote.
*
* NOTE: The string can be decoded by the standard
* https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams[`URLSearchParams`]
* JavaScript class.
*/
// solhint-disable-next-line func-name-mixedcase
function COUNTING_MODE() external view returns (string memory);
/**
* @notice module:core
* @dev Hashing function used to (re)build the proposal id from the proposal details.
*
* NOTE: For all off-chain and external calls, use {getProposalId}.
*/
function hashProposal(
address[] memory targets,
uint256[] memory values,
bytes[] memory calldatas,
bytes32 descriptionHash
) external pure returns (uint256);
/**
* @notice module:core
* @dev Function used to get the proposal id from the proposal details.
*/
function getProposalId(
address[] memory targets,
uint256[] memory values,
bytes[] memory calldatas,
bytes32 descriptionHash
) external view returns (uint256);
/**
* @notice module:core
* @dev Current state of a proposal, following Compound's convention
*/
function state(uint256 proposalId) external view returns (ProposalState);
/**
* @notice module:core
* @dev The number of votes required in order for a voter to become a proposer.
*/
function proposalThreshold() external view returns (uint256);
/**
* @notice module:core
* @dev Timepoint used to retrieve user's votes and quorum. If using block number (as per Compound's Comp), the
* snapshot is performed at the end of this block. Hence, voting for this proposal starts at the beginning of the
* following block.
*/
function proposalSnapshot(uint256 proposalId) external view returns (uint256);
/**
* @notice module:core
* @dev Timepoint at which votes close. If using block number, votes close at the end of this block, so it is
* possible to cast a vote during this block.
*/
function proposalDeadline(uint256 proposalId) external view returns (uint256);
/**
* @notice module:core
* @dev The account that created a proposal.
*/
function proposalProposer(uint256 proposalId) external view returns (address);
/**
* @notice module:core
* @dev The time when a queued proposal becomes executable ("ETA"). Unlike {proposalSnapshot} and
* {proposalDeadline}, this doesn't use the governor clock, and instead relies on the executor's clock which may be
* different. In most cases this will be a timestamp.
*/
function proposalEta(uint256 proposalId) external view returns (uint256);
/**
* @notice module:core
* @dev Whether a proposal needs to be queued before execution.
*/
function proposalNeedsQueuing(uint256 proposalId) external view returns (bool);
/**
* @notice module:user-config
* @dev Delay, between the proposal is created and the vote starts. The unit this duration is expressed in depends
* on the clock (see ERC-6372) this contract uses.
*
* This can be increased to leave time for users to buy voting power, or delegate it, before the voting of a
* proposal starts.
*
* NOTE: While this interface returns a uint256, timepoints are stored as uint48 following the ERC-6372 clock type.
* Consequently this value must fit in a uint48 (when added to the current clock). See {IERC6372-clock}.
*/
function votingDelay() external view returns (uint256);
/**
* @notice module:user-config
* @dev Delay between the vote start and vote end. The unit this duration is expressed in depends on the clock
* (see ERC-6372) this contract uses.
*
* NOTE: The {votingDelay} can delay the start of the vote. This must be considered when setting the voting
* duration compared to the voting delay.
*
* NOTE: This value is stored when the proposal is submitted so that possible changes to the value do not affect
* proposals that have already been submitted. The type used to save it is a uint32. Consequently, while this
* interface returns a uint256, the value it returns should fit in a uint32.
*/
function votingPeriod() external view returns (uint256);
/**
* @notice module:user-config
* @dev Minimum number of cast voted required for a proposal to be successful.
*
* NOTE: The `timepoint` parameter corresponds to the snapshot used for counting vote. This allows to scale the
* quorum depending on values such as the totalSupply of a token at this timepoint (see {ERC20Votes}).
*/
function quorum(uint256 timepoint) external view returns (uint256);
/**
* @notice module:reputation
* @dev Voting power of an `account` at a specific `timepoint`.
*
* Note: this can be implemented in a number of ways, for example by reading the delegated balance from one (or
* multiple), {ERC20Votes} tokens.
*/
function getVotes(address account, uint256 timepoint) external view returns (uint256);
/**
* @notice module:reputation
* @dev Voting power of an `account` at a specific `timepoint` given additional encoded parameters.
*/
function getVotesWithParams(
address account,
uint256 timepoint,
bytes memory params
) external view returns (uint256);
/**
* @notice module:voting
* @dev Returns whether `account` has cast a vote on `proposalId`.
*/
function hasVoted(uint256 proposalId, address account) external view returns (bool);
/**
* @dev Create a new proposal. Vote start after a delay specified by {IGovernor-votingDelay} and lasts for a
* duration specified by {IGovernor-votingPeriod}.
*
* Emits a {ProposalCreated} event.
*
* NOTE: The state of the Governor and `targets` may change between the proposal creation and its execution.
* This may be the result of third party actions on the targeted contracts, or other governor proposals.
* For example, the balance of this contract could be updated or its access control permissions may be modified,
* possibly compromising the proposal's ability to execute successfully (e.g. the governor doesn't have enough
* value to cover a proposal with multiple transfers).
*/
function propose(
address[] memory targets,
uint256[] memory values,
bytes[] memory calldatas,
string memory description
) external returns (uint256 proposalId);
/**
* @dev Queue a proposal. Some governors require this step to be performed before execution can happen. If queuing
* is not necessary, this function may revert.
* Queuing a proposal requires the quorum to be reached, the vote to be successful, and the deadline to be reached.
*
* Emits a {ProposalQueued} event.
*/
function queue(
address[] memory targets,
uint256[] memory values,
bytes[] memory calldatas,
bytes32 descriptionHash
) external returns (uint256 proposalId);
/**
* @dev Execute a successful proposal. This requires the quorum to be reached, the vote to be successful, and the
* deadline to be reached. Depending on the governor it might also be required that the proposal was queued and
* that some delay passed.
*
* Emits a {ProposalExecuted} event.
*
* NOTE: Some modules can modify the requirements for execution, for example by adding an additional timelock.
*/
function execute(
address[] memory targets,
uint256[] memory values,
bytes[] memory calldatas,
bytes32 descriptionHash
) external payable returns (uint256 proposalId);
/**
* @dev Cancel a proposal. A proposal is cancellable by the proposer, but only while it is Pending state, i.e.
* before the vote starts.
*
* Emits a {ProposalCanceled} event.
*/
function cancel(
address[] memory targets,
uint256[] memory values,
bytes[] memory calldatas,
bytes32 descriptionHash
) external returns (uint256 proposalId);
/**
* @dev Cast a vote
*
* Emits a {VoteCast} event.
*/
function castVote(uint256 proposalId, uint8 support) external returns (uint256 balance);
/**
* @dev Cast a vote with a reason
*
* Emits a {VoteCast} event.
*/
function castVoteWithReason(
uint256 proposalId,
uint8 support,
string calldata reason
) external returns (uint256 balance);
/**
* @dev Cast a vote with a reason and additional encoded parameters
*
* Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.
*/
function castVoteWithReasonAndParams(
uint256 proposalId,
uint8 support,
string calldata reason,
bytes memory params
) external returns (uint256 balance);
/**
* @dev Cast a vote using the voter's signature, including ERC-1271 signature support.
*
* Emits a {VoteCast} event.
*/
function castVoteBySig(
uint256 proposalId,
uint8 support,
address voter,
bytes memory signature
) external returns (uint256 balance);
/**
* @dev Cast a vote with a reason and additional encoded parameters using the voter's signature,
* including ERC-1271 signature support.
*
* Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.
*/
function castVoteWithReasonAndParamsBySig(
uint256 proposalId,
uint8 support,
address voter,
string calldata reason,
bytes memory params,
bytes memory signature
) external returns (uint256 balance);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (governance/TimelockController.sol)
pragma solidity ^0.8.20;
import {AccessControl} from "../access/AccessControl.sol";
import {ERC721Holder} from "../token/ERC721/utils/ERC721Holder.sol";
import {ERC1155Holder} from "../token/ERC1155/utils/ERC1155Holder.sol";
import {Address} from "../utils/Address.sol";
import {IERC165} from "../utils/introspection/ERC165.sol";
/**
* @dev Contract module which acts as a timelocked controller. When set as the
* owner of an `Ownable` smart contract, it enforces a timelock on all
* `onlyOwner` maintenance operations. This gives time for users of the
* controlled contract to exit before a potentially dangerous maintenance
* operation is applied.
*
* By default, this contract is self administered, meaning administration tasks
* have to go through the timelock process. The proposer (resp executor) role
* is in charge of proposing (resp executing) operations. A common use case is
* to position this {TimelockController} as the owner of a smart contract, with
* a multisig or a DAO as the sole proposer.
*/
contract TimelockController is AccessControl, ERC721Holder, ERC1155Holder {
bytes32 public constant PROPOSER_ROLE = keccak256("PROPOSER_ROLE");
bytes32 public constant EXECUTOR_ROLE = keccak256("EXECUTOR_ROLE");
bytes32 public constant CANCELLER_ROLE = keccak256("CANCELLER_ROLE");
uint256 internal constant _DONE_TIMESTAMP = uint256(1);
mapping(bytes32 id => uint256) private _timestamps;
uint256 private _minDelay;
enum OperationState {
Unset,
Waiting,
Ready,
Done
}
/**
* @dev Mismatch between the parameters length for an operation call.
*/
error TimelockInvalidOperationLength(uint256 targets, uint256 payloads, uint256 values);
/**
* @dev The schedule operation doesn't meet the minimum delay.
*/
error TimelockInsufficientDelay(uint256 delay, uint256 minDelay);
/**
* @dev The current state of an operation is not as required.
* The `expectedStates` is a bitmap with the bits enabled for each OperationState enum position
* counting from right to left.
*
* See {_encodeStateBitmap}.
*/
error TimelockUnexpectedOperationState(bytes32 operationId, bytes32 expectedStates);
/**
* @dev The predecessor to an operation not yet done.
*/
error TimelockUnexecutedPredecessor(bytes32 predecessorId);
/**
* @dev The caller account is not authorized.
*/
error TimelockUnauthorizedCaller(address caller);
/**
* @dev Emitted when a call is scheduled as part of operation `id`.
*/
event CallScheduled(
bytes32 indexed id,
uint256 indexed index,
address target,
uint256 value,
bytes data,
bytes32 predecessor,
uint256 delay
);
/**
* @dev Emitted when a call is performed as part of operation `id`.
*/
event CallExecuted(bytes32 indexed id, uint256 indexed index, address target, uint256 value, bytes data);
/**
* @dev Emitted when new proposal is scheduled with non-zero salt.
*/
event CallSalt(bytes32 indexed id, bytes32 salt);
/**
* @dev Emitted when operation `id` is cancelled.
*/
event Cancelled(bytes32 indexed id);
/**
* @dev Emitted when the minimum delay for future operations is modified.
*/
event MinDelayChange(uint256 oldDuration, uint256 newDuration);
/**
* @dev Initializes the contract with the following parameters:
*
* - `minDelay`: initial minimum delay in seconds for operations
* - `proposers`: accounts to be granted proposer and canceller roles
* - `executors`: accounts to be granted executor role
* - `admin`: optional account to be granted admin role; disable with zero address
*
* IMPORTANT: The optional admin can aid with initial configuration of roles after deployment
* without being subject to delay, but this role should be subsequently renounced in favor of
* administration through timelocked proposals. Previous versions of this contract would assign
* this admin to the deployer automatically and should be renounced as well.
*/
constructor(uint256 minDelay, address[] memory proposers, address[] memory executors, address admin) {
// self administration
_grantRole(DEFAULT_ADMIN_ROLE, address(this));
// optional admin
if (admin != address(0)) {
_grantRole(DEFAULT_ADMIN_ROLE, admin);
}
// register proposers and cancellers
for (uint256 i = 0; i < proposers.length; ++i) {
_grantRole(PROPOSER_ROLE, proposers[i]);
_grantRole(CANCELLER_ROLE, proposers[i]);
}
// register executors
for (uint256 i = 0; i < executors.length; ++i) {
_grantRole(EXECUTOR_ROLE, executors[i]);
}
_minDelay = minDelay;
emit MinDelayChange(0, minDelay);
}
/**
* @dev Modifier to make a function callable only by a certain role. In
* addition to checking the sender's role, `address(0)` 's role is also
* considered. Granting a role to `address(0)` is equivalent to enabling
* this role for everyone.
*/
modifier onlyRoleOrOpenRole(bytes32 role) {
if (!hasRole(role, address(0))) {
_checkRole(role, _msgSender());
}
_;
}
/**
* @dev Contract might receive/hold ETH as part of the maintenance process.
*/
receive() external payable virtual {}
/// @inheritdoc IERC165
function supportsInterface(
bytes4 interfaceId
) public view virtual override(AccessControl, ERC1155Holder) returns (bool) {
return super.supportsInterface(interfaceId);
}
/**
* @dev Returns whether an id corresponds to a registered operation. This
* includes both Waiting, Ready, and Done operations.
*/
function isOperation(bytes32 id) public view returns (bool) {
return getOperationState(id) != OperationState.Unset;
}
/**
* @dev Returns whether an operation is pending or not. Note that a "pending" operation may also be "ready".
*/
function isOperationPending(bytes32 id) public view returns (bool) {
OperationState state = getOperationState(id);
return state == OperationState.Waiting || state == OperationState.Ready;
}
/**
* @dev Returns whether an operation is ready for execution. Note that a "ready" operation is also "pending".
*/
function isOperationReady(bytes32 id) public view returns (bool) {
return getOperationState(id) == OperationState.Ready;
}
/**
* @dev Returns whether an operation is done or not.
*/
function isOperationDone(bytes32 id) public view returns (bool) {
return getOperationState(id) == OperationState.Done;
}
/**
* @dev Returns the timestamp at which an operation becomes ready (0 for
* unset operations, 1 for done operations).
*/
function getTimestamp(bytes32 id) public view virtual returns (uint256) {
return _timestamps[id];
}
/**
* @dev Returns operation state.
*/
function getOperationState(bytes32 id) public view virtual returns (OperationState) {
uint256 timestamp = getTimestamp(id);
if (timestamp == 0) {
return OperationState.Unset;
} else if (timestamp == _DONE_TIMESTAMP) {
return OperationState.Done;
} else if (timestamp > block.timestamp) {
return OperationState.Waiting;
} else {
return OperationState.Ready;
}
}
/**
* @dev Returns the minimum delay in seconds for an operation to become valid.
*
* This value can be changed by executing an operation that calls `updateDelay`.
*/
function getMinDelay() public view virtual returns (uint256) {
return _minDelay;
}
/**
* @dev Returns the identifier of an operation containing a single
* transaction.
*/
function hashOperation(
address target,
uint256 value,
bytes calldata data,
bytes32 predecessor,
bytes32 salt
) public pure virtual returns (bytes32) {
return keccak256(abi.encode(target, value, data, predecessor, salt));
}
/**
* @dev Returns the identifier of an operation containing a batch of
* transactions.
*/
function hashOperationBatch(
address[] calldata targets,
uint256[] calldata values,
bytes[] calldata payloads,
bytes32 predecessor,
bytes32 salt
) public pure virtual returns (bytes32) {
return keccak256(abi.encode(targets, values, payloads, predecessor, salt));
}
/**
* @dev Schedule an operation containing a single transaction.
*
* Emits {CallSalt} if salt is nonzero, and {CallScheduled}.
*
* Requirements:
*
* - the caller must have the 'proposer' role.
*/
function schedule(
address target,
uint256 value,
bytes calldata data,
bytes32 predecessor,
bytes32 salt,
uint256 delay
) public virtual onlyRole(PROPOSER_ROLE) {
bytes32 id = hashOperation(target, value, data, predecessor, salt);
_schedule(id, delay);
emit CallScheduled(id, 0, target, value, data, predecessor, delay);
if (salt != bytes32(0)) {
emit CallSalt(id, salt);
}
}
/**
* @dev Schedule an operation containing a batch of transactions.
*
* Emits {CallSalt} if salt is nonzero, and one {CallScheduled} event per transaction in the batch.
*
* Requirements:
*
* - the caller must have the 'proposer' role.
*/
function scheduleBatch(
address[] calldata targets,
uint256[] calldata values,
bytes[] calldata payloads,
bytes32 predecessor,
bytes32 salt,
uint256 delay
) public virtual onlyRole(PROPOSER_ROLE) {
if (targets.length != values.length || targets.length != payloads.length) {
revert TimelockInvalidOperationLength(targets.length, payloads.length, values.length);
}
bytes32 id = hashOperationBatch(targets, values, payloads, predecessor, salt);
_schedule(id, delay);
for (uint256 i = 0; i < targets.length; ++i) {
emit CallScheduled(id, i, targets[i], values[i], payloads[i], predecessor, delay);
}
if (salt != bytes32(0)) {
emit CallSalt(id, salt);
}
}
/**
* @dev Schedule an operation that is to become valid after a given delay.
*/
function _schedule(bytes32 id, uint256 delay) private {
if (isOperation(id)) {
revert TimelockUnexpectedOperationState(id, _encodeStateBitmap(OperationState.Unset));
}
uint256 minDelay = getMinDelay();
if (delay < minDelay) {
revert TimelockInsufficientDelay(delay, minDelay);
}
_timestamps[id] = block.timestamp + delay;
}
/**
* @dev Cancel an operation.
*
* Requirements:
*
* - the caller must have the 'canceller' role.
*/
function cancel(bytes32 id) public virtual onlyRole(CANCELLER_ROLE) {
if (!isOperationPending(id)) {
revert TimelockUnexpectedOperationState(
id,
_encodeStateBitmap(OperationState.Waiting) | _encodeStateBitmap(OperationState.Ready)
);
}
delete _timestamps[id];
emit Cancelled(id);
}
/**
* @dev Execute an (ready) operation containing a single transaction.
*
* Emits a {CallExecuted} event.
*
* Requirements:
*
* - the caller must have the 'executor' role.
*/
// This function can reenter, but it doesn't pose a risk because _afterCall checks that the proposal is pending,
// thus any modifications to the operation during reentrancy should be caught.
// slither-disable-next-line reentrancy-eth
function execute(
address target,
uint256 value,
bytes calldata payload,
bytes32 predecessor,
bytes32 salt
) public payable virtual onlyRoleOrOpenRole(EXECUTOR_ROLE) {
bytes32 id = hashOperation(target, value, payload, predecessor, salt);
_beforeCall(id, predecessor);
_execute(target, value, payload);
emit CallExecuted(id, 0, target, value, payload);
_afterCall(id);
}
/**
* @dev Execute an (ready) operation containing a batch of transactions.
*
* Emits one {CallExecuted} event per transaction in the batch.
*
* Requirements:
*
* - the caller must have the 'executor' role.
*/
// This function can reenter, but it doesn't pose a risk because _afterCall checks that the proposal is pending,
// thus any modifications to the operation during reentrancy should be caught.
// slither-disable-next-line reentrancy-eth
function executeBatch(
address[] calldata targets,
uint256[] calldata values,
bytes[] calldata payloads,
bytes32 predecessor,
bytes32 salt
) public payable virtual onlyRoleOrOpenRole(EXECUTOR_ROLE) {
if (targets.length != values.length || targets.length != payloads.length) {
revert TimelockInvalidOperationLength(targets.length, payloads.length, values.length);
}
bytes32 id = hashOperationBatch(targets, values, payloads, predecessor, salt);
_beforeCall(id, predecessor);
for (uint256 i = 0; i < targets.length; ++i) {
address target = targets[i];
uint256 value = values[i];
bytes calldata payload = payloads[i];
_execute(target, value, payload);
emit CallExecuted(id, i, target, value, payload);
}
_afterCall(id);
}
/**
* @dev Execute an operation's call.
*/
function _execute(address target, uint256 value, bytes calldata data) internal virtual {
(bool success, bytes memory returndata) = target.call{value: value}(data);
Address.verifyCallResult(success, returndata);
}
/**
* @dev Checks before execution of an operation's calls.
*/
function _beforeCall(bytes32 id, bytes32 predecessor) private view {
if (!isOperationReady(id)) {
revert TimelockUnexpectedOperationState(id, _encodeStateBitmap(OperationState.Ready));
}
if (predecessor != bytes32(0) && !isOperationDone(predecessor)) {
revert TimelockUnexecutedPredecessor(predecessor);
}
}
/**
* @dev Checks after execution of an operation's calls.
*/
function _afterCall(bytes32 id) private {
if (!isOperationReady(id)) {
revert TimelockUnexpectedOperationState(id, _encodeStateBitmap(OperationState.Ready));
}
_timestamps[id] = _DONE_TIMESTAMP;
}
/**
* @dev Changes the minimum timelock duration for future operations.
*
* Emits a {MinDelayChange} event.
*
* Requirements:
*
* - the caller must be the timelock itself. This can only be achieved by scheduling and later executing
* an operation where the timelock is the target and the data is the ABI-encoded call to this function.
*/
function updateDelay(uint256 newDelay) external virtual {
address sender = _msgSender();
if (sender != address(this)) {
revert TimelockUnauthorizedCaller(sender);
}
emit MinDelayChange(_minDelay, newDelay);
_minDelay = newDelay;
}
/**
* @dev Encodes a `OperationState` into a `bytes32` representation where each bit enabled corresponds to
* the underlying position in the `OperationState` enum. For example:
*
* 0x000...1000
* ^^^^^^----- ...
* ^---- Done
* ^--- Ready
* ^-- Waiting
* ^- Unset
*/
function _encodeStateBitmap(OperationState operationState) internal pure returns (bytes32) {
return bytes32(1 << uint8(operationState));
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (governance/utils/IVotes.sol)
pragma solidity >=0.8.4;
/**
* @dev Common interface for {ERC20Votes}, {ERC721Votes}, and other {Votes}-enabled contracts.
*/
interface IVotes {
/**
* @dev The signature used has expired.
*/
error VotesExpiredSignature(uint256 expiry);
/**
* @dev Emitted when an account changes their delegate.
*/
event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);
/**
* @dev Emitted when a token transfer or delegate change results in changes to a delegate's number of voting units.
*/
event DelegateVotesChanged(address indexed delegate, uint256 previousVotes, uint256 newVotes);
/**
* @dev Returns the current amount of votes that `account` has.
*/
function getVotes(address account) external view returns (uint256);
/**
* @dev Returns the amount of votes that `account` had at a specific moment in the past. If the `clock()` is
* configured to use block numbers, this will return the value at the end of the corresponding block.
*/
function getPastVotes(address account, uint256 timepoint) external view returns (uint256);
/**
* @dev Returns the total supply of votes available at a specific moment in the past. If the `clock()` is
* configured to use block numbers, this will return the value at the end of the corresponding block.
*
* NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes.
* Votes that have not been delegated are still part of total supply, even though they would not participate in a
* vote.
*/
function getPastTotalSupply(uint256 timepoint) external view returns (uint256);
/**
* @dev Returns the delegate that `account` has chosen.
*/
function delegates(address account) external view returns (address);
/**
* @dev Delegates votes from the sender to `delegatee`.
*/
function delegate(address delegatee) external;
/**
* @dev Delegates votes from signer to `delegatee`.
*/
function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) external;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/draft-IERC6093.sol)
pragma solidity >=0.8.4;
/**
* @dev Standard ERC-20 Errors
* Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-20 tokens.
*/
interface IERC20Errors {
/**
* @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.
* @param sender Address whose tokens are being transferred.
* @param balance Current balance for the interacting account.
* @param needed Minimum amount required to perform a transfer.
*/
error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed);
/**
* @dev Indicates a failure with the token `sender`. Used in transfers.
* @param sender Address whose tokens are being transferred.
*/
error ERC20InvalidSender(address sender);
/**
* @dev Indicates a failure with the token `receiver`. Used in transfers.
* @param receiver Address to which tokens are being transferred.
*/
error ERC20InvalidReceiver(address receiver);
/**
* @dev Indicates a failure with the `spender`’s `allowance`. Used in transfers.
* @param spender Address that may be allowed to operate on tokens without being their owner.
* @param allowance Amount of tokens a `spender` is allowed to operate with.
* @param needed Minimum amount required to perform a transfer.
*/
error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed);
/**
* @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
* @param approver Address initiating an approval operation.
*/
error ERC20InvalidApprover(address approver);
/**
* @dev Indicates a failure with the `spender` to be approved. Used in approvals.
* @param spender Address that may be allowed to operate on tokens without being their owner.
*/
error ERC20InvalidSpender(address spender);
}
/**
* @dev Standard ERC-721 Errors
* Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-721 tokens.
*/
interface IERC721Errors {
/**
* @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in ERC-20.
* Used in balance queries.
* @param owner Address of the current owner of a token.
*/
error ERC721InvalidOwner(address owner);
/**
* @dev Indicates a `tokenId` whose `owner` is the zero address.
* @param tokenId Identifier number of a token.
*/
error ERC721NonexistentToken(uint256 tokenId);
/**
* @dev Indicates an error related to the ownership over a particular token. Used in transfers.
* @param sender Address whose tokens are being transferred.
* @param tokenId Identifier number of a token.
* @param owner Address of the current owner of a token.
*/
error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner);
/**
* @dev Indicates a failure with the token `sender`. Used in transfers.
* @param sender Address whose tokens are being transferred.
*/
error ERC721InvalidSender(address sender);
/**
* @dev Indicates a failure with the token `receiver`. Used in transfers.
* @param receiver Address to which tokens are being transferred.
*/
error ERC721InvalidReceiver(address receiver);
/**
* @dev Indicates a failure with the `operator`’s approval. Used in transfers.
* @param operator Address that may be allowed to operate on tokens without being their owner.
* @param tokenId Identifier number of a token.
*/
error ERC721InsufficientApproval(address operator, uint256 tokenId);
/**
* @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
* @param approver Address initiating an approval operation.
*/
error ERC721InvalidApprover(address approver);
/**
* @dev Indicates a failure with the `operator` to be approved. Used in approvals.
* @param operator Address that may be allowed to operate on tokens without being their owner.
*/
error ERC721InvalidOperator(address operator);
}
/**
* @dev Standard ERC-1155 Errors
* Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-1155 tokens.
*/
interface IERC1155Errors {
/**
* @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.
* @param sender Address whose tokens are being transferred.
* @param balance Current balance for the interacting account.
* @param needed Minimum amount required to perform a transfer.
* @param tokenId Identifier number of a token.
*/
error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId);
/**
* @dev Indicates a failure with the token `sender`. Used in transfers.
* @param sender Address whose tokens are being transferred.
*/
error ERC1155InvalidSender(address sender);
/**
* @dev Indicates a failure with the token `receiver`. Used in transfers.
* @param receiver Address to which tokens are being transferred.
*/
error ERC1155InvalidReceiver(address receiver);
/**
* @dev Indicates a failure with the `operator`’s approval. Used in transfers.
* @param operator Address that may be allowed to operate on tokens without being their owner.
* @param owner Address of the current owner of a token.
*/
error ERC1155MissingApprovalForAll(address operator, address owner);
/**
* @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
* @param approver Address initiating an approval operation.
*/
error ERC1155InvalidApprover(address approver);
/**
* @dev Indicates a failure with the `operator` to be approved. Used in approvals.
* @param operator Address that may be allowed to operate on tokens without being their owner.
*/
error ERC1155InvalidOperator(address operator);
/**
* @dev Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation.
* Used in batch transfers.
* @param idsLength Length of the array of token identifiers
* @param valuesLength Length of the array of token amounts
*/
error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC1271.sol)
pragma solidity >=0.5.0;
/**
* @dev Interface of the ERC-1271 standard signature validation method for
* contracts as defined in https://eips.ethereum.org/EIPS/eip-1271[ERC-1271].
*/
interface IERC1271 {
/**
* @dev Should return whether the signature provided is valid for the provided data
* @param hash Hash of the data to be signed
* @param signature Signature byte array associated with `hash`
*/
function isValidSignature(bytes32 hash, bytes calldata signature) external view returns (bytes4 magicValue);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC165.sol)
pragma solidity >=0.4.16;
import {IERC165} from "../utils/introspection/IERC165.sol";// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC5267.sol)
pragma solidity >=0.4.16;
interface IERC5267 {
/**
* @dev MAY be emitted to signal that the domain could have changed.
*/
event EIP712DomainChanged();
/**
* @dev returns the fields and values that describe the domain separator used by this contract for EIP-712
* signature.
*/
function eip712Domain()
external
view
returns (
bytes1 fields,
string memory name,
string memory version,
uint256 chainId,
address verifyingContract,
bytes32 salt,
uint256[] memory extensions
);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC5805.sol)
pragma solidity >=0.8.4;
import {IVotes} from "../governance/utils/IVotes.sol";
import {IERC6372} from "./IERC6372.sol";
interface IERC5805 is IERC6372, IVotes {}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC6372.sol)
pragma solidity >=0.4.16;
interface IERC6372 {
/**
* @dev Clock used for flagging checkpoints. Can be overridden to implement timestamp based checkpoints (and voting).
*/
function clock() external view returns (uint48);
/**
* @dev Description of the clock
*/
// solhint-disable-next-line func-name-mixedcase
function CLOCK_MODE() external view returns (string memory);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC7913.sol)
pragma solidity >=0.5.0;
/**
* @dev Signature verifier interface.
*/
interface IERC7913SignatureVerifier {
/**
* @dev Verifies `signature` as a valid signature of `hash` by `key`.
*
* MUST return the bytes4 magic value IERC7913SignatureVerifier.verify.selector if the signature is valid.
* SHOULD return 0xffffffff or revert if the signature is not valid.
* SHOULD return 0xffffffff or revert if the key is empty
*/
function verify(bytes calldata key, bytes32 hash, bytes calldata signature) external view returns (bytes4);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (proxy/Clones.sol)
pragma solidity ^0.8.20;
import {Create2} from "../utils/Create2.sol";
import {Errors} from "../utils/Errors.sol";
/**
* @dev https://eips.ethereum.org/EIPS/eip-1167[ERC-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.
*/
library Clones {
error CloneArgumentsTooLong();
/**
* @dev Deploys and returns the address of a clone that mimics the behavior of `implementation`.
*
* This function uses the create opcode, which should never revert.
*
* WARNING: This function does not check if `implementation` has code. A clone that points to an address
* without code cannot be initialized. Initialization calls may appear to be successful when, in reality, they
* have no effect and leave the clone uninitialized, allowing a third party to initialize it later.
*/
function clone(address implementation) internal returns (address instance) {
return clone(implementation, 0);
}
/**
* @dev Same as {xref-Clones-clone-address-}[clone], but with a `value` parameter to send native currency
* to the new contract.
*
* WARNING: This function does not check if `implementation` has code. A clone that points to an address
* without code cannot be initialized. Initialization calls may appear to be successful when, in reality, they
* have no effect and leave the clone uninitialized, allowing a third party to initialize it later.
*
* NOTE: Using a non-zero value at creation will require the contract using this function (e.g. a factory)
* to always have enough balance for new deployments. Consider exposing this function under a payable method.
*/
function clone(address implementation, uint256 value) internal returns (address instance) {
if (address(this).balance < value) {
revert Errors.InsufficientBalance(address(this).balance, value);
}
assembly ("memory-safe") {
// 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(value, 0x09, 0x37)
}
if (instance == address(0)) {
revert Errors.FailedDeployment();
}
}
/**
* @dev Deploys and returns the address of a clone that mimics the behavior of `implementation`.
*
* This function uses the create2 opcode and a `salt` to deterministically deploy
* the clone. Using the same `implementation` and `salt` multiple times will revert, since
* the clones cannot be deployed twice at the same address.
*
* WARNING: This function does not check if `implementation` has code. A clone that points to an address
* without code cannot be initialized. Initialization calls may appear to be successful when, in reality, they
* have no effect and leave the clone uninitialized, allowing a third party to initialize it later.
*/
function cloneDeterministic(address implementation, bytes32 salt) internal returns (address instance) {
return cloneDeterministic(implementation, salt, 0);
}
/**
* @dev Same as {xref-Clones-cloneDeterministic-address-bytes32-}[cloneDeterministic], but with
* a `value` parameter to send native currency to the new contract.
*
* WARNING: This function does not check if `implementation` has code. A clone that points to an address
* without code cannot be initialized. Initialization calls may appear to be successful when, in reality, they
* have no effect and leave the clone uninitialized, allowing a third party to initialize it later.
*
* NOTE: Using a non-zero value at creation will require the contract using this function (e.g. a factory)
* to always have enough balance for new deployments. Consider exposing this function under a payable method.
*/
function cloneDeterministic(
address implementation,
bytes32 salt,
uint256 value
) internal returns (address instance) {
if (address(this).balance < value) {
revert Errors.InsufficientBalance(address(this).balance, value);
}
assembly ("memory-safe") {
// 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(value, 0x09, 0x37, salt)
}
if (instance == address(0)) {
revert Errors.FailedDeployment();
}
}
/**
* @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}.
*/
function predictDeterministicAddress(
address implementation,
bytes32 salt,
address deployer
) internal pure returns (address predicted) {
assembly ("memory-safe") {
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 := and(keccak256(add(ptr, 0x43), 0x55), 0xffffffffffffffffffffffffffffffffffffffff)
}
}
/**
* @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));
}
/**
* @dev Deploys and returns the address of a clone that mimics the behavior of `implementation` with custom
* immutable arguments. These are provided through `args` and cannot be changed after deployment. To
* access the arguments within the implementation, use {fetchCloneArgs}.
*
* This function uses the create opcode, which should never revert.
*
* WARNING: This function does not check if `implementation` has code. A clone that points to an address
* without code cannot be initialized. Initialization calls may appear to be successful when, in reality, they
* have no effect and leave the clone uninitialized, allowing a third party to initialize it later.
*/
function cloneWithImmutableArgs(address implementation, bytes memory args) internal returns (address instance) {
return cloneWithImmutableArgs(implementation, args, 0);
}
/**
* @dev Same as {xref-Clones-cloneWithImmutableArgs-address-bytes-}[cloneWithImmutableArgs], but with a `value`
* parameter to send native currency to the new contract.
*
* WARNING: This function does not check if `implementation` has code. A clone that points to an address
* without code cannot be initialized. Initialization calls may appear to be successful when, in reality, they
* have no effect and leave the clone uninitialized, allowing a third party to initialize it later.
*
* NOTE: Using a non-zero value at creation will require the contract using this function (e.g. a factory)
* to always have enough balance for new deployments. Consider exposing this function under a payable method.
*/
function cloneWithImmutableArgs(
address implementation,
bytes memory args,
uint256 value
) internal returns (address instance) {
if (address(this).balance < value) {
revert Errors.InsufficientBalance(address(this).balance, value);
}
bytes memory bytecode = _cloneCodeWithImmutableArgs(implementation, args);
assembly ("memory-safe") {
instance := create(value, add(bytecode, 0x20), mload(bytecode))
}
if (instance == address(0)) {
revert Errors.FailedDeployment();
}
}
/**
* @dev Deploys and returns the address of a clone that mimics the behavior of `implementation` with custom
* immutable arguments. These are provided through `args` and cannot be changed after deployment. To
* access the arguments within the implementation, use {fetchCloneArgs}.
*
* This function uses the create2 opcode and a `salt` to deterministically deploy the clone. Using the same
* `implementation`, `args` and `salt` multiple times will revert, since the clones cannot be deployed twice
* at the same address.
*
* WARNING: This function does not check if `implementation` has code. A clone that points to an address
* without code cannot be initialized. Initialization calls may appear to be successful when, in reality, they
* have no effect and leave the clone uninitialized, allowing a third party to initialize it later.
*/
function cloneDeterministicWithImmutableArgs(
address implementation,
bytes memory args,
bytes32 salt
) internal returns (address instance) {
return cloneDeterministicWithImmutableArgs(implementation, args, salt, 0);
}
/**
* @dev Same as {xref-Clones-cloneDeterministicWithImmutableArgs-address-bytes-bytes32-}[cloneDeterministicWithImmutableArgs],
* but with a `value` parameter to send native currency to the new contract.
*
* WARNING: This function does not check if `implementation` has code. A clone that points to an address
* without code cannot be initialized. Initialization calls may appear to be successful when, in reality, they
* have no effect and leave the clone uninitialized, allowing a third party to initialize it later.
*
* NOTE: Using a non-zero value at creation will require the contract using this function (e.g. a factory)
* to always have enough balance for new deployments. Consider exposing this function under a payable method.
*/
function cloneDeterministicWithImmutableArgs(
address implementation,
bytes memory args,
bytes32 salt,
uint256 value
) internal returns (address instance) {
bytes memory bytecode = _cloneCodeWithImmutableArgs(implementation, args);
return Create2.deploy(value, salt, bytecode);
}
/**
* @dev Computes the address of a clone deployed using {Clones-cloneDeterministicWithImmutableArgs}.
*/
function predictDeterministicAddressWithImmutableArgs(
address implementation,
bytes memory args,
bytes32 salt,
address deployer
) internal pure returns (address predicted) {
bytes memory bytecode = _cloneCodeWithImmutableArgs(implementation, args);
return Create2.computeAddress(salt, keccak256(bytecode), deployer);
}
/**
* @dev Computes the address of a clone deployed using {Clones-cloneDeterministicWithImmutableArgs}.
*/
function predictDeterministicAddressWithImmutableArgs(
address implementation,
bytes memory args,
bytes32 salt
) internal view returns (address predicted) {
return predictDeterministicAddressWithImmutableArgs(implementation, args, salt, address(this));
}
/**
* @dev Get the immutable args attached to a clone.
*
* - If `instance` is a clone that was deployed using `clone` or `cloneDeterministic`, this
* function will return an empty array.
* - If `instance` is a clone that was deployed using `cloneWithImmutableArgs` or
* `cloneDeterministicWithImmutableArgs`, this function will return the args array used at
* creation.
* - If `instance` is NOT a clone deployed using this library, the behavior is undefined. This
* function should only be used to check addresses that are known to be clones.
*/
function fetchCloneArgs(address instance) internal view returns (bytes memory) {
bytes memory result = new bytes(instance.code.length - 45); // revert if length is too short
assembly ("memory-safe") {
extcodecopy(instance, add(result, 32), 45, mload(result))
}
return result;
}
/**
* @dev Helper that prepares the initcode of the proxy with immutable args.
*
* An assembly variant of this function requires copying the `args` array, which can be efficiently done using
* `mcopy`. Unfortunately, that opcode is not available before cancun. A pure solidity implementation using
* abi.encodePacked is more expensive but also more portable and easier to review.
*
* NOTE: https://eips.ethereum.org/EIPS/eip-170[EIP-170] limits the length of the contract code to 24576 bytes.
* With the proxy code taking 45 bytes, that limits the length of the immutable args to 24531 bytes.
*/
function _cloneCodeWithImmutableArgs(
address implementation,
bytes memory args
) private pure returns (bytes memory) {
if (args.length > 24531) revert CloneArgumentsTooLong();
return
abi.encodePacked(
hex"61",
uint16(args.length + 45),
hex"3d81600a3d39f3363d3d373d3d3d363d73",
implementation,
hex"5af43d82803e903d91602b57fd5bf3",
args
);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC1155/IERC1155Receiver.sol)
pragma solidity >=0.6.2;
import {IERC165} from "../../utils/introspection/IERC165.sol";
/**
* @dev Interface that must be implemented by smart contracts in order to receive
* ERC-1155 token transfers.
*/
interface IERC1155Receiver is IERC165 {
/**
* @dev Handles the receipt of a single ERC-1155 token type. This function is
* called at the end of a `safeTransferFrom` after the balance has been updated.
*
* NOTE: To accept the transfer, this must return
* `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))`
* (i.e. 0xf23a6e61, or its own function selector).
*
* @param operator The address which initiated the transfer (i.e. msg.sender)
* @param from The address which previously owned the token
* @param id The ID of the token being transferred
* @param value The amount of tokens being transferred
* @param data Additional data with no specified format
* @return `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` if transfer is allowed
*/
function onERC1155Received(
address operator,
address from,
uint256 id,
uint256 value,
bytes calldata data
) external returns (bytes4);
/**
* @dev Handles the receipt of a multiple ERC-1155 token types. This function
* is called at the end of a `safeBatchTransferFrom` after the balances have
* been updated.
*
* NOTE: To accept the transfer(s), this must return
* `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))`
* (i.e. 0xbc197c81, or its own function selector).
*
* @param operator The address which initiated the batch transfer (i.e. msg.sender)
* @param from The address which previously owned the token
* @param ids An array containing ids of each token being transferred (order and length must match values array)
* @param values An array containing amounts of each token being transferred (order and length must match ids array)
* @param data Additional data with no specified format
* @return `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` if transfer is allowed
*/
function onERC1155BatchReceived(
address operator,
address from,
uint256[] calldata ids,
uint256[] calldata values,
bytes calldata data
) external returns (bytes4);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC1155/utils/ERC1155Holder.sol)
pragma solidity ^0.8.20;
import {IERC165, ERC165} from "../../../utils/introspection/ERC165.sol";
import {IERC1155Receiver} from "../IERC1155Receiver.sol";
/**
* @dev Simple implementation of `IERC1155Receiver` that will allow a contract to hold ERC-1155 tokens.
*
* IMPORTANT: When inheriting this contract, you must include a way to use the received tokens, otherwise they will be
* stuck.
*/
abstract contract ERC1155Holder is ERC165, IERC1155Receiver {
/// @inheritdoc IERC165
function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {
return interfaceId == type(IERC1155Receiver).interfaceId || super.supportsInterface(interfaceId);
}
function onERC1155Received(
address,
address,
uint256,
uint256,
bytes memory
) public virtual override returns (bytes4) {
return this.onERC1155Received.selector;
}
function onERC1155BatchReceived(
address,
address,
uint256[] memory,
uint256[] memory,
bytes memory
) public virtual override returns (bytes4) {
return this.onERC1155BatchReceived.selector;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC20/extensions/IERC20Metadata.sol)
pragma solidity >=0.6.2;
import {IERC20} from "../IERC20.sol";
/**
* @dev Interface for the optional metadata functions from the ERC-20 standard.
*/
interface IERC20Metadata is IERC20 {
/**
* @dev Returns the name of the token.
*/
function name() external view returns (string memory);
/**
* @dev Returns the symbol of the token.
*/
function symbol() external view returns (string memory);
/**
* @dev Returns the decimals places of the token.
*/
function decimals() external view returns (uint8);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC20/extensions/IERC20Permit.sol)
pragma solidity >=0.4.16;
/**
* @dev Interface of the ERC-20 Permit extension allowing approvals to be made via signatures, as defined in
* https://eips.ethereum.org/EIPS/eip-2612[ERC-2612].
*
* Adds the {permit} method, which can be used to change an account's ERC-20 allowance (see {IERC20-allowance}) by
* presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't
* need to send a transaction, and thus is not required to hold Ether at all.
*
* ==== Security Considerations
*
* There are two important considerations concerning the use of `permit`. The first is that a valid permit signature
* expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be
* considered as an intention to spend the allowance in any specific way. The second is that because permits have
* built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should
* take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be
* generally recommended is:
*
* ```solidity
* function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {
* try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}
* doThing(..., value);
* }
*
* function doThing(..., uint256 value) public {
* token.safeTransferFrom(msg.sender, address(this), value);
* ...
* }
* ```
*
* Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of
* `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also
* {SafeERC20-safeTransferFrom}).
*
* Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so
* contracts should have entry points that don't rely on permit.
*/
interface IERC20Permit {
/**
* @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
* given ``owner``'s signed approval.
*
* IMPORTANT: The same issues {IERC20-approve} has related to transaction
* ordering also apply here.
*
* Emits an {Approval} event.
*
* Requirements:
*
* - `spender` cannot be the zero address.
* - `deadline` must be a timestamp in the future.
* - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
* over the EIP712-formatted function arguments.
* - the signature must use ``owner``'s current nonce (see {nonces}).
*
* For more information on the signature format, see the
* https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
* section].
*
* CAUTION: See Security Considerations above.
*/
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
/**
* @dev Returns the current nonce for `owner`. This value must be
* included whenever a signature is generated for {permit}.
*
* Every successful call to {permit} increases ``owner``'s nonce by one. This
* prevents a signature from being used multiple times.
*/
function nonces(address owner) external view returns (uint256);
/**
* @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.
*/
// solhint-disable-next-line func-name-mixedcase
function DOMAIN_SEPARATOR() external view returns (bytes32);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC20/IERC20.sol)
pragma solidity >=0.4.16;
/**
* @dev Interface of the ERC-20 standard as defined in the ERC.
*/
interface IERC20 {
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
/**
* @dev Returns the value of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the value of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves a `value` amount of tokens from the caller's account to `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, uint256 value) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets a `value` amount of tokens as the allowance of `spender` over the
* caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 value) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from `from` to `to` using the
* allowance mechanism. `value` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(address from, address to, uint256 value) external returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC721/IERC721Receiver.sol)
pragma solidity >=0.5.0;
/**
* @title ERC-721 token receiver interface
* @dev Interface for any contract that wants to support safeTransfers
* from ERC-721 asset contracts.
*/
interface IERC721Receiver {
/**
* @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}
* by `operator` from `from`, this function is called.
*
* It must return its Solidity selector to confirm the token transfer.
* If any other value is returned or the interface is not implemented by the recipient, the transfer will be
* reverted.
*
* The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.
*/
function onERC721Received(
address operator,
address from,
uint256 tokenId,
bytes calldata data
) external returns (bytes4);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/utils/ERC721Holder.sol)
pragma solidity ^0.8.20;
import {IERC721Receiver} from "../IERC721Receiver.sol";
/**
* @dev Implementation of the {IERC721Receiver} interface.
*
* Accepts all token transfers.
* Make sure the contract is able to use its token with {IERC721-safeTransferFrom}, {IERC721-approve} or
* {IERC721-setApprovalForAll}.
*/
abstract contract ERC721Holder is IERC721Receiver {
/**
* @dev See {IERC721Receiver-onERC721Received}.
*
* Always returns `IERC721Receiver.onERC721Received.selector`.
*/
function onERC721Received(address, address, uint256, bytes memory) public virtual returns (bytes4) {
return this.onERC721Received.selector;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (utils/Address.sol)
pragma solidity ^0.8.20;
import {Errors} from "./Errors.sol";
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev There's no code at `target` (it is not a contract).
*/
error AddressEmptyCode(address target);
/**
* @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.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
if (address(this).balance < amount) {
revert Errors.InsufficientBalance(address(this).balance, amount);
}
(bool success, bytes memory returndata) = recipient.call{value: amount}("");
if (!success) {
_revert(returndata);
}
}
/**
* @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 or custom error, it is bubbled
* up by this function (like regular Solidity function calls). However, if
* the call reverted with no returned reason, this function reverts with a
* {Errors.FailedCall} error.
*
* 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.
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0);
}
/**
* @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`.
*/
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
if (address(this).balance < value) {
revert Errors.InsufficientBalance(address(this).balance, value);
}
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata);
}
/**
* @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target
* was not a contract or bubbling up the revert reason (falling back to {Errors.FailedCall}) in case
* of an unsuccessful call.
*/
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata
) internal view returns (bytes memory) {
if (!success) {
_revert(returndata);
} else {
// only check if target is a contract if the call was successful and the return data is empty
// otherwise we already know that it was a contract
if (returndata.length == 0 && target.code.length == 0) {
revert AddressEmptyCode(target);
}
return returndata;
}
}
/**
* @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the
* revert reason or with a default {Errors.FailedCall} error.
*/
function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {
if (!success) {
_revert(returndata);
} else {
return returndata;
}
}
/**
* @dev Reverts with returndata if present. Otherwise reverts with {Errors.FailedCall}.
*/
function _revert(bytes memory returndata) 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
assembly ("memory-safe") {
revert(add(returndata, 0x20), mload(returndata))
}
} else {
revert Errors.FailedCall();
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (utils/Bytes.sol)
pragma solidity ^0.8.24;
import {Math} from "./math/Math.sol";
/**
* @dev Bytes operations.
*/
library Bytes {
/**
* @dev Forward search for `s` in `buffer`
* * If `s` is present in the buffer, returns the index of the first instance
* * If `s` is not present in the buffer, returns type(uint256).max
*
* NOTE: replicates the behavior of https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/indexOf[Javascript's `Array.indexOf`]
*/
function indexOf(bytes memory buffer, bytes1 s) internal pure returns (uint256) {
return indexOf(buffer, s, 0);
}
/**
* @dev Forward search for `s` in `buffer` starting at position `pos`
* * If `s` is present in the buffer (at or after `pos`), returns the index of the next instance
* * If `s` is not present in the buffer (at or after `pos`), returns type(uint256).max
*
* NOTE: replicates the behavior of https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/indexOf[Javascript's `Array.indexOf`]
*/
function indexOf(bytes memory buffer, bytes1 s, uint256 pos) internal pure returns (uint256) {
uint256 length = buffer.length;
for (uint256 i = pos; i < length; ++i) {
if (bytes1(_unsafeReadBytesOffset(buffer, i)) == s) {
return i;
}
}
return type(uint256).max;
}
/**
* @dev Backward search for `s` in `buffer`
* * If `s` is present in the buffer, returns the index of the last instance
* * If `s` is not present in the buffer, returns type(uint256).max
*
* NOTE: replicates the behavior of https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/lastIndexOf[Javascript's `Array.lastIndexOf`]
*/
function lastIndexOf(bytes memory buffer, bytes1 s) internal pure returns (uint256) {
return lastIndexOf(buffer, s, type(uint256).max);
}
/**
* @dev Backward search for `s` in `buffer` starting at position `pos`
* * If `s` is present in the buffer (at or before `pos`), returns the index of the previous instance
* * If `s` is not present in the buffer (at or before `pos`), returns type(uint256).max
*
* NOTE: replicates the behavior of https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/lastIndexOf[Javascript's `Array.lastIndexOf`]
*/
function lastIndexOf(bytes memory buffer, bytes1 s, uint256 pos) internal pure returns (uint256) {
unchecked {
uint256 length = buffer.length;
for (uint256 i = Math.min(Math.saturatingAdd(pos, 1), length); i > 0; --i) {
if (bytes1(_unsafeReadBytesOffset(buffer, i - 1)) == s) {
return i - 1;
}
}
return type(uint256).max;
}
}
/**
* @dev Copies the content of `buffer`, from `start` (included) to the end of `buffer` into a new bytes object in
* memory.
*
* NOTE: replicates the behavior of https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/slice[Javascript's `Array.slice`]
*/
function slice(bytes memory buffer, uint256 start) internal pure returns (bytes memory) {
return slice(buffer, start, buffer.length);
}
/**
* @dev Copies the content of `buffer`, from `start` (included) to `end` (excluded) into a new bytes object in
* memory.
*
* NOTE: replicates the behavior of https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/slice[Javascript's `Array.slice`]
*/
function slice(bytes memory buffer, uint256 start, uint256 end) internal pure returns (bytes memory) {
// sanitize
uint256 length = buffer.length;
end = Math.min(end, length);
start = Math.min(start, end);
// allocate and copy
bytes memory result = new bytes(end - start);
assembly ("memory-safe") {
mcopy(add(result, 0x20), add(add(buffer, 0x20), start), sub(end, start))
}
return result;
}
/**
* @dev Reads a bytes32 from a bytes array without bounds checking.
*
* NOTE: making this function internal would mean it could be used with memory unsafe offset, and marking the
* assembly block as such would prevent some optimizations.
*/
function _unsafeReadBytesOffset(bytes memory buffer, uint256 offset) private pure returns (bytes32 value) {
// This is not memory safe in the general case, but all calls to this private function are within bounds.
assembly ("memory-safe") {
value := mload(add(add(buffer, 0x20), offset))
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)
pragma solidity ^0.8.20;
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
function _contextSuffixLength() internal view virtual returns (uint256) {
return 0;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/Create2.sol)
pragma solidity ^0.8.20;
import {Errors} from "./Errors.sol";
/**
* @dev Helper to make usage of the `CREATE2` EVM opcode easier and safer.
* `CREATE2` can be used to compute in advance the address where a smart
* contract will be deployed, which allows for interesting new mechanisms known
* as 'counterfactual interactions'.
*
* See the https://eips.ethereum.org/EIPS/eip-1014#motivation[EIP] for more
* information.
*/
library Create2 {
/**
* @dev There's no code to deploy.
*/
error Create2EmptyBytecode();
/**
* @dev Deploys a contract using `CREATE2`. The address where the contract
* will be deployed can be known in advance via {computeAddress}.
*
* The bytecode for a contract can be obtained from Solidity with
* `type(contractName).creationCode`.
*
* Requirements:
*
* - `bytecode` must not be empty.
* - `salt` must have not been used for `bytecode` already.
* - the factory must have a balance of at least `amount`.
* - if `amount` is non-zero, `bytecode` must have a `payable` constructor.
*/
function deploy(uint256 amount, bytes32 salt, bytes memory bytecode) internal returns (address addr) {
if (address(this).balance < amount) {
revert Errors.InsufficientBalance(address(this).balance, amount);
}
if (bytecode.length == 0) {
revert Create2EmptyBytecode();
}
assembly ("memory-safe") {
addr := create2(amount, add(bytecode, 0x20), mload(bytecode), salt)
// if no address was created, and returndata is not empty, bubble revert
if and(iszero(addr), not(iszero(returndatasize()))) {
let p := mload(0x40)
returndatacopy(p, 0, returndatasize())
revert(p, returndatasize())
}
}
if (addr == address(0)) {
revert Errors.FailedDeployment();
}
}
/**
* @dev Returns the address where a contract will be stored if deployed via {deploy}. Any change in the
* `bytecodeHash` or `salt` will result in a new destination address.
*/
function computeAddress(bytes32 salt, bytes32 bytecodeHash) internal view returns (address) {
return computeAddress(salt, bytecodeHash, address(this));
}
/**
* @dev Returns the address where a contract will be stored if deployed via {deploy} from a contract located at
* `deployer`. If `deployer` is this contract's address, returns the same value as {computeAddress}.
*/
function computeAddress(bytes32 salt, bytes32 bytecodeHash, address deployer) internal pure returns (address addr) {
assembly ("memory-safe") {
let ptr := mload(0x40) // Get free memory pointer
// | | ↓ ptr ... ↓ ptr + 0x0B (start) ... ↓ ptr + 0x20 ... ↓ ptr + 0x40 ... |
// |-------------------|---------------------------------------------------------------------------|
// | bytecodeHash | CCCCCCCCCCCCC...CC |
// | salt | BBBBBBBBBBBBB...BB |
// | deployer | 000000...0000AAAAAAAAAAAAAAAAAAA...AA |
// | 0xFF | FF |
// |-------------------|---------------------------------------------------------------------------|
// | memory | 000000...00FFAAAAAAAAAAAAAAAAAAA...AABBBBBBBBBBBBB...BBCCCCCCCCCCCCC...CC |
// | keccak(start, 85) | ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ |
mstore(add(ptr, 0x40), bytecodeHash)
mstore(add(ptr, 0x20), salt)
mstore(ptr, deployer) // Right-aligned with 12 preceding garbage bytes
let start := add(ptr, 0x0b) // The hashed data starts at the final garbage byte which we will set to 0xff
mstore8(start, 0xff)
addr := and(keccak256(start, 85), 0xffffffffffffffffffffffffffffffffffffffff)
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/cryptography/ECDSA.sol)
pragma solidity ^0.8.20;
/**
* @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.
*
* These functions can be used to verify that a message was signed by the holder
* of the private keys of a given address.
*/
library ECDSA {
enum RecoverError {
NoError,
InvalidSignature,
InvalidSignatureLength,
InvalidSignatureS
}
/**
* @dev The signature derives the `address(0)`.
*/
error ECDSAInvalidSignature();
/**
* @dev The signature has an invalid length.
*/
error ECDSAInvalidSignatureLength(uint256 length);
/**
* @dev The signature has an S value that is in the upper half order.
*/
error ECDSAInvalidSignatureS(bytes32 s);
/**
* @dev Returns the address that signed a hashed message (`hash`) with `signature` or an error. This will not
* return address(0) without also returning an error description. Errors are documented using an enum (error type)
* and a bytes32 providing additional information about the error.
*
* If no error is returned, then the address can be used for verification purposes.
*
* The `ecrecover` EVM precompile allows for malleable (non-unique) signatures:
* this function rejects them by requiring the `s` value to be in the lower
* half order, and the `v` value to be either 27 or 28.
*
* IMPORTANT: `hash` _must_ be the result of a hash operation for the
* verification to be secure: it is possible to craft signatures that
* recover to arbitrary addresses for non-hashed data. A safe way to ensure
* this is by receiving a hash of the original message (which may otherwise
* be too long), and then calling {MessageHashUtils-toEthSignedMessageHash} on it.
*
* Documentation for signature generation:
* - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]
* - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]
*/
function tryRecover(
bytes32 hash,
bytes memory signature
) internal pure returns (address recovered, RecoverError err, bytes32 errArg) {
if (signature.length == 65) {
bytes32 r;
bytes32 s;
uint8 v;
// ecrecover takes the signature parameters, and the only way to get them
// currently is to use assembly.
assembly ("memory-safe") {
r := mload(add(signature, 0x20))
s := mload(add(signature, 0x40))
v := byte(0, mload(add(signature, 0x60)))
}
return tryRecover(hash, v, r, s);
} else {
return (address(0), RecoverError.InvalidSignatureLength, bytes32(signature.length));
}
}
/**
* @dev Returns the address that signed a hashed message (`hash`) with
* `signature`. This address can then be used for verification purposes.
*
* The `ecrecover` EVM precompile allows for malleable (non-unique) signatures:
* this function rejects them by requiring the `s` value to be in the lower
* half order, and the `v` value to be either 27 or 28.
*
* IMPORTANT: `hash` _must_ be the result of a hash operation for the
* verification to be secure: it is possible to craft signatures that
* recover to arbitrary addresses for non-hashed data. A safe way to ensure
* this is by receiving a hash of the original message (which may otherwise
* be too long), and then calling {MessageHashUtils-toEthSignedMessageHash} on it.
*/
function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {
(address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, signature);
_throwError(error, errorArg);
return recovered;
}
/**
* @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.
*
* See https://eips.ethereum.org/EIPS/eip-2098[ERC-2098 short signatures]
*/
function tryRecover(
bytes32 hash,
bytes32 r,
bytes32 vs
) internal pure returns (address recovered, RecoverError err, bytes32 errArg) {
unchecked {
bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);
// We do not check for an overflow here since the shift operation results in 0 or 1.
uint8 v = uint8((uint256(vs) >> 255) + 27);
return tryRecover(hash, v, r, s);
}
}
/**
* @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.
*/
function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {
(address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, r, vs);
_throwError(error, errorArg);
return recovered;
}
/**
* @dev Overload of {ECDSA-tryRecover} that receives the `v`,
* `r` and `s` signature fields separately.
*/
function tryRecover(
bytes32 hash,
uint8 v,
bytes32 r,
bytes32 s
) internal pure returns (address recovered, RecoverError err, bytes32 errArg) {
// EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature
// unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines
// the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most
// signatures from current libraries generate a unique signature with an s-value in the lower half order.
//
// If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value
// with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or
// vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept
// these malleable signatures as well.
if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {
return (address(0), RecoverError.InvalidSignatureS, s);
}
// If the signature is valid (and not malleable), return the signer address
address signer = ecrecover(hash, v, r, s);
if (signer == address(0)) {
return (address(0), RecoverError.InvalidSignature, bytes32(0));
}
return (signer, RecoverError.NoError, bytes32(0));
}
/**
* @dev Overload of {ECDSA-recover} that receives the `v`,
* `r` and `s` signature fields separately.
*/
function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {
(address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, v, r, s);
_throwError(error, errorArg);
return recovered;
}
/**
* @dev Optionally reverts with the corresponding custom error according to the `error` argument provided.
*/
function _throwError(RecoverError error, bytes32 errorArg) private pure {
if (error == RecoverError.NoError) {
return; // no error: do nothing
} else if (error == RecoverError.InvalidSignature) {
revert ECDSAInvalidSignature();
} else if (error == RecoverError.InvalidSignatureLength) {
revert ECDSAInvalidSignatureLength(uint256(errorArg));
} else if (error == RecoverError.InvalidSignatureS) {
revert ECDSAInvalidSignatureS(errorArg);
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.3.0) (utils/cryptography/MessageHashUtils.sol)
pragma solidity ^0.8.20;
import {Strings} from "../Strings.sol";
/**
* @dev Signature message hash utilities for producing digests to be consumed by {ECDSA} recovery or signing.
*
* The library provides methods for generating a hash of a message that conforms to the
* https://eips.ethereum.org/EIPS/eip-191[ERC-191] and https://eips.ethereum.org/EIPS/eip-712[EIP 712]
* specifications.
*/
library MessageHashUtils {
/**
* @dev Returns the keccak256 digest of an ERC-191 signed data with version
* `0x45` (`personal_sign` messages).
*
* The digest is calculated by prefixing a bytes32 `messageHash` with
* `"\x19Ethereum Signed Message:\n32"` and hashing the result. It corresponds with the
* hash signed when using the https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_sign[`eth_sign`] JSON-RPC method.
*
* NOTE: The `messageHash` parameter is intended to be the result of hashing a raw message with
* keccak256, although any bytes32 value can be safely used because the final digest will
* be re-hashed.
*
* See {ECDSA-recover}.
*/
function toEthSignedMessageHash(bytes32 messageHash) internal pure returns (bytes32 digest) {
assembly ("memory-safe") {
mstore(0x00, "\x19Ethereum Signed Message:\n32") // 32 is the bytes-length of messageHash
mstore(0x1c, messageHash) // 0x1c (28) is the length of the prefix
digest := keccak256(0x00, 0x3c) // 0x3c is the length of the prefix (0x1c) + messageHash (0x20)
}
}
/**
* @dev Returns the keccak256 digest of an ERC-191 signed data with version
* `0x45` (`personal_sign` messages).
*
* The digest is calculated by prefixing an arbitrary `message` with
* `"\x19Ethereum Signed Message:\n" + len(message)` and hashing the result. It corresponds with the
* hash signed when using the https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_sign[`eth_sign`] JSON-RPC method.
*
* See {ECDSA-recover}.
*/
function toEthSignedMessageHash(bytes memory message) internal pure returns (bytes32) {
return
keccak256(bytes.concat("\x19Ethereum Signed Message:\n", bytes(Strings.toString(message.length)), message));
}
/**
* @dev Returns the keccak256 digest of an ERC-191 signed data with version
* `0x00` (data with intended validator).
*
* The digest is calculated by prefixing an arbitrary `data` with `"\x19\x00"` and the intended
* `validator` address. Then hashing the result.
*
* See {ECDSA-recover}.
*/
function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) {
return keccak256(abi.encodePacked(hex"19_00", validator, data));
}
/**
* @dev Variant of {toDataWithIntendedValidatorHash-address-bytes} optimized for cases where `data` is a bytes32.
*/
function toDataWithIntendedValidatorHash(
address validator,
bytes32 messageHash
) internal pure returns (bytes32 digest) {
assembly ("memory-safe") {
mstore(0x00, hex"19_00")
mstore(0x02, shl(96, validator))
mstore(0x16, messageHash)
digest := keccak256(0x00, 0x36)
}
}
/**
* @dev Returns the keccak256 digest of an EIP-712 typed data (ERC-191 version `0x01`).
*
* The digest is calculated from a `domainSeparator` and a `structHash`, by prefixing them with
* `\x19\x01` and hashing the result. It corresponds to the hash signed by the
* https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`] JSON-RPC method as part of EIP-712.
*
* See {ECDSA-recover}.
*/
function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 digest) {
assembly ("memory-safe") {
let ptr := mload(0x40)
mstore(ptr, hex"19_01")
mstore(add(ptr, 0x02), domainSeparator)
mstore(add(ptr, 0x22), structHash)
digest := keccak256(ptr, 0x42)
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (utils/cryptography/SignatureChecker.sol)
pragma solidity ^0.8.24;
import {ECDSA} from "./ECDSA.sol";
import {IERC1271} from "../../interfaces/IERC1271.sol";
import {IERC7913SignatureVerifier} from "../../interfaces/IERC7913.sol";
import {Bytes} from "../../utils/Bytes.sol";
/**
* @dev Signature verification helper that can be used instead of `ECDSA.recover` to seamlessly support:
*
* * ECDSA signatures from externally owned accounts (EOAs)
* * ERC-1271 signatures from smart contract wallets like Argent and Safe Wallet (previously Gnosis Safe)
* * ERC-7913 signatures from keys that do not have an Ethereum address of their own
*
* See https://eips.ethereum.org/EIPS/eip-1271[ERC-1271] and https://eips.ethereum.org/EIPS/eip-7913[ERC-7913].
*/
library SignatureChecker {
using Bytes for bytes;
/**
* @dev Checks if a signature is valid for a given signer and data hash. If the signer has code, the
* signature is validated against it using ERC-1271, otherwise it's validated using `ECDSA.recover`.
*
* NOTE: Unlike ECDSA signatures, contract signatures are revocable, and the outcome of this function can thus
* change through time. It could return true at block N and false at block N+1 (or the opposite).
*
* NOTE: For an extended version of this function that supports ERC-7913 signatures, see {isValidSignatureNow-bytes-bytes32-bytes-}.
*/
function isValidSignatureNow(address signer, bytes32 hash, bytes memory signature) internal view returns (bool) {
if (signer.code.length == 0) {
(address recovered, ECDSA.RecoverError err, ) = ECDSA.tryRecover(hash, signature);
return err == ECDSA.RecoverError.NoError && recovered == signer;
} else {
return isValidERC1271SignatureNow(signer, hash, signature);
}
}
/**
* @dev Checks if a signature is valid for a given signer and data hash. The signature is validated
* against the signer smart contract using ERC-1271.
*
* NOTE: Unlike ECDSA signatures, contract signatures are revocable, and the outcome of this function can thus
* change through time. It could return true at block N and false at block N+1 (or the opposite).
*/
function isValidERC1271SignatureNow(
address signer,
bytes32 hash,
bytes memory signature
) internal view returns (bool) {
(bool success, bytes memory result) = signer.staticcall(
abi.encodeCall(IERC1271.isValidSignature, (hash, signature))
);
return (success &&
result.length >= 32 &&
abi.decode(result, (bytes32)) == bytes32(IERC1271.isValidSignature.selector));
}
/**
* @dev Verifies a signature for a given ERC-7913 signer and hash.
*
* The signer is a `bytes` object that is the concatenation of an address and optionally a key:
* `verifier || key`. A signer must be at least 20 bytes long.
*
* Verification is done as follows:
*
* * If `signer.length < 20`: verification fails
* * If `signer.length == 20`: verification is done using {isValidSignatureNow}
* * Otherwise: verification is done using {IERC7913SignatureVerifier}
*
* NOTE: Unlike ECDSA signatures, contract signatures are revocable, and the outcome of this function can thus
* change through time. It could return true at block N and false at block N+1 (or the opposite).
*/
function isValidSignatureNow(
bytes memory signer,
bytes32 hash,
bytes memory signature
) internal view returns (bool) {
if (signer.length < 20) {
return false;
} else if (signer.length == 20) {
return isValidSignatureNow(address(bytes20(signer)), hash, signature);
} else {
(bool success, bytes memory result) = address(bytes20(signer)).staticcall(
abi.encodeCall(IERC7913SignatureVerifier.verify, (signer.slice(20), hash, signature))
);
return (success &&
result.length >= 32 &&
abi.decode(result, (bytes32)) == bytes32(IERC7913SignatureVerifier.verify.selector));
}
}
/**
* @dev Verifies multiple ERC-7913 `signatures` for a given `hash` using a set of `signers`.
* Returns `false` if the number of signers and signatures is not the same.
*
* The signers should be ordered by their `keccak256` hash to ensure efficient duplication check. Unordered
* signers are supported, but the uniqueness check will be more expensive.
*
* NOTE: Unlike ECDSA signatures, contract signatures are revocable, and the outcome of this function can thus
* change through time. It could return true at block N and false at block N+1 (or the opposite).
*/
function areValidSignaturesNow(
bytes32 hash,
bytes[] memory signers,
bytes[] memory signatures
) internal view returns (bool) {
if (signers.length != signatures.length) return false;
bytes32 lastId = bytes32(0);
for (uint256 i = 0; i < signers.length; ++i) {
bytes memory signer = signers[i];
// If one of the signatures is invalid, reject the batch
if (!isValidSignatureNow(signer, hash, signatures[i])) return false;
bytes32 id = keccak256(signer);
// If the current signer ID is greater than all previous IDs, then this is a new signer.
if (lastId < id) {
lastId = id;
} else {
// If this signer id is not greater than all the previous ones, verify that it is not a duplicate of a previous one
// This loop is never executed if the signers are ordered by id.
for (uint256 j = 0; j < i; ++j) {
if (id == keccak256(signers[j])) return false;
}
}
}
return true;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/Errors.sol)
pragma solidity ^0.8.20;
/**
* @dev Collection of common custom errors used in multiple contracts
*
* IMPORTANT: Backwards compatibility is not guaranteed in future versions of the library.
* It is recommended to avoid relying on the error API for critical functionality.
*
* _Available since v5.1._
*/
library Errors {
/**
* @dev The ETH balance of the account is not enough to perform the operation.
*/
error InsufficientBalance(uint256 balance, uint256 needed);
/**
* @dev A call to an address target failed. The target may have reverted.
*/
error FailedCall();
/**
* @dev The deployment failed.
*/
error FailedDeployment();
/**
* @dev A necessary precompile is missing.
*/
error MissingPrecompile(address);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (utils/introspection/ERC165.sol)
pragma solidity ^0.8.20;
import {IERC165} from "./IERC165.sol";
/**
* @dev Implementation of the {IERC165} interface.
*
* Contracts that want to implement ERC-165 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);
* }
* ```
*/
abstract contract ERC165 is IERC165 {
/// @inheritdoc IERC165
function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {
return interfaceId == type(IERC165).interfaceId;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (utils/introspection/IERC165.sol)
pragma solidity >=0.4.16;
/**
* @dev Interface of the ERC-165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[ERC].
*
* 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[ERC 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 v5.3.0) (utils/math/Math.sol)
pragma solidity ^0.8.20;
import {Panic} from "../Panic.sol";
import {SafeCast} from "./SafeCast.sol";
/**
* @dev Standard math utilities missing in the Solidity language.
*/
library Math {
enum Rounding {
Floor, // Toward negative infinity
Ceil, // Toward positive infinity
Trunc, // Toward zero
Expand // Away from zero
}
/**
* @dev Return the 512-bit addition of two uint256.
*
* The result is stored in two 256 variables such that sum = high * 2²⁵⁶ + low.
*/
function add512(uint256 a, uint256 b) internal pure returns (uint256 high, uint256 low) {
assembly ("memory-safe") {
low := add(a, b)
high := lt(low, a)
}
}
/**
* @dev Return the 512-bit multiplication of two uint256.
*
* The result is stored in two 256 variables such that product = high * 2²⁵⁶ + low.
*/
function mul512(uint256 a, uint256 b) internal pure returns (uint256 high, uint256 low) {
// 512-bit multiply [high low] = x * y. Compute the product mod 2²⁵⁶ and mod 2²⁵⁶ - 1, then use
// the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
// variables such that product = high * 2²⁵⁶ + low.
assembly ("memory-safe") {
let mm := mulmod(a, b, not(0))
low := mul(a, b)
high := sub(sub(mm, low), lt(mm, low))
}
}
/**
* @dev Returns the addition of two unsigned integers, with a success flag (no overflow).
*/
function tryAdd(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {
unchecked {
uint256 c = a + b;
success = c >= a;
result = c * SafeCast.toUint(success);
}
}
/**
* @dev Returns the subtraction of two unsigned integers, with a success flag (no overflow).
*/
function trySub(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {
unchecked {
uint256 c = a - b;
success = c <= a;
result = c * SafeCast.toUint(success);
}
}
/**
* @dev Returns the multiplication of two unsigned integers, with a success flag (no overflow).
*/
function tryMul(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {
unchecked {
uint256 c = a * b;
assembly ("memory-safe") {
// Only true when the multiplication doesn't overflow
// (c / a == b) || (a == 0)
success := or(eq(div(c, a), b), iszero(a))
}
// equivalent to: success ? c : 0
result = c * SafeCast.toUint(success);
}
}
/**
* @dev Returns the division of two unsigned integers, with a success flag (no division by zero).
*/
function tryDiv(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {
unchecked {
success = b > 0;
assembly ("memory-safe") {
// The `DIV` opcode returns zero when the denominator is 0.
result := div(a, b)
}
}
}
/**
* @dev Returns the remainder of dividing two unsigned integers, with a success flag (no division by zero).
*/
function tryMod(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {
unchecked {
success = b > 0;
assembly ("memory-safe") {
// The `MOD` opcode returns zero when the denominator is 0.
result := mod(a, b)
}
}
}
/**
* @dev Unsigned saturating addition, bounds to `2²⁵⁶ - 1` instead of overflowing.
*/
function saturatingAdd(uint256 a, uint256 b) internal pure returns (uint256) {
(bool success, uint256 result) = tryAdd(a, b);
return ternary(success, result, type(uint256).max);
}
/**
* @dev Unsigned saturating subtraction, bounds to zero instead of overflowing.
*/
function saturatingSub(uint256 a, uint256 b) internal pure returns (uint256) {
(, uint256 result) = trySub(a, b);
return result;
}
/**
* @dev Unsigned saturating multiplication, bounds to `2²⁵⁶ - 1` instead of overflowing.
*/
function saturatingMul(uint256 a, uint256 b) internal pure returns (uint256) {
(bool success, uint256 result) = tryMul(a, b);
return ternary(success, result, type(uint256).max);
}
/**
* @dev Branchless ternary evaluation for `a ? b : c`. Gas costs are constant.
*
* IMPORTANT: This function may reduce bytecode size and consume less gas when used standalone.
* However, the compiler may optimize Solidity ternary operations (i.e. `a ? b : c`) to only compute
* one branch when needed, making this function more expensive.
*/
function ternary(bool condition, uint256 a, uint256 b) internal pure returns (uint256) {
unchecked {
// branchless ternary works because:
// b ^ (a ^ b) == a
// b ^ 0 == b
return b ^ ((a ^ b) * SafeCast.toUint(condition));
}
}
/**
* @dev Returns the largest of two numbers.
*/
function max(uint256 a, uint256 b) internal pure returns (uint256) {
return ternary(a > b, a, b);
}
/**
* @dev Returns the smallest of two numbers.
*/
function min(uint256 a, uint256 b) internal pure returns (uint256) {
return ternary(a < b, a, b);
}
/**
* @dev Returns the average of two numbers. The result is rounded towards
* zero.
*/
function average(uint256 a, uint256 b) internal pure returns (uint256) {
// (a + b) / 2 can overflow.
return (a & b) + (a ^ b) / 2;
}
/**
* @dev Returns the ceiling of the division of two numbers.
*
* This differs from standard division with `/` in that it rounds towards infinity instead
* of rounding towards zero.
*/
function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
if (b == 0) {
// Guarantee the same behavior as in a regular Solidity division.
Panic.panic(Panic.DIVISION_BY_ZERO);
}
// The following calculation ensures accurate ceiling division without overflow.
// Since a is non-zero, (a - 1) / b will not overflow.
// The largest possible result occurs when (a - 1) / b is type(uint256).max,
// but the largest value we can obtain is type(uint256).max - 1, which happens
// when a = type(uint256).max and b = 1.
unchecked {
return SafeCast.toUint(a > 0) * ((a - 1) / b + 1);
}
}
/**
* @dev Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or
* denominator == 0.
*
* Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) with further edits by
* Uniswap Labs also under MIT license.
*/
function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {
unchecked {
(uint256 high, uint256 low) = mul512(x, y);
// Handle non-overflow cases, 256 by 256 division.
if (high == 0) {
// Solidity will revert if denominator == 0, unlike the div opcode on its own.
// The surrounding unchecked block does not change this fact.
// See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.
return low / denominator;
}
// Make sure the result is less than 2²⁵⁶. Also prevents denominator == 0.
if (denominator <= high) {
Panic.panic(ternary(denominator == 0, Panic.DIVISION_BY_ZERO, Panic.UNDER_OVERFLOW));
}
///////////////////////////////////////////////
// 512 by 256 division.
///////////////////////////////////////////////
// Make division exact by subtracting the remainder from [high low].
uint256 remainder;
assembly ("memory-safe") {
// Compute remainder using mulmod.
remainder := mulmod(x, y, denominator)
// Subtract 256 bit number from 512 bit number.
high := sub(high, gt(remainder, low))
low := sub(low, remainder)
}
// Factor powers of two out of denominator and compute largest power of two divisor of denominator.
// Always >= 1. See https://cs.stackexchange.com/q/138556/92363.
uint256 twos = denominator & (0 - denominator);
assembly ("memory-safe") {
// Divide denominator by twos.
denominator := div(denominator, twos)
// Divide [high low] by twos.
low := div(low, twos)
// Flip twos such that it is 2²⁵⁶ / twos. If twos is zero, then it becomes one.
twos := add(div(sub(0, twos), twos), 1)
}
// Shift in bits from high into low.
low |= high * twos;
// Invert denominator mod 2²⁵⁶. Now that denominator is an odd number, it has an inverse modulo 2²⁵⁶ such
// that denominator * inv ≡ 1 mod 2²⁵⁶. Compute the inverse by starting with a seed that is correct for
// four bits. That is, denominator * inv ≡ 1 mod 2⁴.
uint256 inverse = (3 * denominator) ^ 2;
// Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also
// works in modular arithmetic, doubling the correct bits in each step.
inverse *= 2 - denominator * inverse; // inverse mod 2⁸
inverse *= 2 - denominator * inverse; // inverse mod 2¹⁶
inverse *= 2 - denominator * inverse; // inverse mod 2³²
inverse *= 2 - denominator * inverse; // inverse mod 2⁶⁴
inverse *= 2 - denominator * inverse; // inverse mod 2¹²⁸
inverse *= 2 - denominator * inverse; // inverse mod 2²⁵⁶
// Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
// This will give us the correct result modulo 2²⁵⁶. Since the preconditions guarantee that the outcome is
// less than 2²⁵⁶, this is the final result. We don't need to compute the high bits of the result and high
// is no longer required.
result = low * inverse;
return result;
}
}
/**
* @dev Calculates x * y / denominator with full precision, following the selected rounding direction.
*/
function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {
return mulDiv(x, y, denominator) + SafeCast.toUint(unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0);
}
/**
* @dev Calculates floor(x * y >> n) with full precision. Throws if result overflows a uint256.
*/
function mulShr(uint256 x, uint256 y, uint8 n) internal pure returns (uint256 result) {
unchecked {
(uint256 high, uint256 low) = mul512(x, y);
if (high >= 1 << n) {
Panic.panic(Panic.UNDER_OVERFLOW);
}
return (high << (256 - n)) | (low >> n);
}
}
/**
* @dev Calculates x * y >> n with full precision, following the selected rounding direction.
*/
function mulShr(uint256 x, uint256 y, uint8 n, Rounding rounding) internal pure returns (uint256) {
return mulShr(x, y, n) + SafeCast.toUint(unsignedRoundsUp(rounding) && mulmod(x, y, 1 << n) > 0);
}
/**
* @dev Calculate the modular multiplicative inverse of a number in Z/nZ.
*
* If n is a prime, then Z/nZ is a field. In that case all elements are inversible, except 0.
* If n is not a prime, then Z/nZ is not a field, and some elements might not be inversible.
*
* If the input value is not inversible, 0 is returned.
*
* NOTE: If you know for sure that n is (big) a prime, it may be cheaper to use Fermat's little theorem and get the
* inverse using `Math.modExp(a, n - 2, n)`. See {invModPrime}.
*/
function invMod(uint256 a, uint256 n) internal pure returns (uint256) {
unchecked {
if (n == 0) return 0;
// The inverse modulo is calculated using the Extended Euclidean Algorithm (iterative version)
// Used to compute integers x and y such that: ax + ny = gcd(a, n).
// When the gcd is 1, then the inverse of a modulo n exists and it's x.
// ax + ny = 1
// ax = 1 + (-y)n
// ax ≡ 1 (mod n) # x is the inverse of a modulo n
// If the remainder is 0 the gcd is n right away.
uint256 remainder = a % n;
uint256 gcd = n;
// Therefore the initial coefficients are:
// ax + ny = gcd(a, n) = n
// 0a + 1n = n
int256 x = 0;
int256 y = 1;
while (remainder != 0) {
uint256 quotient = gcd / remainder;
(gcd, remainder) = (
// The old remainder is the next gcd to try.
remainder,
// Compute the next remainder.
// Can't overflow given that (a % gcd) * (gcd // (a % gcd)) <= gcd
// where gcd is at most n (capped to type(uint256).max)
gcd - remainder * quotient
);
(x, y) = (
// Increment the coefficient of a.
y,
// Decrement the coefficient of n.
// Can overflow, but the result is casted to uint256 so that the
// next value of y is "wrapped around" to a value between 0 and n - 1.
x - y * int256(quotient)
);
}
if (gcd != 1) return 0; // No inverse exists.
return ternary(x < 0, n - uint256(-x), uint256(x)); // Wrap the result if it's negative.
}
}
/**
* @dev Variant of {invMod}. More efficient, but only works if `p` is known to be a prime greater than `2`.
*
* From https://en.wikipedia.org/wiki/Fermat%27s_little_theorem[Fermat's little theorem], we know that if p is
* prime, then `a**(p-1) ≡ 1 mod p`. As a consequence, we have `a * a**(p-2) ≡ 1 mod p`, which means that
* `a**(p-2)` is the modular multiplicative inverse of a in Fp.
*
* NOTE: this function does NOT check that `p` is a prime greater than `2`.
*/
function invModPrime(uint256 a, uint256 p) internal view returns (uint256) {
unchecked {
return Math.modExp(a, p - 2, p);
}
}
/**
* @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m)
*
* Requirements:
* - modulus can't be zero
* - underlying staticcall to precompile must succeed
*
* IMPORTANT: The result is only valid if the underlying call succeeds. When using this function, make
* sure the chain you're using it on supports the precompiled contract for modular exponentiation
* at address 0x05 as specified in https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise,
* the underlying function will succeed given the lack of a revert, but the result may be incorrectly
* interpreted as 0.
*/
function modExp(uint256 b, uint256 e, uint256 m) internal view returns (uint256) {
(bool success, uint256 result) = tryModExp(b, e, m);
if (!success) {
Panic.panic(Panic.DIVISION_BY_ZERO);
}
return result;
}
/**
* @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m).
* It includes a success flag indicating if the operation succeeded. Operation will be marked as failed if trying
* to operate modulo 0 or if the underlying precompile reverted.
*
* IMPORTANT: The result is only valid if the success flag is true. When using this function, make sure the chain
* you're using it on supports the precompiled contract for modular exponentiation at address 0x05 as specified in
* https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise, the underlying function will succeed given the lack
* of a revert, but the result may be incorrectly interpreted as 0.
*/
function tryModExp(uint256 b, uint256 e, uint256 m) internal view returns (bool success, uint256 result) {
if (m == 0) return (false, 0);
assembly ("memory-safe") {
let ptr := mload(0x40)
// | Offset | Content | Content (Hex) |
// |-----------|------------|--------------------------------------------------------------------|
// | 0x00:0x1f | size of b | 0x0000000000000000000000000000000000000000000000000000000000000020 |
// | 0x20:0x3f | size of e | 0x0000000000000000000000000000000000000000000000000000000000000020 |
// | 0x40:0x5f | size of m | 0x0000000000000000000000000000000000000000000000000000000000000020 |
// | 0x60:0x7f | value of b | 0x<.............................................................b> |
// | 0x80:0x9f | value of e | 0x<.............................................................e> |
// | 0xa0:0xbf | value of m | 0x<.............................................................m> |
mstore(ptr, 0x20)
mstore(add(ptr, 0x20), 0x20)
mstore(add(ptr, 0x40), 0x20)
mstore(add(ptr, 0x60), b)
mstore(add(ptr, 0x80), e)
mstore(add(ptr, 0xa0), m)
// Given the result < m, it's guaranteed to fit in 32 bytes,
// so we can use the memory scratch space located at offset 0.
success := staticcall(gas(), 0x05, ptr, 0xc0, 0x00, 0x20)
result := mload(0x00)
}
}
/**
* @dev Variant of {modExp} that supports inputs of arbitrary length.
*/
function modExp(bytes memory b, bytes memory e, bytes memory m) internal view returns (bytes memory) {
(bool success, bytes memory result) = tryModExp(b, e, m);
if (!success) {
Panic.panic(Panic.DIVISION_BY_ZERO);
}
return result;
}
/**
* @dev Variant of {tryModExp} that supports inputs of arbitrary length.
*/
function tryModExp(
bytes memory b,
bytes memory e,
bytes memory m
) internal view returns (bool success, bytes memory result) {
if (_zeroBytes(m)) return (false, new bytes(0));
uint256 mLen = m.length;
// Encode call args in result and move the free memory pointer
result = abi.encodePacked(b.length, e.length, mLen, b, e, m);
assembly ("memory-safe") {
let dataPtr := add(result, 0x20)
// Write result on top of args to avoid allocating extra memory.
success := staticcall(gas(), 0x05, dataPtr, mload(result), dataPtr, mLen)
// Overwrite the length.
// result.length > returndatasize() is guaranteed because returndatasize() == m.length
mstore(result, mLen)
// Set the memory pointer after the returned data.
mstore(0x40, add(dataPtr, mLen))
}
}
/**
* @dev Returns whether the provided byte array is zero.
*/
function _zeroBytes(bytes memory byteArray) private pure returns (bool) {
for (uint256 i = 0; i < byteArray.length; ++i) {
if (byteArray[i] != 0) {
return false;
}
}
return true;
}
/**
* @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded
* towards zero.
*
* This method is based on Newton's method for computing square roots; the algorithm is restricted to only
* using integer operations.
*/
function sqrt(uint256 a) internal pure returns (uint256) {
unchecked {
// Take care of easy edge cases when a == 0 or a == 1
if (a <= 1) {
return a;
}
// In this function, we use Newton's method to get a root of `f(x) := x² - a`. It involves building a
// sequence x_n that converges toward sqrt(a). For each iteration x_n, we also define the error between
// the current value as `ε_n = | x_n - sqrt(a) |`.
//
// For our first estimation, we consider `e` the smallest power of 2 which is bigger than the square root
// of the target. (i.e. `2**(e-1) ≤ sqrt(a) < 2**e`). We know that `e ≤ 128` because `(2¹²⁸)² = 2²⁵⁶` is
// bigger than any uint256.
//
// By noticing that
// `2**(e-1) ≤ sqrt(a) < 2**e → (2**(e-1))² ≤ a < (2**e)² → 2**(2*e-2) ≤ a < 2**(2*e)`
// we can deduce that `e - 1` is `log2(a) / 2`. We can thus compute `x_n = 2**(e-1)` using a method similar
// to the msb function.
uint256 aa = a;
uint256 xn = 1;
if (aa >= (1 << 128)) {
aa >>= 128;
xn <<= 64;
}
if (aa >= (1 << 64)) {
aa >>= 64;
xn <<= 32;
}
if (aa >= (1 << 32)) {
aa >>= 32;
xn <<= 16;
}
if (aa >= (1 << 16)) {
aa >>= 16;
xn <<= 8;
}
if (aa >= (1 << 8)) {
aa >>= 8;
xn <<= 4;
}
if (aa >= (1 << 4)) {
aa >>= 4;
xn <<= 2;
}
if (aa >= (1 << 2)) {
xn <<= 1;
}
// We now have x_n such that `x_n = 2**(e-1) ≤ sqrt(a) < 2**e = 2 * x_n`. This implies ε_n ≤ 2**(e-1).
//
// We can refine our estimation by noticing that the middle of that interval minimizes the error.
// If we move x_n to equal 2**(e-1) + 2**(e-2), then we reduce the error to ε_n ≤ 2**(e-2).
// This is going to be our x_0 (and ε_0)
xn = (3 * xn) >> 1; // ε_0 := | x_0 - sqrt(a) | ≤ 2**(e-2)
// From here, Newton's method give us:
// x_{n+1} = (x_n + a / x_n) / 2
//
// One should note that:
// x_{n+1}² - a = ((x_n + a / x_n) / 2)² - a
// = ((x_n² + a) / (2 * x_n))² - a
// = (x_n⁴ + 2 * a * x_n² + a²) / (4 * x_n²) - a
// = (x_n⁴ + 2 * a * x_n² + a² - 4 * a * x_n²) / (4 * x_n²)
// = (x_n⁴ - 2 * a * x_n² + a²) / (4 * x_n²)
// = (x_n² - a)² / (2 * x_n)²
// = ((x_n² - a) / (2 * x_n))²
// ≥ 0
// Which proves that for all n ≥ 1, sqrt(a) ≤ x_n
//
// This gives us the proof of quadratic convergence of the sequence:
// ε_{n+1} = | x_{n+1} - sqrt(a) |
// = | (x_n + a / x_n) / 2 - sqrt(a) |
// = | (x_n² + a - 2*x_n*sqrt(a)) / (2 * x_n) |
// = | (x_n - sqrt(a))² / (2 * x_n) |
// = | ε_n² / (2 * x_n) |
// = ε_n² / | (2 * x_n) |
//
// For the first iteration, we have a special case where x_0 is known:
// ε_1 = ε_0² / | (2 * x_0) |
// ≤ (2**(e-2))² / (2 * (2**(e-1) + 2**(e-2)))
// ≤ 2**(2*e-4) / (3 * 2**(e-1))
// ≤ 2**(e-3) / 3
// ≤ 2**(e-3-log2(3))
// ≤ 2**(e-4.5)
//
// For the following iterations, we use the fact that, 2**(e-1) ≤ sqrt(a) ≤ x_n:
// ε_{n+1} = ε_n² / | (2 * x_n) |
// ≤ (2**(e-k))² / (2 * 2**(e-1))
// ≤ 2**(2*e-2*k) / 2**e
// ≤ 2**(e-2*k)
xn = (xn + a / xn) >> 1; // ε_1 := | x_1 - sqrt(a) | ≤ 2**(e-4.5) -- special case, see above
xn = (xn + a / xn) >> 1; // ε_2 := | x_2 - sqrt(a) | ≤ 2**(e-9) -- general case with k = 4.5
xn = (xn + a / xn) >> 1; // ε_3 := | x_3 - sqrt(a) | ≤ 2**(e-18) -- general case with k = 9
xn = (xn + a / xn) >> 1; // ε_4 := | x_4 - sqrt(a) | ≤ 2**(e-36) -- general case with k = 18
xn = (xn + a / xn) >> 1; // ε_5 := | x_5 - sqrt(a) | ≤ 2**(e-72) -- general case with k = 36
xn = (xn + a / xn) >> 1; // ε_6 := | x_6 - sqrt(a) | ≤ 2**(e-144) -- general case with k = 72
// Because e ≤ 128 (as discussed during the first estimation phase), we know have reached a precision
// ε_6 ≤ 2**(e-144) < 1. Given we're operating on integers, then we can ensure that xn is now either
// sqrt(a) or sqrt(a) + 1.
return xn - SafeCast.toUint(xn > a / xn);
}
}
/**
* @dev Calculates sqrt(a), following the selected rounding direction.
*/
function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = sqrt(a);
return result + SafeCast.toUint(unsignedRoundsUp(rounding) && result * result < a);
}
}
/**
* @dev Return the log in base 2 of a positive value rounded towards zero.
* Returns 0 if given 0.
*/
function log2(uint256 x) internal pure returns (uint256 r) {
// If value has upper 128 bits set, log2 result is at least 128
r = SafeCast.toUint(x > 0xffffffffffffffffffffffffffffffff) << 7;
// If upper 64 bits of 128-bit half set, add 64 to result
r |= SafeCast.toUint((x >> r) > 0xffffffffffffffff) << 6;
// If upper 32 bits of 64-bit half set, add 32 to result
r |= SafeCast.toUint((x >> r) > 0xffffffff) << 5;
// If upper 16 bits of 32-bit half set, add 16 to result
r |= SafeCast.toUint((x >> r) > 0xffff) << 4;
// If upper 8 bits of 16-bit half set, add 8 to result
r |= SafeCast.toUint((x >> r) > 0xff) << 3;
// If upper 4 bits of 8-bit half set, add 4 to result
r |= SafeCast.toUint((x >> r) > 0xf) << 2;
// Shifts value right by the current result and use it as an index into this lookup table:
//
// | x (4 bits) | index | table[index] = MSB position |
// |------------|---------|-----------------------------|
// | 0000 | 0 | table[0] = 0 |
// | 0001 | 1 | table[1] = 0 |
// | 0010 | 2 | table[2] = 1 |
// | 0011 | 3 | table[3] = 1 |
// | 0100 | 4 | table[4] = 2 |
// | 0101 | 5 | table[5] = 2 |
// | 0110 | 6 | table[6] = 2 |
// | 0111 | 7 | table[7] = 2 |
// | 1000 | 8 | table[8] = 3 |
// | 1001 | 9 | table[9] = 3 |
// | 1010 | 10 | table[10] = 3 |
// | 1011 | 11 | table[11] = 3 |
// | 1100 | 12 | table[12] = 3 |
// | 1101 | 13 | table[13] = 3 |
// | 1110 | 14 | table[14] = 3 |
// | 1111 | 15 | table[15] = 3 |
//
// The lookup table is represented as a 32-byte value with the MSB positions for 0-15 in the last 16 bytes.
assembly ("memory-safe") {
r := or(r, byte(shr(r, x), 0x0000010102020202030303030303030300000000000000000000000000000000))
}
}
/**
* @dev Return the log in base 2, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log2(value);
return result + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << result < value);
}
}
/**
* @dev Return the log in base 10 of a positive value rounded towards zero.
* Returns 0 if given 0.
*/
function log10(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >= 10 ** 64) {
value /= 10 ** 64;
result += 64;
}
if (value >= 10 ** 32) {
value /= 10 ** 32;
result += 32;
}
if (value >= 10 ** 16) {
value /= 10 ** 16;
result += 16;
}
if (value >= 10 ** 8) {
value /= 10 ** 8;
result += 8;
}
if (value >= 10 ** 4) {
value /= 10 ** 4;
result += 4;
}
if (value >= 10 ** 2) {
value /= 10 ** 2;
result += 2;
}
if (value >= 10 ** 1) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 10, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log10(value);
return result + SafeCast.toUint(unsignedRoundsUp(rounding) && 10 ** result < value);
}
}
/**
* @dev Return the log in base 256 of a positive value rounded towards zero.
* Returns 0 if given 0.
*
* Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
*/
function log256(uint256 x) internal pure returns (uint256 r) {
// If value has upper 128 bits set, log2 result is at least 128
r = SafeCast.toUint(x > 0xffffffffffffffffffffffffffffffff) << 7;
// If upper 64 bits of 128-bit half set, add 64 to result
r |= SafeCast.toUint((x >> r) > 0xffffffffffffffff) << 6;
// If upper 32 bits of 64-bit half set, add 32 to result
r |= SafeCast.toUint((x >> r) > 0xffffffff) << 5;
// If upper 16 bits of 32-bit half set, add 16 to result
r |= SafeCast.toUint((x >> r) > 0xffff) << 4;
// Add 1 if upper 8 bits of 16-bit half set, and divide accumulated result by 8
return (r >> 3) | SafeCast.toUint((x >> r) > 0xff);
}
/**
* @dev Return the log in base 256, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log256(value);
return result + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << (result << 3) < value);
}
}
/**
* @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers.
*/
function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) {
return uint8(rounding) % 2 == 1;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/math/SafeCast.sol)
// This file was procedurally generated from scripts/generate/templates/SafeCast.js.
pragma solidity ^0.8.20;
/**
* @dev Wrappers over Solidity's uintXX/intXX/bool casting operators with added overflow
* checks.
*
* Downcasting from uint256/int256 in Solidity does not revert on overflow. This can
* easily result in undesired exploitation or bugs, since developers usually
* assume that overflows raise errors. `SafeCast` restores this intuition by
* reverting the transaction when such an operation overflows.
*
* Using this library instead of the unchecked operations eliminates an entire
* class of bugs, so it's recommended to use it always.
*/
library SafeCast {
/**
* @dev Value doesn't fit in an uint of `bits` size.
*/
error SafeCastOverflowedUintDowncast(uint8 bits, uint256 value);
/**
* @dev An int value doesn't fit in an uint of `bits` size.
*/
error SafeCastOverflowedIntToUint(int256 value);
/**
* @dev Value doesn't fit in an int of `bits` size.
*/
error SafeCastOverflowedIntDowncast(uint8 bits, int256 value);
/**
* @dev An uint value doesn't fit in an int of `bits` size.
*/
error SafeCastOverflowedUintToInt(uint256 value);
/**
* @dev Returns the downcasted uint248 from uint256, reverting on
* overflow (when the input is greater than largest uint248).
*
* Counterpart to Solidity's `uint248` operator.
*
* Requirements:
*
* - input must fit into 248 bits
*/
function toUint248(uint256 value) internal pure returns (uint248) {
if (value > type(uint248).max) {
revert SafeCastOverflowedUintDowncast(248, value);
}
return uint248(value);
}
/**
* @dev Returns the downcasted uint240 from uint256, reverting on
* overflow (when the input is greater than largest uint240).
*
* Counterpart to Solidity's `uint240` operator.
*
* Requirements:
*
* - input must fit into 240 bits
*/
function toUint240(uint256 value) internal pure returns (uint240) {
if (value > type(uint240).max) {
revert SafeCastOverflowedUintDowncast(240, value);
}
return uint240(value);
}
/**
* @dev Returns the downcasted uint232 from uint256, reverting on
* overflow (when the input is greater than largest uint232).
*
* Counterpart to Solidity's `uint232` operator.
*
* Requirements:
*
* - input must fit into 232 bits
*/
function toUint232(uint256 value) internal pure returns (uint232) {
if (value > type(uint232).max) {
revert SafeCastOverflowedUintDowncast(232, value);
}
return uint232(value);
}
/**
* @dev Returns the downcasted uint224 from uint256, reverting on
* overflow (when the input is greater than largest uint224).
*
* Counterpart to Solidity's `uint224` operator.
*
* Requirements:
*
* - input must fit into 224 bits
*/
function toUint224(uint256 value) internal pure returns (uint224) {
if (value > type(uint224).max) {
revert SafeCastOverflowedUintDowncast(224, value);
}
return uint224(value);
}
/**
* @dev Returns the downcasted uint216 from uint256, reverting on
* overflow (when the input is greater than largest uint216).
*
* Counterpart to Solidity's `uint216` operator.
*
* Requirements:
*
* - input must fit into 216 bits
*/
function toUint216(uint256 value) internal pure returns (uint216) {
if (value > type(uint216).max) {
revert SafeCastOverflowedUintDowncast(216, value);
}
return uint216(value);
}
/**
* @dev Returns the downcasted uint208 from uint256, reverting on
* overflow (when the input is greater than largest uint208).
*
* Counterpart to Solidity's `uint208` operator.
*
* Requirements:
*
* - input must fit into 208 bits
*/
function toUint208(uint256 value) internal pure returns (uint208) {
if (value > type(uint208).max) {
revert SafeCastOverflowedUintDowncast(208, value);
}
return uint208(value);
}
/**
* @dev Returns the downcasted uint200 from uint256, reverting on
* overflow (when the input is greater than largest uint200).
*
* Counterpart to Solidity's `uint200` operator.
*
* Requirements:
*
* - input must fit into 200 bits
*/
function toUint200(uint256 value) internal pure returns (uint200) {
if (value > type(uint200).max) {
revert SafeCastOverflowedUintDowncast(200, value);
}
return uint200(value);
}
/**
* @dev Returns the downcasted uint192 from uint256, reverting on
* overflow (when the input is greater than largest uint192).
*
* Counterpart to Solidity's `uint192` operator.
*
* Requirements:
*
* - input must fit into 192 bits
*/
function toUint192(uint256 value) internal pure returns (uint192) {
if (value > type(uint192).max) {
revert SafeCastOverflowedUintDowncast(192, value);
}
return uint192(value);
}
/**
* @dev Returns the downcasted uint184 from uint256, reverting on
* overflow (when the input is greater than largest uint184).
*
* Counterpart to Solidity's `uint184` operator.
*
* Requirements:
*
* - input must fit into 184 bits
*/
function toUint184(uint256 value) internal pure returns (uint184) {
if (value > type(uint184).max) {
revert SafeCastOverflowedUintDowncast(184, value);
}
return uint184(value);
}
/**
* @dev Returns the downcasted uint176 from uint256, reverting on
* overflow (when the input is greater than largest uint176).
*
* Counterpart to Solidity's `uint176` operator.
*
* Requirements:
*
* - input must fit into 176 bits
*/
function toUint176(uint256 value) internal pure returns (uint176) {
if (value > type(uint176).max) {
revert SafeCastOverflowedUintDowncast(176, value);
}
return uint176(value);
}
/**
* @dev Returns the downcasted uint168 from uint256, reverting on
* overflow (when the input is greater than largest uint168).
*
* Counterpart to Solidity's `uint168` operator.
*
* Requirements:
*
* - input must fit into 168 bits
*/
function toUint168(uint256 value) internal pure returns (uint168) {
if (value > type(uint168).max) {
revert SafeCastOverflowedUintDowncast(168, value);
}
return uint168(value);
}
/**
* @dev Returns the downcasted uint160 from uint256, reverting on
* overflow (when the input is greater than largest uint160).
*
* Counterpart to Solidity's `uint160` operator.
*
* Requirements:
*
* - input must fit into 160 bits
*/
function toUint160(uint256 value) internal pure returns (uint160) {
if (value > type(uint160).max) {
revert SafeCastOverflowedUintDowncast(160, value);
}
return uint160(value);
}
/**
* @dev Returns the downcasted uint152 from uint256, reverting on
* overflow (when the input is greater than largest uint152).
*
* Counterpart to Solidity's `uint152` operator.
*
* Requirements:
*
* - input must fit into 152 bits
*/
function toUint152(uint256 value) internal pure returns (uint152) {
if (value > type(uint152).max) {
revert SafeCastOverflowedUintDowncast(152, value);
}
return uint152(value);
}
/**
* @dev Returns the downcasted uint144 from uint256, reverting on
* overflow (when the input is greater than largest uint144).
*
* Counterpart to Solidity's `uint144` operator.
*
* Requirements:
*
* - input must fit into 144 bits
*/
function toUint144(uint256 value) internal pure returns (uint144) {
if (value > type(uint144).max) {
revert SafeCastOverflowedUintDowncast(144, value);
}
return uint144(value);
}
/**
* @dev Returns the downcasted uint136 from uint256, reverting on
* overflow (when the input is greater than largest uint136).
*
* Counterpart to Solidity's `uint136` operator.
*
* Requirements:
*
* - input must fit into 136 bits
*/
function toUint136(uint256 value) internal pure returns (uint136) {
if (value > type(uint136).max) {
revert SafeCastOverflowedUintDowncast(136, value);
}
return uint136(value);
}
/**
* @dev Returns the downcasted uint128 from uint256, reverting on
* overflow (when the input is greater than largest uint128).
*
* Counterpart to Solidity's `uint128` operator.
*
* Requirements:
*
* - input must fit into 128 bits
*/
function toUint128(uint256 value) internal pure returns (uint128) {
if (value > type(uint128).max) {
revert SafeCastOverflowedUintDowncast(128, value);
}
return uint128(value);
}
/**
* @dev Returns the downcasted uint120 from uint256, reverting on
* overflow (when the input is greater than largest uint120).
*
* Counterpart to Solidity's `uint120` operator.
*
* Requirements:
*
* - input must fit into 120 bits
*/
function toUint120(uint256 value) internal pure returns (uint120) {
if (value > type(uint120).max) {
revert SafeCastOverflowedUintDowncast(120, value);
}
return uint120(value);
}
/**
* @dev Returns the downcasted uint112 from uint256, reverting on
* overflow (when the input is greater than largest uint112).
*
* Counterpart to Solidity's `uint112` operator.
*
* Requirements:
*
* - input must fit into 112 bits
*/
function toUint112(uint256 value) internal pure returns (uint112) {
if (value > type(uint112).max) {
revert SafeCastOverflowedUintDowncast(112, value);
}
return uint112(value);
}
/**
* @dev Returns the downcasted uint104 from uint256, reverting on
* overflow (when the input is greater than largest uint104).
*
* Counterpart to Solidity's `uint104` operator.
*
* Requirements:
*
* - input must fit into 104 bits
*/
function toUint104(uint256 value) internal pure returns (uint104) {
if (value > type(uint104).max) {
revert SafeCastOverflowedUintDowncast(104, value);
}
return uint104(value);
}
/**
* @dev Returns the downcasted uint96 from uint256, reverting on
* overflow (when the input is greater than largest uint96).
*
* Counterpart to Solidity's `uint96` operator.
*
* Requirements:
*
* - input must fit into 96 bits
*/
function toUint96(uint256 value) internal pure returns (uint96) {
if (value > type(uint96).max) {
revert SafeCastOverflowedUintDowncast(96, value);
}
return uint96(value);
}
/**
* @dev Returns the downcasted uint88 from uint256, reverting on
* overflow (when the input is greater than largest uint88).
*
* Counterpart to Solidity's `uint88` operator.
*
* Requirements:
*
* - input must fit into 88 bits
*/
function toUint88(uint256 value) internal pure returns (uint88) {
if (value > type(uint88).max) {
revert SafeCastOverflowedUintDowncast(88, value);
}
return uint88(value);
}
/**
* @dev Returns the downcasted uint80 from uint256, reverting on
* overflow (when the input is greater than largest uint80).
*
* Counterpart to Solidity's `uint80` operator.
*
* Requirements:
*
* - input must fit into 80 bits
*/
function toUint80(uint256 value) internal pure returns (uint80) {
if (value > type(uint80).max) {
revert SafeCastOverflowedUintDowncast(80, value);
}
return uint80(value);
}
/**
* @dev Returns the downcasted uint72 from uint256, reverting on
* overflow (when the input is greater than largest uint72).
*
* Counterpart to Solidity's `uint72` operator.
*
* Requirements:
*
* - input must fit into 72 bits
*/
function toUint72(uint256 value) internal pure returns (uint72) {
if (value > type(uint72).max) {
revert SafeCastOverflowedUintDowncast(72, value);
}
return uint72(value);
}
/**
* @dev Returns the downcasted uint64 from uint256, reverting on
* overflow (when the input is greater than largest uint64).
*
* Counterpart to Solidity's `uint64` operator.
*
* Requirements:
*
* - input must fit into 64 bits
*/
function toUint64(uint256 value) internal pure returns (uint64) {
if (value > type(uint64).max) {
revert SafeCastOverflowedUintDowncast(64, value);
}
return uint64(value);
}
/**
* @dev Returns the downcasted uint56 from uint256, reverting on
* overflow (when the input is greater than largest uint56).
*
* Counterpart to Solidity's `uint56` operator.
*
* Requirements:
*
* - input must fit into 56 bits
*/
function toUint56(uint256 value) internal pure returns (uint56) {
if (value > type(uint56).max) {
revert SafeCastOverflowedUintDowncast(56, value);
}
return uint56(value);
}
/**
* @dev Returns the downcasted uint48 from uint256, reverting on
* overflow (when the input is greater than largest uint48).
*
* Counterpart to Solidity's `uint48` operator.
*
* Requirements:
*
* - input must fit into 48 bits
*/
function toUint48(uint256 value) internal pure returns (uint48) {
if (value > type(uint48).max) {
revert SafeCastOverflowedUintDowncast(48, value);
}
return uint48(value);
}
/**
* @dev Returns the downcasted uint40 from uint256, reverting on
* overflow (when the input is greater than largest uint40).
*
* Counterpart to Solidity's `uint40` operator.
*
* Requirements:
*
* - input must fit into 40 bits
*/
function toUint40(uint256 value) internal pure returns (uint40) {
if (value > type(uint40).max) {
revert SafeCastOverflowedUintDowncast(40, value);
}
return uint40(value);
}
/**
* @dev Returns the downcasted uint32 from uint256, reverting on
* overflow (when the input is greater than largest uint32).
*
* Counterpart to Solidity's `uint32` operator.
*
* Requirements:
*
* - input must fit into 32 bits
*/
function toUint32(uint256 value) internal pure returns (uint32) {
if (value > type(uint32).max) {
revert SafeCastOverflowedUintDowncast(32, value);
}
return uint32(value);
}
/**
* @dev Returns the downcasted uint24 from uint256, reverting on
* overflow (when the input is greater than largest uint24).
*
* Counterpart to Solidity's `uint24` operator.
*
* Requirements:
*
* - input must fit into 24 bits
*/
function toUint24(uint256 value) internal pure returns (uint24) {
if (value > type(uint24).max) {
revert SafeCastOverflowedUintDowncast(24, value);
}
return uint24(value);
}
/**
* @dev Returns the downcasted uint16 from uint256, reverting on
* overflow (when the input is greater than largest uint16).
*
* Counterpart to Solidity's `uint16` operator.
*
* Requirements:
*
* - input must fit into 16 bits
*/
function toUint16(uint256 value) internal pure returns (uint16) {
if (value > type(uint16).max) {
revert SafeCastOverflowedUintDowncast(16, value);
}
return uint16(value);
}
/**
* @dev Returns the downcasted uint8 from uint256, reverting on
* overflow (when the input is greater than largest uint8).
*
* Counterpart to Solidity's `uint8` operator.
*
* Requirements:
*
* - input must fit into 8 bits
*/
function toUint8(uint256 value) internal pure returns (uint8) {
if (value > type(uint8).max) {
revert SafeCastOverflowedUintDowncast(8, value);
}
return uint8(value);
}
/**
* @dev Converts a signed int256 into an unsigned uint256.
*
* Requirements:
*
* - input must be greater than or equal to 0.
*/
function toUint256(int256 value) internal pure returns (uint256) {
if (value < 0) {
revert SafeCastOverflowedIntToUint(value);
}
return uint256(value);
}
/**
* @dev Returns the downcasted int248 from int256, reverting on
* overflow (when the input is less than smallest int248 or
* greater than largest int248).
*
* Counterpart to Solidity's `int248` operator.
*
* Requirements:
*
* - input must fit into 248 bits
*/
function toInt248(int256 value) internal pure returns (int248 downcasted) {
downcasted = int248(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(248, value);
}
}
/**
* @dev Returns the downcasted int240 from int256, reverting on
* overflow (when the input is less than smallest int240 or
* greater than largest int240).
*
* Counterpart to Solidity's `int240` operator.
*
* Requirements:
*
* - input must fit into 240 bits
*/
function toInt240(int256 value) internal pure returns (int240 downcasted) {
downcasted = int240(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(240, value);
}
}
/**
* @dev Returns the downcasted int232 from int256, reverting on
* overflow (when the input is less than smallest int232 or
* greater than largest int232).
*
* Counterpart to Solidity's `int232` operator.
*
* Requirements:
*
* - input must fit into 232 bits
*/
function toInt232(int256 value) internal pure returns (int232 downcasted) {
downcasted = int232(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(232, value);
}
}
/**
* @dev Returns the downcasted int224 from int256, reverting on
* overflow (when the input is less than smallest int224 or
* greater than largest int224).
*
* Counterpart to Solidity's `int224` operator.
*
* Requirements:
*
* - input must fit into 224 bits
*/
function toInt224(int256 value) internal pure returns (int224 downcasted) {
downcasted = int224(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(224, value);
}
}
/**
* @dev Returns the downcasted int216 from int256, reverting on
* overflow (when the input is less than smallest int216 or
* greater than largest int216).
*
* Counterpart to Solidity's `int216` operator.
*
* Requirements:
*
* - input must fit into 216 bits
*/
function toInt216(int256 value) internal pure returns (int216 downcasted) {
downcasted = int216(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(216, value);
}
}
/**
* @dev Returns the downcasted int208 from int256, reverting on
* overflow (when the input is less than smallest int208 or
* greater than largest int208).
*
* Counterpart to Solidity's `int208` operator.
*
* Requirements:
*
* - input must fit into 208 bits
*/
function toInt208(int256 value) internal pure returns (int208 downcasted) {
downcasted = int208(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(208, value);
}
}
/**
* @dev Returns the downcasted int200 from int256, reverting on
* overflow (when the input is less than smallest int200 or
* greater than largest int200).
*
* Counterpart to Solidity's `int200` operator.
*
* Requirements:
*
* - input must fit into 200 bits
*/
function toInt200(int256 value) internal pure returns (int200 downcasted) {
downcasted = int200(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(200, value);
}
}
/**
* @dev Returns the downcasted int192 from int256, reverting on
* overflow (when the input is less than smallest int192 or
* greater than largest int192).
*
* Counterpart to Solidity's `int192` operator.
*
* Requirements:
*
* - input must fit into 192 bits
*/
function toInt192(int256 value) internal pure returns (int192 downcasted) {
downcasted = int192(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(192, value);
}
}
/**
* @dev Returns the downcasted int184 from int256, reverting on
* overflow (when the input is less than smallest int184 or
* greater than largest int184).
*
* Counterpart to Solidity's `int184` operator.
*
* Requirements:
*
* - input must fit into 184 bits
*/
function toInt184(int256 value) internal pure returns (int184 downcasted) {
downcasted = int184(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(184, value);
}
}
/**
* @dev Returns the downcasted int176 from int256, reverting on
* overflow (when the input is less than smallest int176 or
* greater than largest int176).
*
* Counterpart to Solidity's `int176` operator.
*
* Requirements:
*
* - input must fit into 176 bits
*/
function toInt176(int256 value) internal pure returns (int176 downcasted) {
downcasted = int176(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(176, value);
}
}
/**
* @dev Returns the downcasted int168 from int256, reverting on
* overflow (when the input is less than smallest int168 or
* greater than largest int168).
*
* Counterpart to Solidity's `int168` operator.
*
* Requirements:
*
* - input must fit into 168 bits
*/
function toInt168(int256 value) internal pure returns (int168 downcasted) {
downcasted = int168(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(168, value);
}
}
/**
* @dev Returns the downcasted int160 from int256, reverting on
* overflow (when the input is less than smallest int160 or
* greater than largest int160).
*
* Counterpart to Solidity's `int160` operator.
*
* Requirements:
*
* - input must fit into 160 bits
*/
function toInt160(int256 value) internal pure returns (int160 downcasted) {
downcasted = int160(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(160, value);
}
}
/**
* @dev Returns the downcasted int152 from int256, reverting on
* overflow (when the input is less than smallest int152 or
* greater than largest int152).
*
* Counterpart to Solidity's `int152` operator.
*
* Requirements:
*
* - input must fit into 152 bits
*/
function toInt152(int256 value) internal pure returns (int152 downcasted) {
downcasted = int152(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(152, value);
}
}
/**
* @dev Returns the downcasted int144 from int256, reverting on
* overflow (when the input is less than smallest int144 or
* greater than largest int144).
*
* Counterpart to Solidity's `int144` operator.
*
* Requirements:
*
* - input must fit into 144 bits
*/
function toInt144(int256 value) internal pure returns (int144 downcasted) {
downcasted = int144(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(144, value);
}
}
/**
* @dev Returns the downcasted int136 from int256, reverting on
* overflow (when the input is less than smallest int136 or
* greater than largest int136).
*
* Counterpart to Solidity's `int136` operator.
*
* Requirements:
*
* - input must fit into 136 bits
*/
function toInt136(int256 value) internal pure returns (int136 downcasted) {
downcasted = int136(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(136, value);
}
}
/**
* @dev Returns the downcasted int128 from int256, reverting on
* overflow (when the input is less than smallest int128 or
* greater than largest int128).
*
* Counterpart to Solidity's `int128` operator.
*
* Requirements:
*
* - input must fit into 128 bits
*/
function toInt128(int256 value) internal pure returns (int128 downcasted) {
downcasted = int128(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(128, value);
}
}
/**
* @dev Returns the downcasted int120 from int256, reverting on
* overflow (when the input is less than smallest int120 or
* greater than largest int120).
*
* Counterpart to Solidity's `int120` operator.
*
* Requirements:
*
* - input must fit into 120 bits
*/
function toInt120(int256 value) internal pure returns (int120 downcasted) {
downcasted = int120(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(120, value);
}
}
/**
* @dev Returns the downcasted int112 from int256, reverting on
* overflow (when the input is less than smallest int112 or
* greater than largest int112).
*
* Counterpart to Solidity's `int112` operator.
*
* Requirements:
*
* - input must fit into 112 bits
*/
function toInt112(int256 value) internal pure returns (int112 downcasted) {
downcasted = int112(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(112, value);
}
}
/**
* @dev Returns the downcasted int104 from int256, reverting on
* overflow (when the input is less than smallest int104 or
* greater than largest int104).
*
* Counterpart to Solidity's `int104` operator.
*
* Requirements:
*
* - input must fit into 104 bits
*/
function toInt104(int256 value) internal pure returns (int104 downcasted) {
downcasted = int104(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(104, value);
}
}
/**
* @dev Returns the downcasted int96 from int256, reverting on
* overflow (when the input is less than smallest int96 or
* greater than largest int96).
*
* Counterpart to Solidity's `int96` operator.
*
* Requirements:
*
* - input must fit into 96 bits
*/
function toInt96(int256 value) internal pure returns (int96 downcasted) {
downcasted = int96(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(96, value);
}
}
/**
* @dev Returns the downcasted int88 from int256, reverting on
* overflow (when the input is less than smallest int88 or
* greater than largest int88).
*
* Counterpart to Solidity's `int88` operator.
*
* Requirements:
*
* - input must fit into 88 bits
*/
function toInt88(int256 value) internal pure returns (int88 downcasted) {
downcasted = int88(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(88, value);
}
}
/**
* @dev Returns the downcasted int80 from int256, reverting on
* overflow (when the input is less than smallest int80 or
* greater than largest int80).
*
* Counterpart to Solidity's `int80` operator.
*
* Requirements:
*
* - input must fit into 80 bits
*/
function toInt80(int256 value) internal pure returns (int80 downcasted) {
downcasted = int80(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(80, value);
}
}
/**
* @dev Returns the downcasted int72 from int256, reverting on
* overflow (when the input is less than smallest int72 or
* greater than largest int72).
*
* Counterpart to Solidity's `int72` operator.
*
* Requirements:
*
* - input must fit into 72 bits
*/
function toInt72(int256 value) internal pure returns (int72 downcasted) {
downcasted = int72(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(72, value);
}
}
/**
* @dev Returns the downcasted int64 from int256, reverting on
* overflow (when the input is less than smallest int64 or
* greater than largest int64).
*
* Counterpart to Solidity's `int64` operator.
*
* Requirements:
*
* - input must fit into 64 bits
*/
function toInt64(int256 value) internal pure returns (int64 downcasted) {
downcasted = int64(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(64, value);
}
}
/**
* @dev Returns the downcasted int56 from int256, reverting on
* overflow (when the input is less than smallest int56 or
* greater than largest int56).
*
* Counterpart to Solidity's `int56` operator.
*
* Requirements:
*
* - input must fit into 56 bits
*/
function toInt56(int256 value) internal pure returns (int56 downcasted) {
downcasted = int56(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(56, value);
}
}
/**
* @dev Returns the downcasted int48 from int256, reverting on
* overflow (when the input is less than smallest int48 or
* greater than largest int48).
*
* Counterpart to Solidity's `int48` operator.
*
* Requirements:
*
* - input must fit into 48 bits
*/
function toInt48(int256 value) internal pure returns (int48 downcasted) {
downcasted = int48(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(48, value);
}
}
/**
* @dev Returns the downcasted int40 from int256, reverting on
* overflow (when the input is less than smallest int40 or
* greater than largest int40).
*
* Counterpart to Solidity's `int40` operator.
*
* Requirements:
*
* - input must fit into 40 bits
*/
function toInt40(int256 value) internal pure returns (int40 downcasted) {
downcasted = int40(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(40, value);
}
}
/**
* @dev Returns the downcasted int32 from int256, reverting on
* overflow (when the input is less than smallest int32 or
* greater than largest int32).
*
* Counterpart to Solidity's `int32` operator.
*
* Requirements:
*
* - input must fit into 32 bits
*/
function toInt32(int256 value) internal pure returns (int32 downcasted) {
downcasted = int32(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(32, value);
}
}
/**
* @dev Returns the downcasted int24 from int256, reverting on
* overflow (when the input is less than smallest int24 or
* greater than largest int24).
*
* Counterpart to Solidity's `int24` operator.
*
* Requirements:
*
* - input must fit into 24 bits
*/
function toInt24(int256 value) internal pure returns (int24 downcasted) {
downcasted = int24(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(24, value);
}
}
/**
* @dev Returns the downcasted int16 from int256, reverting on
* overflow (when the input is less than smallest int16 or
* greater than largest int16).
*
* Counterpart to Solidity's `int16` operator.
*
* Requirements:
*
* - input must fit into 16 bits
*/
function toInt16(int256 value) internal pure returns (int16 downcasted) {
downcasted = int16(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(16, value);
}
}
/**
* @dev Returns the downcasted int8 from int256, reverting on
* overflow (when the input is less than smallest int8 or
* greater than largest int8).
*
* Counterpart to Solidity's `int8` operator.
*
* Requirements:
*
* - input must fit into 8 bits
*/
function toInt8(int256 value) internal pure returns (int8 downcasted) {
downcasted = int8(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(8, value);
}
}
/**
* @dev Converts an unsigned uint256 into a signed int256.
*
* Requirements:
*
* - input must be less than or equal to maxInt256.
*/
function toInt256(uint256 value) internal pure returns (int256) {
// Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive
if (value > uint256(type(int256).max)) {
revert SafeCastOverflowedUintToInt(value);
}
return int256(value);
}
/**
* @dev Cast a boolean (false or true) to a uint256 (0 or 1) with no jump.
*/
function toUint(bool b) internal pure returns (uint256 u) {
assembly ("memory-safe") {
u := iszero(iszero(b))
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/math/SignedMath.sol)
pragma solidity ^0.8.20;
import {SafeCast} from "./SafeCast.sol";
/**
* @dev Standard signed math utilities missing in the Solidity language.
*/
library SignedMath {
/**
* @dev Branchless ternary evaluation for `a ? b : c`. Gas costs are constant.
*
* IMPORTANT: This function may reduce bytecode size and consume less gas when used standalone.
* However, the compiler may optimize Solidity ternary operations (i.e. `a ? b : c`) to only compute
* one branch when needed, making this function more expensive.
*/
function ternary(bool condition, int256 a, int256 b) internal pure returns (int256) {
unchecked {
// branchless ternary works because:
// b ^ (a ^ b) == a
// b ^ 0 == b
return b ^ ((a ^ b) * int256(SafeCast.toUint(condition)));
}
}
/**
* @dev Returns the largest of two signed numbers.
*/
function max(int256 a, int256 b) internal pure returns (int256) {
return ternary(a > b, a, b);
}
/**
* @dev Returns the smallest of two signed numbers.
*/
function min(int256 a, int256 b) internal pure returns (int256) {
return ternary(a < b, a, b);
}
/**
* @dev Returns the average of two signed numbers without overflow.
* The result is rounded towards zero.
*/
function average(int256 a, int256 b) internal pure returns (int256) {
// Formula from the book "Hacker's Delight"
int256 x = (a & b) + ((a ^ b) >> 1);
return x + (int256(uint256(x) >> 255) & (a ^ b));
}
/**
* @dev Returns the absolute unsigned value of a signed value.
*/
function abs(int256 n) internal pure returns (uint256) {
unchecked {
// Formula from the "Bit Twiddling Hacks" by Sean Eron Anderson.
// Since `n` is a signed integer, the generated bytecode will use the SAR opcode to perform the right shift,
// taking advantage of the most significant (or "sign" bit) in two's complement representation.
// This opcode adds new most significant bits set to the value of the previous most significant bit. As a result,
// the mask will either be `bytes32(0)` (if n is positive) or `~bytes32(0)` (if n is negative).
int256 mask = n >> 255;
// A `bytes32(0)` mask leaves the input unchanged, while a `~bytes32(0)` mask complements it.
return uint256((n + mask) ^ mask);
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/Panic.sol)
pragma solidity ^0.8.20;
/**
* @dev Helper library for emitting standardized panic codes.
*
* ```solidity
* contract Example {
* using Panic for uint256;
*
* // Use any of the declared internal constants
* function foo() { Panic.GENERIC.panic(); }
*
* // Alternatively
* function foo() { Panic.panic(Panic.GENERIC); }
* }
* ```
*
* Follows the list from https://github.com/ethereum/solidity/blob/v0.8.24/libsolutil/ErrorCodes.h[libsolutil].
*
* _Available since v5.1._
*/
// slither-disable-next-line unused-state
library Panic {
/// @dev generic / unspecified error
uint256 internal constant GENERIC = 0x00;
/// @dev used by the assert() builtin
uint256 internal constant ASSERT = 0x01;
/// @dev arithmetic underflow or overflow
uint256 internal constant UNDER_OVERFLOW = 0x11;
/// @dev division or modulo by zero
uint256 internal constant DIVISION_BY_ZERO = 0x12;
/// @dev enum conversion error
uint256 internal constant ENUM_CONVERSION_ERROR = 0x21;
/// @dev invalid encoding in storage
uint256 internal constant STORAGE_ENCODING_ERROR = 0x22;
/// @dev empty array pop
uint256 internal constant EMPTY_ARRAY_POP = 0x31;
/// @dev array out of bounds access
uint256 internal constant ARRAY_OUT_OF_BOUNDS = 0x32;
/// @dev resource error (too large allocation or too large array)
uint256 internal constant RESOURCE_ERROR = 0x41;
/// @dev calling invalid internal function
uint256 internal constant INVALID_INTERNAL_FUNCTION = 0x51;
/// @dev Reverts with a panic code. Recommended to use with
/// the internal constants with predefined codes.
function panic(uint256 code) internal pure {
assembly ("memory-safe") {
mstore(0x00, 0x4e487b71)
mstore(0x20, code)
revert(0x1c, 0x24)
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (utils/Strings.sol)
pragma solidity ^0.8.20;
import {Math} from "./math/Math.sol";
import {SafeCast} from "./math/SafeCast.sol";
import {SignedMath} from "./math/SignedMath.sol";
/**
* @dev String operations.
*/
library Strings {
using SafeCast for *;
bytes16 private constant HEX_DIGITS = "0123456789abcdef";
uint8 private constant ADDRESS_LENGTH = 20;
uint256 private constant SPECIAL_CHARS_LOOKUP =
(1 << 0x08) | // backspace
(1 << 0x09) | // tab
(1 << 0x0a) | // newline
(1 << 0x0c) | // form feed
(1 << 0x0d) | // carriage return
(1 << 0x22) | // double quote
(1 << 0x5c); // backslash
/**
* @dev The `value` string doesn't fit in the specified `length`.
*/
error StringsInsufficientHexLength(uint256 value, uint256 length);
/**
* @dev The string being parsed contains characters that are not in scope of the given base.
*/
error StringsInvalidChar();
/**
* @dev The string being parsed is not a properly formatted address.
*/
error StringsInvalidAddressFormat();
/**
* @dev Converts a `uint256` to its ASCII `string` decimal representation.
*/
function toString(uint256 value) internal pure returns (string memory) {
unchecked {
uint256 length = Math.log10(value) + 1;
string memory buffer = new string(length);
uint256 ptr;
assembly ("memory-safe") {
ptr := add(add(buffer, 0x20), length)
}
while (true) {
ptr--;
assembly ("memory-safe") {
mstore8(ptr, byte(mod(value, 10), HEX_DIGITS))
}
value /= 10;
if (value == 0) break;
}
return buffer;
}
}
/**
* @dev Converts a `int256` to its ASCII `string` decimal representation.
*/
function toStringSigned(int256 value) internal pure returns (string memory) {
return string.concat(value < 0 ? "-" : "", toString(SignedMath.abs(value)));
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
*/
function toHexString(uint256 value) internal pure returns (string memory) {
unchecked {
return toHexString(value, Math.log256(value) + 1);
}
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
*/
function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
uint256 localValue = value;
bytes memory buffer = new bytes(2 * length + 2);
buffer[0] = "0";
buffer[1] = "x";
for (uint256 i = 2 * length + 1; i > 1; --i) {
buffer[i] = HEX_DIGITS[localValue & 0xf];
localValue >>= 4;
}
if (localValue != 0) {
revert StringsInsufficientHexLength(value, length);
}
return string(buffer);
}
/**
* @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal
* representation.
*/
function toHexString(address addr) internal pure returns (string memory) {
return toHexString(uint256(uint160(addr)), ADDRESS_LENGTH);
}
/**
* @dev Converts an `address` with fixed length of 20 bytes to its checksummed ASCII `string` hexadecimal
* representation, according to EIP-55.
*/
function toChecksumHexString(address addr) internal pure returns (string memory) {
bytes memory buffer = bytes(toHexString(addr));
// hash the hex part of buffer (skip length + 2 bytes, length 40)
uint256 hashValue;
assembly ("memory-safe") {
hashValue := shr(96, keccak256(add(buffer, 0x22), 40))
}
for (uint256 i = 41; i > 1; --i) {
// possible values for buffer[i] are 48 (0) to 57 (9) and 97 (a) to 102 (f)
if (hashValue & 0xf > 7 && uint8(buffer[i]) > 96) {
// case shift by xoring with 0x20
buffer[i] ^= 0x20;
}
hashValue >>= 4;
}
return string(buffer);
}
/**
* @dev Returns true if the two strings are equal.
*/
function equal(string memory a, string memory b) internal pure returns (bool) {
return bytes(a).length == bytes(b).length && keccak256(bytes(a)) == keccak256(bytes(b));
}
/**
* @dev Parse a decimal string and returns the value as a `uint256`.
*
* Requirements:
* - The string must be formatted as `[0-9]*`
* - The result must fit into an `uint256` type
*/
function parseUint(string memory input) internal pure returns (uint256) {
return parseUint(input, 0, bytes(input).length);
}
/**
* @dev Variant of {parseUint-string} that parses a substring of `input` located between position `begin` (included) and
* `end` (excluded).
*
* Requirements:
* - The substring must be formatted as `[0-9]*`
* - The result must fit into an `uint256` type
*/
function parseUint(string memory input, uint256 begin, uint256 end) internal pure returns (uint256) {
(bool success, uint256 value) = tryParseUint(input, begin, end);
if (!success) revert StringsInvalidChar();
return value;
}
/**
* @dev Variant of {parseUint-string} that returns false if the parsing fails because of an invalid character.
*
* NOTE: This function will revert if the result does not fit in a `uint256`.
*/
function tryParseUint(string memory input) internal pure returns (bool success, uint256 value) {
return _tryParseUintUncheckedBounds(input, 0, bytes(input).length);
}
/**
* @dev Variant of {parseUint-string-uint256-uint256} that returns false if the parsing fails because of an invalid
* character.
*
* NOTE: This function will revert if the result does not fit in a `uint256`.
*/
function tryParseUint(
string memory input,
uint256 begin,
uint256 end
) internal pure returns (bool success, uint256 value) {
if (end > bytes(input).length || begin > end) return (false, 0);
return _tryParseUintUncheckedBounds(input, begin, end);
}
/**
* @dev Implementation of {tryParseUint-string-uint256-uint256} that does not check bounds. Caller should make sure that
* `begin <= end <= input.length`. Other inputs would result in undefined behavior.
*/
function _tryParseUintUncheckedBounds(
string memory input,
uint256 begin,
uint256 end
) private pure returns (bool success, uint256 value) {
bytes memory buffer = bytes(input);
uint256 result = 0;
for (uint256 i = begin; i < end; ++i) {
uint8 chr = _tryParseChr(bytes1(_unsafeReadBytesOffset(buffer, i)));
if (chr > 9) return (false, 0);
result *= 10;
result += chr;
}
return (true, result);
}
/**
* @dev Parse a decimal string and returns the value as a `int256`.
*
* Requirements:
* - The string must be formatted as `[-+]?[0-9]*`
* - The result must fit in an `int256` type.
*/
function parseInt(string memory input) internal pure returns (int256) {
return parseInt(input, 0, bytes(input).length);
}
/**
* @dev Variant of {parseInt-string} that parses a substring of `input` located between position `begin` (included) and
* `end` (excluded).
*
* Requirements:
* - The substring must be formatted as `[-+]?[0-9]*`
* - The result must fit in an `int256` type.
*/
function parseInt(string memory input, uint256 begin, uint256 end) internal pure returns (int256) {
(bool success, int256 value) = tryParseInt(input, begin, end);
if (!success) revert StringsInvalidChar();
return value;
}
/**
* @dev Variant of {parseInt-string} that returns false if the parsing fails because of an invalid character or if
* the result does not fit in a `int256`.
*
* NOTE: This function will revert if the absolute value of the result does not fit in a `uint256`.
*/
function tryParseInt(string memory input) internal pure returns (bool success, int256 value) {
return _tryParseIntUncheckedBounds(input, 0, bytes(input).length);
}
uint256 private constant ABS_MIN_INT256 = 2 ** 255;
/**
* @dev Variant of {parseInt-string-uint256-uint256} that returns false if the parsing fails because of an invalid
* character or if the result does not fit in a `int256`.
*
* NOTE: This function will revert if the absolute value of the result does not fit in a `uint256`.
*/
function tryParseInt(
string memory input,
uint256 begin,
uint256 end
) internal pure returns (bool success, int256 value) {
if (end > bytes(input).length || begin > end) return (false, 0);
return _tryParseIntUncheckedBounds(input, begin, end);
}
/**
* @dev Implementation of {tryParseInt-string-uint256-uint256} that does not check bounds. Caller should make sure that
* `begin <= end <= input.length`. Other inputs would result in undefined behavior.
*/
function _tryParseIntUncheckedBounds(
string memory input,
uint256 begin,
uint256 end
) private pure returns (bool success, int256 value) {
bytes memory buffer = bytes(input);
// Check presence of a negative sign.
bytes1 sign = begin == end ? bytes1(0) : bytes1(_unsafeReadBytesOffset(buffer, begin)); // don't do out-of-bound (possibly unsafe) read if sub-string is empty
bool positiveSign = sign == bytes1("+");
bool negativeSign = sign == bytes1("-");
uint256 offset = (positiveSign || negativeSign).toUint();
(bool absSuccess, uint256 absValue) = tryParseUint(input, begin + offset, end);
if (absSuccess && absValue < ABS_MIN_INT256) {
return (true, negativeSign ? -int256(absValue) : int256(absValue));
} else if (absSuccess && negativeSign && absValue == ABS_MIN_INT256) {
return (true, type(int256).min);
} else return (false, 0);
}
/**
* @dev Parse a hexadecimal string (with or without "0x" prefix), and returns the value as a `uint256`.
*
* Requirements:
* - The string must be formatted as `(0x)?[0-9a-fA-F]*`
* - The result must fit in an `uint256` type.
*/
function parseHexUint(string memory input) internal pure returns (uint256) {
return parseHexUint(input, 0, bytes(input).length);
}
/**
* @dev Variant of {parseHexUint-string} that parses a substring of `input` located between position `begin` (included) and
* `end` (excluded).
*
* Requirements:
* - The substring must be formatted as `(0x)?[0-9a-fA-F]*`
* - The result must fit in an `uint256` type.
*/
function parseHexUint(string memory input, uint256 begin, uint256 end) internal pure returns (uint256) {
(bool success, uint256 value) = tryParseHexUint(input, begin, end);
if (!success) revert StringsInvalidChar();
return value;
}
/**
* @dev Variant of {parseHexUint-string} that returns false if the parsing fails because of an invalid character.
*
* NOTE: This function will revert if the result does not fit in a `uint256`.
*/
function tryParseHexUint(string memory input) internal pure returns (bool success, uint256 value) {
return _tryParseHexUintUncheckedBounds(input, 0, bytes(input).length);
}
/**
* @dev Variant of {parseHexUint-string-uint256-uint256} that returns false if the parsing fails because of an
* invalid character.
*
* NOTE: This function will revert if the result does not fit in a `uint256`.
*/
function tryParseHexUint(
string memory input,
uint256 begin,
uint256 end
) internal pure returns (bool success, uint256 value) {
if (end > bytes(input).length || begin > end) return (false, 0);
return _tryParseHexUintUncheckedBounds(input, begin, end);
}
/**
* @dev Implementation of {tryParseHexUint-string-uint256-uint256} that does not check bounds. Caller should make sure that
* `begin <= end <= input.length`. Other inputs would result in undefined behavior.
*/
function _tryParseHexUintUncheckedBounds(
string memory input,
uint256 begin,
uint256 end
) private pure returns (bool success, uint256 value) {
bytes memory buffer = bytes(input);
// skip 0x prefix if present
bool hasPrefix = (end > begin + 1) && bytes2(_unsafeReadBytesOffset(buffer, begin)) == bytes2("0x"); // don't do out-of-bound (possibly unsafe) read if sub-string is empty
uint256 offset = hasPrefix.toUint() * 2;
uint256 result = 0;
for (uint256 i = begin + offset; i < end; ++i) {
uint8 chr = _tryParseChr(bytes1(_unsafeReadBytesOffset(buffer, i)));
if (chr > 15) return (false, 0);
result *= 16;
unchecked {
// Multiplying by 16 is equivalent to a shift of 4 bits (with additional overflow check).
// This guarantees that adding a value < 16 will not cause an overflow, hence the unchecked.
result += chr;
}
}
return (true, result);
}
/**
* @dev Parse a hexadecimal string (with or without "0x" prefix), and returns the value as an `address`.
*
* Requirements:
* - The string must be formatted as `(0x)?[0-9a-fA-F]{40}`
*/
function parseAddress(string memory input) internal pure returns (address) {
return parseAddress(input, 0, bytes(input).length);
}
/**
* @dev Variant of {parseAddress-string} that parses a substring of `input` located between position `begin` (included) and
* `end` (excluded).
*
* Requirements:
* - The substring must be formatted as `(0x)?[0-9a-fA-F]{40}`
*/
function parseAddress(string memory input, uint256 begin, uint256 end) internal pure returns (address) {
(bool success, address value) = tryParseAddress(input, begin, end);
if (!success) revert StringsInvalidAddressFormat();
return value;
}
/**
* @dev Variant of {parseAddress-string} that returns false if the parsing fails because the input is not a properly
* formatted address. See {parseAddress-string} requirements.
*/
function tryParseAddress(string memory input) internal pure returns (bool success, address value) {
return tryParseAddress(input, 0, bytes(input).length);
}
/**
* @dev Variant of {parseAddress-string-uint256-uint256} that returns false if the parsing fails because input is not a properly
* formatted address. See {parseAddress-string-uint256-uint256} requirements.
*/
function tryParseAddress(
string memory input,
uint256 begin,
uint256 end
) internal pure returns (bool success, address value) {
if (end > bytes(input).length || begin > end) return (false, address(0));
bool hasPrefix = (end > begin + 1) && bytes2(_unsafeReadBytesOffset(bytes(input), begin)) == bytes2("0x"); // don't do out-of-bound (possibly unsafe) read if sub-string is empty
uint256 expectedLength = 40 + hasPrefix.toUint() * 2;
// check that input is the correct length
if (end - begin == expectedLength) {
// length guarantees that this does not overflow, and value is at most type(uint160).max
(bool s, uint256 v) = _tryParseHexUintUncheckedBounds(input, begin, end);
return (s, address(uint160(v)));
} else {
return (false, address(0));
}
}
function _tryParseChr(bytes1 chr) private pure returns (uint8) {
uint8 value = uint8(chr);
// Try to parse `chr`:
// - Case 1: [0-9]
// - Case 2: [a-f]
// - Case 3: [A-F]
// - otherwise not supported
unchecked {
if (value > 47 && value < 58) value -= 48;
else if (value > 96 && value < 103) value -= 87;
else if (value > 64 && value < 71) value -= 55;
else return type(uint8).max;
}
return value;
}
/**
* @dev Escape special characters in JSON strings. This can be useful to prevent JSON injection in NFT metadata.
*
* WARNING: This function should only be used in double quoted JSON strings. Single quotes are not escaped.
*
* NOTE: This function escapes all unicode characters, and not just the ones in ranges defined in section 2.5 of
* RFC-4627 (U+0000 to U+001F, U+0022 and U+005C). ECMAScript's `JSON.parse` does recover escaped unicode
* characters that are not in this range, but other tooling may provide different results.
*/
function escapeJSON(string memory input) internal pure returns (string memory) {
bytes memory buffer = bytes(input);
bytes memory output = new bytes(2 * buffer.length); // worst case scenario
uint256 outputLength = 0;
for (uint256 i; i < buffer.length; ++i) {
bytes1 char = bytes1(_unsafeReadBytesOffset(buffer, i));
if (((SPECIAL_CHARS_LOOKUP & (1 << uint8(char))) != 0)) {
output[outputLength++] = "\\";
if (char == 0x08) output[outputLength++] = "b";
else if (char == 0x09) output[outputLength++] = "t";
else if (char == 0x0a) output[outputLength++] = "n";
else if (char == 0x0c) output[outputLength++] = "f";
else if (char == 0x0d) output[outputLength++] = "r";
else if (char == 0x5c) output[outputLength++] = "\\";
else if (char == 0x22) {
// solhint-disable-next-line quotes
output[outputLength++] = '"';
}
} else {
output[outputLength++] = char;
}
}
// write the actual length and deallocate unused memory
assembly ("memory-safe") {
mstore(output, outputLength)
mstore(0x40, add(output, shl(5, shr(5, add(outputLength, 63)))))
}
return string(output);
}
/**
* @dev Reads a bytes32 from a bytes array without bounds checking.
*
* NOTE: making this function internal would mean it could be used with memory unsafe offset, and marking the
* assembly block as such would prevent some optimizations.
*/
function _unsafeReadBytesOffset(bytes memory buffer, uint256 offset) private pure returns (bytes32 value) {
// This is not memory safe in the general case, but all calls to this private function are within bounds.
assembly ("memory-safe") {
value := mload(add(add(buffer, 0x20), offset))
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (utils/structs/Checkpoints.sol)
// This file was procedurally generated from scripts/generate/templates/Checkpoints.js.
pragma solidity ^0.8.20;
import {Math} from "../math/Math.sol";
/**
* @dev This library defines the `Trace*` struct, for checkpointing values as they change at different points in
* time, and later looking up past values by block number. See {Votes} as an example.
*
* To create a history of checkpoints define a variable type `Checkpoints.Trace*` in your contract, and store a new
* checkpoint for the current transaction block using the {push} function.
*/
library Checkpoints {
/**
* @dev A value was attempted to be inserted on a past checkpoint.
*/
error CheckpointUnorderedInsertion();
struct Trace224 {
Checkpoint224[] _checkpoints;
}
struct Checkpoint224 {
uint32 _key;
uint224 _value;
}
/**
* @dev Pushes a (`key`, `value`) pair into a Trace224 so that it is stored as the checkpoint.
*
* Returns previous value and new value.
*
* IMPORTANT: Never accept `key` as a user input, since an arbitrary `type(uint32).max` key set will disable the
* library.
*/
function push(
Trace224 storage self,
uint32 key,
uint224 value
) internal returns (uint224 oldValue, uint224 newValue) {
return _insert(self._checkpoints, key, value);
}
/**
* @dev Returns the value in the first (oldest) checkpoint with key greater or equal than the search key, or zero if
* there is none.
*/
function lowerLookup(Trace224 storage self, uint32 key) internal view returns (uint224) {
uint256 len = self._checkpoints.length;
uint256 pos = _lowerBinaryLookup(self._checkpoints, key, 0, len);
return pos == len ? 0 : _unsafeAccess(self._checkpoints, pos)._value;
}
/**
* @dev Returns the value in the last (most recent) checkpoint with key lower or equal than the search key, or zero
* if there is none.
*/
function upperLookup(Trace224 storage self, uint32 key) internal view returns (uint224) {
uint256 len = self._checkpoints.length;
uint256 pos = _upperBinaryLookup(self._checkpoints, key, 0, len);
return pos == 0 ? 0 : _unsafeAccess(self._checkpoints, pos - 1)._value;
}
/**
* @dev Returns the value in the last (most recent) checkpoint with key lower or equal than the search key, or zero
* if there is none.
*
* NOTE: This is a variant of {upperLookup} that is optimized to find "recent" checkpoint (checkpoints with high
* keys).
*/
function upperLookupRecent(Trace224 storage self, uint32 key) internal view returns (uint224) {
uint256 len = self._checkpoints.length;
uint256 low = 0;
uint256 high = len;
if (len > 5) {
uint256 mid = len - Math.sqrt(len);
if (key < _unsafeAccess(self._checkpoints, mid)._key) {
high = mid;
} else {
low = mid + 1;
}
}
uint256 pos = _upperBinaryLookup(self._checkpoints, key, low, high);
return pos == 0 ? 0 : _unsafeAccess(self._checkpoints, pos - 1)._value;
}
/**
* @dev Returns the value in the most recent checkpoint, or zero if there are no checkpoints.
*/
function latest(Trace224 storage self) internal view returns (uint224) {
uint256 pos = self._checkpoints.length;
return pos == 0 ? 0 : _unsafeAccess(self._checkpoints, pos - 1)._value;
}
/**
* @dev Returns whether there is a checkpoint in the structure (i.e. it is not empty), and if so the key and value
* in the most recent checkpoint.
*/
function latestCheckpoint(Trace224 storage self) internal view returns (bool exists, uint32 _key, uint224 _value) {
uint256 pos = self._checkpoints.length;
if (pos == 0) {
return (false, 0, 0);
} else {
Checkpoint224 storage ckpt = _unsafeAccess(self._checkpoints, pos - 1);
return (true, ckpt._key, ckpt._value);
}
}
/**
* @dev Returns the number of checkpoints.
*/
function length(Trace224 storage self) internal view returns (uint256) {
return self._checkpoints.length;
}
/**
* @dev Returns checkpoint at given position.
*/
function at(Trace224 storage self, uint32 pos) internal view returns (Checkpoint224 memory) {
return self._checkpoints[pos];
}
/**
* @dev Pushes a (`key`, `value`) pair into an ordered list of checkpoints, either by inserting a new checkpoint,
* or by updating the last one.
*/
function _insert(
Checkpoint224[] storage self,
uint32 key,
uint224 value
) private returns (uint224 oldValue, uint224 newValue) {
uint256 pos = self.length;
if (pos > 0) {
Checkpoint224 storage last = _unsafeAccess(self, pos - 1);
uint32 lastKey = last._key;
uint224 lastValue = last._value;
// Checkpoint keys must be non-decreasing.
if (lastKey > key) {
revert CheckpointUnorderedInsertion();
}
// Update or push new checkpoint
if (lastKey == key) {
last._value = value;
} else {
self.push(Checkpoint224({_key: key, _value: value}));
}
return (lastValue, value);
} else {
self.push(Checkpoint224({_key: key, _value: value}));
return (0, value);
}
}
/**
* @dev Return the index of the first (oldest) checkpoint with key strictly bigger than the search key, or `high`
* if there is none. `low` and `high` define a section where to do the search, with inclusive `low` and exclusive
* `high`.
*
* WARNING: `high` should not be greater than the array's length.
*/
function _upperBinaryLookup(
Checkpoint224[] storage self,
uint32 key,
uint256 low,
uint256 high
) private view returns (uint256) {
while (low < high) {
uint256 mid = Math.average(low, high);
if (_unsafeAccess(self, mid)._key > key) {
high = mid;
} else {
low = mid + 1;
}
}
return high;
}
/**
* @dev Return the index of the first (oldest) checkpoint with key greater or equal than the search key, or `high`
* if there is none. `low` and `high` define a section where to do the search, with inclusive `low` and exclusive
* `high`.
*
* WARNING: `high` should not be greater than the array's length.
*/
function _lowerBinaryLookup(
Checkpoint224[] storage self,
uint32 key,
uint256 low,
uint256 high
) private view returns (uint256) {
while (low < high) {
uint256 mid = Math.average(low, high);
if (_unsafeAccess(self, mid)._key < key) {
low = mid + 1;
} else {
high = mid;
}
}
return high;
}
/**
* @dev Access an element of the array without performing bounds check. The position is assumed to be within bounds.
*/
function _unsafeAccess(
Checkpoint224[] storage self,
uint256 pos
) private pure returns (Checkpoint224 storage result) {
assembly {
mstore(0, self.slot)
result.slot := add(keccak256(0, 0x20), pos)
}
}
struct Trace208 {
Checkpoint208[] _checkpoints;
}
struct Checkpoint208 {
uint48 _key;
uint208 _value;
}
/**
* @dev Pushes a (`key`, `value`) pair into a Trace208 so that it is stored as the checkpoint.
*
* Returns previous value and new value.
*
* IMPORTANT: Never accept `key` as a user input, since an arbitrary `type(uint48).max` key set will disable the
* library.
*/
function push(
Trace208 storage self,
uint48 key,
uint208 value
) internal returns (uint208 oldValue, uint208 newValue) {
return _insert(self._checkpoints, key, value);
}
/**
* @dev Returns the value in the first (oldest) checkpoint with key greater or equal than the search key, or zero if
* there is none.
*/
function lowerLookup(Trace208 storage self, uint48 key) internal view returns (uint208) {
uint256 len = self._checkpoints.length;
uint256 pos = _lowerBinaryLookup(self._checkpoints, key, 0, len);
return pos == len ? 0 : _unsafeAccess(self._checkpoints, pos)._value;
}
/**
* @dev Returns the value in the last (most recent) checkpoint with key lower or equal than the search key, or zero
* if there is none.
*/
function upperLookup(Trace208 storage self, uint48 key) internal view returns (uint208) {
uint256 len = self._checkpoints.length;
uint256 pos = _upperBinaryLookup(self._checkpoints, key, 0, len);
return pos == 0 ? 0 : _unsafeAccess(self._checkpoints, pos - 1)._value;
}
/**
* @dev Returns the value in the last (most recent) checkpoint with key lower or equal than the search key, or zero
* if there is none.
*
* NOTE: This is a variant of {upperLookup} that is optimized to find "recent" checkpoint (checkpoints with high
* keys).
*/
function upperLookupRecent(Trace208 storage self, uint48 key) internal view returns (uint208) {
uint256 len = self._checkpoints.length;
uint256 low = 0;
uint256 high = len;
if (len > 5) {
uint256 mid = len - Math.sqrt(len);
if (key < _unsafeAccess(self._checkpoints, mid)._key) {
high = mid;
} else {
low = mid + 1;
}
}
uint256 pos = _upperBinaryLookup(self._checkpoints, key, low, high);
return pos == 0 ? 0 : _unsafeAccess(self._checkpoints, pos - 1)._value;
}
/**
* @dev Returns the value in the most recent checkpoint, or zero if there are no checkpoints.
*/
function latest(Trace208 storage self) internal view returns (uint208) {
uint256 pos = self._checkpoints.length;
return pos == 0 ? 0 : _unsafeAccess(self._checkpoints, pos - 1)._value;
}
/**
* @dev Returns whether there is a checkpoint in the structure (i.e. it is not empty), and if so the key and value
* in the most recent checkpoint.
*/
function latestCheckpoint(Trace208 storage self) internal view returns (bool exists, uint48 _key, uint208 _value) {
uint256 pos = self._checkpoints.length;
if (pos == 0) {
return (false, 0, 0);
} else {
Checkpoint208 storage ckpt = _unsafeAccess(self._checkpoints, pos - 1);
return (true, ckpt._key, ckpt._value);
}
}
/**
* @dev Returns the number of checkpoints.
*/
function length(Trace208 storage self) internal view returns (uint256) {
return self._checkpoints.length;
}
/**
* @dev Returns checkpoint at given position.
*/
function at(Trace208 storage self, uint32 pos) internal view returns (Checkpoint208 memory) {
return self._checkpoints[pos];
}
/**
* @dev Pushes a (`key`, `value`) pair into an ordered list of checkpoints, either by inserting a new checkpoint,
* or by updating the last one.
*/
function _insert(
Checkpoint208[] storage self,
uint48 key,
uint208 value
) private returns (uint208 oldValue, uint208 newValue) {
uint256 pos = self.length;
if (pos > 0) {
Checkpoint208 storage last = _unsafeAccess(self, pos - 1);
uint48 lastKey = last._key;
uint208 lastValue = last._value;
// Checkpoint keys must be non-decreasing.
if (lastKey > key) {
revert CheckpointUnorderedInsertion();
}
// Update or push new checkpoint
if (lastKey == key) {
last._value = value;
} else {
self.push(Checkpoint208({_key: key, _value: value}));
}
return (lastValue, value);
} else {
self.push(Checkpoint208({_key: key, _value: value}));
return (0, value);
}
}
/**
* @dev Return the index of the first (oldest) checkpoint with key strictly bigger than the search key, or `high`
* if there is none. `low` and `high` define a section where to do the search, with inclusive `low` and exclusive
* `high`.
*
* WARNING: `high` should not be greater than the array's length.
*/
function _upperBinaryLookup(
Checkpoint208[] storage self,
uint48 key,
uint256 low,
uint256 high
) private view returns (uint256) {
while (low < high) {
uint256 mid = Math.average(low, high);
if (_unsafeAccess(self, mid)._key > key) {
high = mid;
} else {
low = mid + 1;
}
}
return high;
}
/**
* @dev Return the index of the first (oldest) checkpoint with key greater or equal than the search key, or `high`
* if there is none. `low` and `high` define a section where to do the search, with inclusive `low` and exclusive
* `high`.
*
* WARNING: `high` should not be greater than the array's length.
*/
function _lowerBinaryLookup(
Checkpoint208[] storage self,
uint48 key,
uint256 low,
uint256 high
) private view returns (uint256) {
while (low < high) {
uint256 mid = Math.average(low, high);
if (_unsafeAccess(self, mid)._key < key) {
low = mid + 1;
} else {
high = mid;
}
}
return high;
}
/**
* @dev Access an element of the array without performing bounds check. The position is assumed to be within bounds.
*/
function _unsafeAccess(
Checkpoint208[] storage self,
uint256 pos
) private pure returns (Checkpoint208 storage result) {
assembly {
mstore(0, self.slot)
result.slot := add(keccak256(0, 0x20), pos)
}
}
struct Trace160 {
Checkpoint160[] _checkpoints;
}
struct Checkpoint160 {
uint96 _key;
uint160 _value;
}
/**
* @dev Pushes a (`key`, `value`) pair into a Trace160 so that it is stored as the checkpoint.
*
* Returns previous value and new value.
*
* IMPORTANT: Never accept `key` as a user input, since an arbitrary `type(uint96).max` key set will disable the
* library.
*/
function push(
Trace160 storage self,
uint96 key,
uint160 value
) internal returns (uint160 oldValue, uint160 newValue) {
return _insert(self._checkpoints, key, value);
}
/**
* @dev Returns the value in the first (oldest) checkpoint with key greater or equal than the search key, or zero if
* there is none.
*/
function lowerLookup(Trace160 storage self, uint96 key) internal view returns (uint160) {
uint256 len = self._checkpoints.length;
uint256 pos = _lowerBinaryLookup(self._checkpoints, key, 0, len);
return pos == len ? 0 : _unsafeAccess(self._checkpoints, pos)._value;
}
/**
* @dev Returns the value in the last (most recent) checkpoint with key lower or equal than the search key, or zero
* if there is none.
*/
function upperLookup(Trace160 storage self, uint96 key) internal view returns (uint160) {
uint256 len = self._checkpoints.length;
uint256 pos = _upperBinaryLookup(self._checkpoints, key, 0, len);
return pos == 0 ? 0 : _unsafeAccess(self._checkpoints, pos - 1)._value;
}
/**
* @dev Returns the value in the last (most recent) checkpoint with key lower or equal than the search key, or zero
* if there is none.
*
* NOTE: This is a variant of {upperLookup} that is optimized to find "recent" checkpoint (checkpoints with high
* keys).
*/
function upperLookupRecent(Trace160 storage self, uint96 key) internal view returns (uint160) {
uint256 len = self._checkpoints.length;
uint256 low = 0;
uint256 high = len;
if (len > 5) {
uint256 mid = len - Math.sqrt(len);
if (key < _unsafeAccess(self._checkpoints, mid)._key) {
high = mid;
} else {
low = mid + 1;
}
}
uint256 pos = _upperBinaryLookup(self._checkpoints, key, low, high);
return pos == 0 ? 0 : _unsafeAccess(self._checkpoints, pos - 1)._value;
}
/**
* @dev Returns the value in the most recent checkpoint, or zero if there are no checkpoints.
*/
function latest(Trace160 storage self) internal view returns (uint160) {
uint256 pos = self._checkpoints.length;
return pos == 0 ? 0 : _unsafeAccess(self._checkpoints, pos - 1)._value;
}
/**
* @dev Returns whether there is a checkpoint in the structure (i.e. it is not empty), and if so the key and value
* in the most recent checkpoint.
*/
function latestCheckpoint(Trace160 storage self) internal view returns (bool exists, uint96 _key, uint160 _value) {
uint256 pos = self._checkpoints.length;
if (pos == 0) {
return (false, 0, 0);
} else {
Checkpoint160 storage ckpt = _unsafeAccess(self._checkpoints, pos - 1);
return (true, ckpt._key, ckpt._value);
}
}
/**
* @dev Returns the number of checkpoints.
*/
function length(Trace160 storage self) internal view returns (uint256) {
return self._checkpoints.length;
}
/**
* @dev Returns checkpoint at given position.
*/
function at(Trace160 storage self, uint32 pos) internal view returns (Checkpoint160 memory) {
return self._checkpoints[pos];
}
/**
* @dev Pushes a (`key`, `value`) pair into an ordered list of checkpoints, either by inserting a new checkpoint,
* or by updating the last one.
*/
function _insert(
Checkpoint160[] storage self,
uint96 key,
uint160 value
) private returns (uint160 oldValue, uint160 newValue) {
uint256 pos = self.length;
if (pos > 0) {
Checkpoint160 storage last = _unsafeAccess(self, pos - 1);
uint96 lastKey = last._key;
uint160 lastValue = last._value;
// Checkpoint keys must be non-decreasing.
if (lastKey > key) {
revert CheckpointUnorderedInsertion();
}
// Update or push new checkpoint
if (lastKey == key) {
last._value = value;
} else {
self.push(Checkpoint160({_key: key, _value: value}));
}
return (lastValue, value);
} else {
self.push(Checkpoint160({_key: key, _value: value}));
return (0, value);
}
}
/**
* @dev Return the index of the first (oldest) checkpoint with key strictly bigger than the search key, or `high`
* if there is none. `low` and `high` define a section where to do the search, with inclusive `low` and exclusive
* `high`.
*
* WARNING: `high` should not be greater than the array's length.
*/
function _upperBinaryLookup(
Checkpoint160[] storage self,
uint96 key,
uint256 low,
uint256 high
) private view returns (uint256) {
while (low < high) {
uint256 mid = Math.average(low, high);
if (_unsafeAccess(self, mid)._key > key) {
high = mid;
} else {
low = mid + 1;
}
}
return high;
}
/**
* @dev Return the index of the first (oldest) checkpoint with key greater or equal than the search key, or `high`
* if there is none. `low` and `high` define a section where to do the search, with inclusive `low` and exclusive
* `high`.
*
* WARNING: `high` should not be greater than the array's length.
*/
function _lowerBinaryLookup(
Checkpoint160[] storage self,
uint96 key,
uint256 low,
uint256 high
) private view returns (uint256) {
while (low < high) {
uint256 mid = Math.average(low, high);
if (_unsafeAccess(self, mid)._key < key) {
low = mid + 1;
} else {
high = mid;
}
}
return high;
}
/**
* @dev Access an element of the array without performing bounds check. The position is assumed to be within bounds.
*/
function _unsafeAccess(
Checkpoint160[] storage self,
uint256 pos
) private pure returns (Checkpoint160 storage result) {
assembly {
mstore(0, self.slot)
result.slot := add(keccak256(0, 0x20), pos)
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/structs/DoubleEndedQueue.sol)
pragma solidity ^0.8.20;
import {Panic} from "../Panic.sol";
/**
* @dev A sequence of items with the ability to efficiently push and pop items (i.e. insert and remove) on both ends of
* the sequence (called front and back). Among other access patterns, it can be used to implement efficient LIFO and
* FIFO queues. Storage use is optimized, and all operations are O(1) constant time. This includes {clear}, given that
* the existing queue contents are left in storage.
*
* The struct is called `Bytes32Deque`. Other types can be cast to and from `bytes32`. This data structure can only be
* used in storage, and not in memory.
* ```solidity
* DoubleEndedQueue.Bytes32Deque queue;
* ```
*/
library DoubleEndedQueue {
/**
* @dev Indices are 128 bits so begin and end are packed in a single storage slot for efficient access.
*
* Struct members have an underscore prefix indicating that they are "private" and should not be read or written to
* directly. Use the functions provided below instead. Modifying the struct manually may violate assumptions and
* lead to unexpected behavior.
*
* The first item is at data[begin] and the last item is at data[end - 1]. This range can wrap around.
*/
struct Bytes32Deque {
uint128 _begin;
uint128 _end;
mapping(uint128 index => bytes32) _data;
}
/**
* @dev Inserts an item at the end of the queue.
*
* Reverts with {Panic-RESOURCE_ERROR} if the queue is full.
*/
function pushBack(Bytes32Deque storage deque, bytes32 value) internal {
unchecked {
uint128 backIndex = deque._end;
if (backIndex + 1 == deque._begin) Panic.panic(Panic.RESOURCE_ERROR);
deque._data[backIndex] = value;
deque._end = backIndex + 1;
}
}
/**
* @dev Removes the item at the end of the queue and returns it.
*
* Reverts with {Panic-EMPTY_ARRAY_POP} if the queue is empty.
*/
function popBack(Bytes32Deque storage deque) internal returns (bytes32 value) {
unchecked {
uint128 backIndex = deque._end;
if (backIndex == deque._begin) Panic.panic(Panic.EMPTY_ARRAY_POP);
--backIndex;
value = deque._data[backIndex];
delete deque._data[backIndex];
deque._end = backIndex;
}
}
/**
* @dev Inserts an item at the beginning of the queue.
*
* Reverts with {Panic-RESOURCE_ERROR} if the queue is full.
*/
function pushFront(Bytes32Deque storage deque, bytes32 value) internal {
unchecked {
uint128 frontIndex = deque._begin - 1;
if (frontIndex == deque._end) Panic.panic(Panic.RESOURCE_ERROR);
deque._data[frontIndex] = value;
deque._begin = frontIndex;
}
}
/**
* @dev Removes the item at the beginning of the queue and returns it.
*
* Reverts with {Panic-EMPTY_ARRAY_POP} if the queue is empty.
*/
function popFront(Bytes32Deque storage deque) internal returns (bytes32 value) {
unchecked {
uint128 frontIndex = deque._begin;
if (frontIndex == deque._end) Panic.panic(Panic.EMPTY_ARRAY_POP);
value = deque._data[frontIndex];
delete deque._data[frontIndex];
deque._begin = frontIndex + 1;
}
}
/**
* @dev Returns the item at the beginning of the queue.
*
* Reverts with {Panic-ARRAY_OUT_OF_BOUNDS} if the queue is empty.
*/
function front(Bytes32Deque storage deque) internal view returns (bytes32 value) {
if (empty(deque)) Panic.panic(Panic.ARRAY_OUT_OF_BOUNDS);
return deque._data[deque._begin];
}
/**
* @dev Returns the item at the end of the queue.
*
* Reverts with {Panic-ARRAY_OUT_OF_BOUNDS} if the queue is empty.
*/
function back(Bytes32Deque storage deque) internal view returns (bytes32 value) {
if (empty(deque)) Panic.panic(Panic.ARRAY_OUT_OF_BOUNDS);
unchecked {
return deque._data[deque._end - 1];
}
}
/**
* @dev Return the item at a position in the queue given by `index`, with the first item at 0 and last item at
* `length(deque) - 1`.
*
* Reverts with {Panic-ARRAY_OUT_OF_BOUNDS} if the index is out of bounds.
*/
function at(Bytes32Deque storage deque, uint256 index) internal view returns (bytes32 value) {
if (index >= length(deque)) Panic.panic(Panic.ARRAY_OUT_OF_BOUNDS);
// By construction, length is a uint128, so the check above ensures that index can be safely downcast to uint128
unchecked {
return deque._data[deque._begin + uint128(index)];
}
}
/**
* @dev Resets the queue back to being empty.
*
* NOTE: The current items are left behind in storage. This does not affect the functioning of the queue, but misses
* out on potential gas refunds.
*/
function clear(Bytes32Deque storage deque) internal {
deque._begin = 0;
deque._end = 0;
}
/**
* @dev Returns the number of items in the queue.
*/
function length(Bytes32Deque storage deque) internal view returns (uint256) {
unchecked {
return uint256(deque._end - deque._begin);
}
}
/**
* @dev Returns true if the queue is empty.
*/
function empty(Bytes32Deque storage deque) internal view returns (bool) {
return deque._end == deque._begin;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/types/Time.sol)
pragma solidity ^0.8.20;
import {Math} from "../math/Math.sol";
import {SafeCast} from "../math/SafeCast.sol";
/**
* @dev This library provides helpers for manipulating time-related objects.
*
* It uses the following types:
* - `uint48` for timepoints
* - `uint32` for durations
*
* While the library doesn't provide specific types for timepoints and duration, it does provide:
* - a `Delay` type to represent duration that can be programmed to change value automatically at a given point
* - additional helper functions
*/
library Time {
using Time for *;
/**
* @dev Get the block timestamp as a Timepoint.
*/
function timestamp() internal view returns (uint48) {
return SafeCast.toUint48(block.timestamp);
}
/**
* @dev Get the block number as a Timepoint.
*/
function blockNumber() internal view returns (uint48) {
return SafeCast.toUint48(block.number);
}
// ==================================================== Delay =====================================================
/**
* @dev A `Delay` is a uint32 duration that can be programmed to change value automatically at a given point in the
* future. The "effect" timepoint describes when the transitions happens from the "old" value to the "new" value.
* This allows updating the delay applied to some operation while keeping some guarantees.
*
* In particular, the {update} function guarantees that if the delay is reduced, the old delay still applies for
* some time. For example if the delay is currently 7 days to do an upgrade, the admin should not be able to set
* the delay to 0 and upgrade immediately. If the admin wants to reduce the delay, the old delay (7 days) should
* still apply for some time.
*
*
* The `Delay` type is 112 bits long, and packs the following:
*
* ```
* | [uint48]: effect date (timepoint)
* | | [uint32]: value before (duration)
* ↓ ↓ ↓ [uint32]: value after (duration)
* 0xAAAAAAAAAAAABBBBBBBBCCCCCCCC
* ```
*
* NOTE: The {get} and {withUpdate} functions operate using timestamps. Block number based delays are not currently
* supported.
*/
type Delay is uint112;
/**
* @dev Wrap a duration into a Delay to add the one-step "update in the future" feature
*/
function toDelay(uint32 duration) internal pure returns (Delay) {
return Delay.wrap(duration);
}
/**
* @dev Get the value at a given timepoint plus the pending value and effect timepoint if there is a scheduled
* change after this timepoint. If the effect timepoint is 0, then the pending value should not be considered.
*/
function _getFullAt(
Delay self,
uint48 timepoint
) private pure returns (uint32 valueBefore, uint32 valueAfter, uint48 effect) {
(valueBefore, valueAfter, effect) = self.unpack();
return effect <= timepoint ? (valueAfter, 0, 0) : (valueBefore, valueAfter, effect);
}
/**
* @dev Get the current value plus the pending value and effect timepoint if there is a scheduled change. If the
* effect timepoint is 0, then the pending value should not be considered.
*/
function getFull(Delay self) internal view returns (uint32 valueBefore, uint32 valueAfter, uint48 effect) {
return _getFullAt(self, timestamp());
}
/**
* @dev Get the current value.
*/
function get(Delay self) internal view returns (uint32) {
(uint32 delay, , ) = self.getFull();
return delay;
}
/**
* @dev Update a Delay object so that it takes a new duration after a timepoint that is automatically computed to
* enforce the old delay at the moment of the update. Returns the updated Delay object and the timestamp when the
* new delay becomes effective.
*/
function withUpdate(
Delay self,
uint32 newValue,
uint32 minSetback
) internal view returns (Delay updatedDelay, uint48 effect) {
uint32 value = self.get();
uint32 setback = uint32(Math.max(minSetback, value > newValue ? value - newValue : 0));
effect = timestamp() + setback;
return (pack(value, newValue, effect), effect);
}
/**
* @dev Split a delay into its components: valueBefore, valueAfter and effect (transition timepoint).
*/
function unpack(Delay self) internal pure returns (uint32 valueBefore, uint32 valueAfter, uint48 effect) {
uint112 raw = Delay.unwrap(self);
valueAfter = uint32(raw);
valueBefore = uint32(raw >> 32);
effect = uint48(raw >> 64);
return (valueBefore, valueAfter, effect);
}
/**
* @dev pack the components into a Delay object.
*/
function pack(uint32 valueBefore, uint32 valueAfter, uint48 effect) internal pure returns (Delay) {
return Delay.wrap((uint112(effect) << 64) | (uint112(valueBefore) << 32) | uint112(valueAfter));
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.28;
import "@openzeppelin/contracts/governance/TimelockController.sol";
import "@openzeppelin/contracts-upgradeable/governance/TimelockControllerUpgradeable.sol";
import "@openzeppelin/contracts/proxy/Clones.sol";
import "./DAOToken.sol";
import "./DAOGovernor.sol";
/**
* @title DAOFactory
* @notice Factory contract for deploying complete DAO governance systems
* @dev Deploys and configures: DAOToken and DAOGovernor (via minimal proxy), TimelockController (treasury)
*
* Architecture:
* - Token: ERC20Votes with auto-delegation, deployed as EIP-1167 minimal proxy
* - Governor: Controls treasury via proposals, deployed as EIP-1167 minimal proxy
* - Treasury: TimelockController holds 99% of tokens
* - Creator: Receives 1% of tokens (auto-delegated, can immediately vote)
*
* Gas Optimization:
* - DAOToken and DAOGovernor use minimal proxy pattern (EIP-1167)
* - Each proxy deployment costs ~45k gas instead of ~2M gas for full contracts
* - Implementation contracts are deployed once in constructor
* - Uses custom errors instead of require strings for reduced bytecode
*/
contract DAOFactory {
// ============ Custom Errors ============
/// @notice Thrown when totalSupply is zero
error InvalidTotalSupply();
/// @notice Thrown when daoName is empty
error EmptyDAOName();
/// @notice Thrown when tokenName is empty
error EmptyTokenName();
/// @notice Thrown when tokenSymbol is empty
error EmptyTokenSymbol();
/// @notice Thrown when votingPeriod is zero
error InvalidVotingPeriod();
/// @notice Thrown when index is out of bounds
error IndexOutOfBounds();
/// @notice Fixed timelock delay: 1 day
uint256 public constant TIMELOCK_MIN_DELAY = 1 days;
/// @notice Percentage of tokens sent to creator (1%)
uint256 public constant CREATOR_ALLOCATION_PERCENT = 1;
/// @notice The DAOToken implementation contract address (for cloning)
address public immutable tokenImplementation;
/// @notice The DAOGovernor implementation contract address (for cloning)
address public immutable governorImplementation;
/// @notice Emitted when a new DAO is created
event DAOCreated(
address indexed creator,
address indexed token,
address indexed governor,
address timelock,
string daoName,
string tokenName,
string tokenSymbol,
uint256 totalSupply
);
/// @notice Struct to hold DAO deployment info
struct DAOInfo {
address token;
address timelock;
address governor;
address creator;
string daoName;
uint256 createdAt;
}
/// @notice Struct for createDAO parameters to avoid stack too deep
struct CreateDAOParams {
string daoName;
string tokenName;
string tokenSymbol;
uint256 totalSupply;
uint48 votingDelay;
uint32 votingPeriod;
}
/// @notice Array of all deployed DAOs
DAOInfo[] public deployedDAOs;
/// @notice Mapping from creator to their DAOs
mapping(address => DAOInfo[]) public creatorDAOs;
/**
* @notice Deploys the DAOToken and DAOGovernor implementations for cloning
* @dev Implementation contracts are never initialized - only clones are
*/
constructor() {
tokenImplementation = address(new DAOToken());
governorImplementation = address(new DAOGovernor());
}
/**
* @notice Creates a new DAO with governance token, timelock treasury, and governor
* @param params CreateDAOParams struct containing:
* - daoName: Name of the DAO (used for Governor)
* - tokenName: Name of the governance token
* - tokenSymbol: Symbol of the governance token
* - totalSupply: Total token supply in wei (e.g., 1000000 * 10^18 for 1M tokens)
* - votingDelay: Delay in seconds before voting starts (e.g., 86400 for 1 day)
* - votingPeriod: Duration in seconds for voting (e.g., 604800 for 1 week)
* @return token Address of deployed DAOToken (proxy)
* @return timelock Address of deployed TimelockController (treasury)
* @return governor Address of deployed DAOGovernor (proxy)
*/
function createDAO(
CreateDAOParams calldata params
) external returns (address token, address timelock, address governor) {
if (params.totalSupply == 0) revert InvalidTotalSupply();
if (bytes(params.daoName).length == 0) revert EmptyDAOName();
if (bytes(params.tokenName).length == 0) revert EmptyTokenName();
if (bytes(params.tokenSymbol).length == 0) revert EmptyTokenSymbol();
if (params.votingPeriod == 0) revert InvalidVotingPeriod();
// Deploy all contracts
(token, timelock, governor) = _deployContracts(params);
// Configure timelock roles
_configureTimelock(TimelockController(payable(timelock)), governor);
// Distribute tokens
_distributeTokens(DAOToken(token), timelock, params.totalSupply);
// Record DAO info
_recordDAO(token, timelock, governor, params.daoName);
// Emit event
emit DAOCreated(
msg.sender,
token,
governor,
timelock,
params.daoName,
params.tokenName,
params.tokenSymbol,
params.totalSupply
);
return (token, timelock, governor);
}
/**
* @dev Deploys Token (via clone), Timelock, and Governor (via clone) contracts
*/
function _deployContracts(
CreateDAOParams calldata params
) internal returns (address token, address timelock, address governor) {
// Calculate proposal threshold (1% of total supply)
uint256 proposalThreshold = (params.totalSupply * CREATOR_ALLOCATION_PERCENT) / 100;
// Deploy Token as minimal proxy (EIP-1167 clone)
token = Clones.clone(tokenImplementation);
DAOToken(token).initialize(
params.tokenName,
params.tokenSymbol,
params.totalSupply,
address(this)
);
// Deploy TimelockController (not cloned - different config per DAO)
address[] memory proposers = new address[](0);
address[] memory executors = new address[](1);
executors[0] = address(0); // Anyone can execute
TimelockController timelockController = new TimelockController(
TIMELOCK_MIN_DELAY,
proposers,
executors,
address(this)
);
timelock = address(timelockController);
// Deploy Governor as minimal proxy (EIP-1167 clone)
// Creator (msg.sender) is set as the initial manager
governor = Clones.clone(governorImplementation);
DAOGovernor(payable(governor)).initialize(
params.daoName,
IVotes(token),
TimelockControllerUpgradeable(payable(timelock)),
params.votingDelay,
params.votingPeriod,
proposalThreshold,
msg.sender // Set creator as initial manager
);
return (token, timelock, governor);
}
/**
* @dev Configures TimelockController roles
*/
function _configureTimelock(
TimelockController timelockController,
address governor
) internal {
// Grant PROPOSER_ROLE to Governor
bytes32 proposerRole = timelockController.PROPOSER_ROLE();
timelockController.grantRole(proposerRole, governor);
// Grant CANCELLER_ROLE to Governor
bytes32 cancellerRole = timelockController.CANCELLER_ROLE();
timelockController.grantRole(cancellerRole, governor);
// Revoke ADMIN role from factory
bytes32 adminRole = timelockController.DEFAULT_ADMIN_ROLE();
timelockController.revokeRole(adminRole, address(this));
}
/**
* @dev Distributes tokens to creator and treasury
*/
function _distributeTokens(
DAOToken daoToken,
address timelock,
uint256 totalSupply
) internal {
uint256 creatorAmount = (totalSupply * CREATOR_ALLOCATION_PERCENT) / 100;
uint256 treasuryAmount = totalSupply - creatorAmount;
// Transfer 1% to creator
daoToken.transfer(msg.sender, creatorAmount);
// Transfer 99% to timelock (treasury)
daoToken.transfer(timelock, treasuryAmount);
}
/**
* @dev Records DAO info in storage
*/
function _recordDAO(
address token,
address timelock,
address governor,
string calldata daoName
) internal {
DAOInfo memory daoInfo = DAOInfo({
token: token,
timelock: timelock,
governor: governor,
creator: msg.sender,
daoName: daoName,
createdAt: block.timestamp
});
deployedDAOs.push(daoInfo);
creatorDAOs[msg.sender].push(daoInfo);
}
/**
* @notice Returns the total number of DAOs created
*/
function getDAOCount() external view returns (uint256) {
return deployedDAOs.length;
}
/**
* @notice Returns all DAOs created by a specific address
* @param creator The address to query
*/
function getDAOsByCreator(address creator) external view returns (DAOInfo[] memory) {
return creatorDAOs[creator];
}
/**
* @notice Returns DAO info at a specific index
* @param index The index in deployedDAOs array
*/
function getDAO(uint256 index) external view returns (DAOInfo memory) {
if (index >= deployedDAOs.length) revert IndexOutOfBounds();
return deployedDAOs[index];
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.28;
import "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol";
import "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC20PermitUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC20VotesUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
/**
* @title DAOToken
* @author CreateDAO
* @notice ERC20 governance token with voting capabilities, designed for minimal proxy (EIP-1167) deployment
* @dev Implementation contract for DAO governance tokens deployed via DAOFactory
*
* ═══════════════════════════════════════════════════════════════════════════════════════
* ARCHITECTURE
* ═══════════════════════════════════════════════════════════════════════════════════════
*
* This contract uses the INITIALIZER PATTERN instead of constructors to support
* EIP-1167 Minimal Proxy (Clone) deployment. Key characteristics:
*
* 1. IMMUTABLE PROXY: Each clone permanently points to this implementation.
* The proxy bytecode hardcodes the implementation address - it CANNOT be changed.
* This is NOT an upgradeable proxy - there is no upgrade mechanism.
*
* 2. NO OWNER/ADMIN: The proxy has no owner, no admin, no special privileges.
* It simply forwards all calls to this implementation via delegatecall.
*
* 3. SEPARATE STORAGE: Each clone has its own storage. The implementation's
* storage is never used (except for immutable variables).
*
* 4. ONE-TIME INITIALIZATION: The `initialize()` function can only be called once
* per clone, enforced by OpenZeppelin's Initializable. This prevents:
* - Re-initialization attacks
* - State manipulation after deployment
*
* ═══════════════════════════════════════════════════════════════════════════════════════
* FEATURES
* ═══════════════════════════════════════════════════════════════════════════════════════
*
* - ERC20Votes: Tracks voting power with historical checkpoints for governance
* - ERC20Permit: Gasless approvals via EIP-2612 signatures
* - Auto-delegation: First-time token recipients automatically self-delegate,
* ensuring voting power is immediately active without manual action
* - 18 decimals (standard ERC20)
*
* ═══════════════════════════════════════════════════════════════════════════════════════
* SECURITY NOTES
* ═══════════════════════════════════════════════════════════════════════════════════════
*
* - Implementation contract has `_disableInitializers()` in constructor to prevent
* initialization of the implementation itself (defense in depth)
* - No minting after initial supply - total supply is fixed at initialization
* - No owner/admin functions - fully decentralized from deployment
*/
contract DAOToken is
Initializable,
ERC20Upgradeable,
ERC20PermitUpgradeable,
ERC20VotesUpgradeable
{
// ═══════════════════════════════════════════════════════════════════════════════════
// STORAGE
// ═══════════════════════════════════════════════════════════════════════════════════
/// @notice Tracks addresses that have received tokens (for auto-delegation)
/// @dev Used to auto-delegate voting power on first token receipt
mapping(address => bool) private _hasReceivedTokens;
// ═══════════════════════════════════════════════════════════════════════════════════
// CONSTRUCTOR
// ═══════════════════════════════════════════════════════════════════════════════════
/**
* @notice Disables initialization on the implementation contract
* @dev This is a security measure. The implementation contract should never be
* initialized directly - only clones should be initialized.
*
* Why this matters:
* - If someone initialized the implementation, they could potentially
* manipulate it in ways that affect clone behavior (for immutable vars)
* - This follows OpenZeppelin's best practice for implementation contracts
*
* @custom:oz-upgrades-unsafe-allow constructor
*/
constructor() {
_disableInitializers();
}
// ═══════════════════════════════════════════════════════════════════════════════════
// INITIALIZER
// ═══════════════════════════════════════════════════════════════════════════════════
/**
* @notice Initializes a new DAO governance token (called once per clone)
* @dev Replaces the constructor for clone deployments. Can only be called once.
*
* @param name_ The name of the token (e.g., "MyDAO Token")
* @param symbol_ The symbol of the token (e.g., "MDT")
* @param totalSupply_ Total supply to mint in wei (e.g., 1000000 * 10^18 for 1M tokens)
* @param mintTo_ Address to receive the initial supply (typically the factory,
* which then distributes to creator and treasury)
*
* @custom:security The `initializer` modifier ensures:
* 1. This function can only be called once per clone
* 2. Reentrancy during initialization is prevented
* 3. The initialization state is properly tracked
*/
function initialize(
string memory name_,
string memory symbol_,
uint256 totalSupply_,
address mintTo_
) external initializer {
// Initialize inherited contracts in the correct order
// Order matters for proper initialization of storage variables
__ERC20_init(name_, symbol_);
__ERC20Permit_init(name_);
__ERC20Votes_init();
// Mint the total supply to the specified address
// This is typically the factory, which distributes tokens appropriately
_mint(mintTo_, totalSupply_);
}
// ═══════════════════════════════════════════════════════════════════════════════════
// CLOCK FUNCTIONS
// ═══════════════════════════════════════════════════════════════════════════════════
/**
* @notice Returns the current clock value for governance (timestamp)
* @dev Required by ERC6372 for governance timing. Uses timestamps as the
* time-keeping mechanism for voting snapshots.
*
* Why timestamps over block numbers:
* - Predictable timing across all chains (L1, L2s have different block times)
* - Better UX: users understand "1 day" better than "7200 blocks"
* - Consistent behavior regardless of network congestion
*
* @return Current block timestamp as uint48
*/
function clock() public view override returns (uint48) {
return uint48(block.timestamp);
}
/**
* @notice Returns the clock mode description
* @dev Required by ERC6372. Indicates that this token uses timestamps
* for governance timing (as opposed to block numbers).
*
* @return Mode string indicating timestamp-based timing
*/
// solhint-disable-next-line func-name-mixedcase
function CLOCK_MODE() public pure override returns (string memory) {
return "mode=timestamp";
}
// ═══════════════════════════════════════════════════════════════════════════════════
// INTERNAL OVERRIDES
// ═══════════════════════════════════════════════════════════════════════════════════
/**
* @dev Internal update function with auto-delegation feature
*
* When an address receives tokens for the first time, this function
* automatically delegates their voting power to themselves. This ensures:
*
* 1. Users have immediate voting power without manual delegation
* 2. The DAO creator can vote immediately after receiving their allocation
* 3. Users don't lose voting ability due to forgetting to delegate
*
* @param from Source address (address(0) for mints)
* @param to Destination address (address(0) for burns)
* @param value Amount of tokens being transferred
*/
function _update(
address from,
address to,
uint256 value
) internal override(ERC20Upgradeable, ERC20VotesUpgradeable) {
// Call parent implementation (handles balance updates and voting checkpoints)
super._update(from, to, value);
// Auto-delegate to self on first receive
// Conditions:
// - `to` is not zero address (not a burn)
// - `to` has never received tokens before
if (to != address(0) && !_hasReceivedTokens[to]) {
_hasReceivedTokens[to] = true;
_delegate(to, to);
}
}
/**
* @dev Override for ERC20Permit nonces
* @param owner The address to query nonces for
* @return Current nonce for the owner
*/
function nonces(
address owner
) public view override(ERC20PermitUpgradeable, NoncesUpgradeable) returns (uint256) {
return super.nonces(owner);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.28;
import "@openzeppelin/contracts/governance/TimelockController.sol";
/**
* @title TimelockControllerForVerification
* @notice This contract exists solely to create an artifact for TimelockController verification
* @dev Hardhat v3 only creates artifacts for contracts declared in your project.
* By declaring a contract that inherits from TimelockController (even with no changes),
* we force Hardhat to create an artifact that can be used for verification.
*
* IMPORTANT: This contract is NOT deployed. The DAOFactory deploys the original
* OpenZeppelin TimelockController directly. This file only exists to:
* 1. Generate a compilable artifact for Etherscan verification
* 2. Reference: contracts/imports/TimelockControllerImport.sol:TimelockControllerForVerification
*/
contract TimelockControllerForVerification is TimelockController {
constructor(
uint256 minDelay,
address[] memory proposers,
address[] memory executors,
address admin
) TimelockController(minDelay, proposers, executors, admin) {}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.28;
import "@openzeppelin/contracts/governance/TimelockController.sol";
/**
* @title TimelockHelper
* @notice Helper contract to ensure TimelockController is compiled into artifacts for testing
* @dev This contract is not deployed, it only exists to generate the TimelockController artifact
*/
contract TimelockHelper is TimelockController {
constructor() TimelockController(0, new address[](0), new address[](0), msg.sender) {}
}{
"evmVersion": "cancun",
"optimizer": {
"enabled": true,
"runs": 1,
"details": {
"yulDetails": {
"optimizerSteps": "u"
}
}
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"remappings": [
"npm/@openzeppelin/[email protected]/:@openzeppelin/contracts/=npm/@openzeppelin/[email protected]/",
"npm/@openzeppelin/[email protected]/:@openzeppelin/contracts/=npm/@openzeppelin/[email protected]/",
"npm/@openzeppelin/[email protected]/:@openzeppelin/contracts/=npm/@openzeppelin/[email protected]/",
"npm/@openzeppelin/[email protected]/:@openzeppelin/contracts/=npm/@openzeppelin/[email protected]/",
"npm/@openzeppelin/[email protected]/:@openzeppelin/contracts/=npm/@openzeppelin/[email protected]/",
"npm/@openzeppelin/[email protected]/:@openzeppelin/contracts/=npm/@openzeppelin/[email protected]/",
"npm/@openzeppelin/[email protected]/:@openzeppelin/contracts/=npm/@openzeppelin/[email protected]/",
"npm/@openzeppelin/[email protected]/:@openzeppelin/contracts/=npm/@openzeppelin/[email protected]/",
"npm/@openzeppelin/[email protected]/:@openzeppelin/contracts/=npm/@openzeppelin/[email protected]/",
"npm/@openzeppelin/[email protected]/:@openzeppelin/contracts/=npm/@openzeppelin/[email protected]/",
"npm/@openzeppelin/[email protected]/:@openzeppelin/contracts/=npm/@openzeppelin/[email protected]/",
"npm/@openzeppelin/[email protected]/:@openzeppelin/contracts/=npm/@openzeppelin/[email protected]/",
"npm/@openzeppelin/[email protected]/:@openzeppelin/contracts/=npm/@openzeppelin/[email protected]/",
"npm/@openzeppelin/[email protected]/:@openzeppelin/contracts/=npm/@openzeppelin/[email protected]/",
"npm/@openzeppelin/[email protected]/:@openzeppelin/contracts/=npm/@openzeppelin/[email protected]/",
"npm/@openzeppelin/[email protected]/:@openzeppelin/contracts/=npm/@openzeppelin/[email protected]/",
"npm/@openzeppelin/[email protected]/:@openzeppelin/contracts/=npm/@openzeppelin/[email protected]/",
"npm/@openzeppelin/[email protected]/:@openzeppelin/contracts/=npm/@openzeppelin/[email protected]/",
"npm/@openzeppelin/[email protected]/:@openzeppelin/contracts/=npm/@openzeppelin/[email protected]/",
"npm/@openzeppelin/[email protected]/:@openzeppelin/contracts/=npm/@openzeppelin/[email protected]/",
"npm/@openzeppelin/[email protected]/:@openzeppelin/contracts/=npm/@openzeppelin/[email protected]/",
"npm/@openzeppelin/[email protected]/:@openzeppelin/contracts/=npm/@openzeppelin/[email protected]/",
"npm/@openzeppelin/[email protected]/:@openzeppelin/contracts/=npm/@openzeppelin/[email protected]/",
"npm/@openzeppelin/[email protected]/:@openzeppelin/contracts/=npm/@openzeppelin/[email protected]/",
"npm/@openzeppelin/[email protected]/:@openzeppelin/contracts/=npm/@openzeppelin/[email protected]/",
"npm/@openzeppelin/[email protected]/:@openzeppelin/contracts/=npm/@openzeppelin/[email protected]/",
"npm/@openzeppelin/[email protected]/:@openzeppelin/contracts/=npm/@openzeppelin/[email protected]/",
"npm/@openzeppelin/[email protected]/:@openzeppelin/contracts/=npm/@openzeppelin/[email protected]/",
"npm/@openzeppelin/[email protected]/:@openzeppelin/contracts/=npm/@openzeppelin/[email protected]/",
"npm/@openzeppelin/[email protected]/:@openzeppelin/contracts/=npm/@openzeppelin/[email protected]/",
"npm/@openzeppelin/[email protected]/:@openzeppelin/contracts/=npm/@openzeppelin/[email protected]/",
"npm/@openzeppelin/[email protected]/:@openzeppelin/contracts/=npm/@openzeppelin/[email protected]/",
"npm/@openzeppelin/[email protected]/:@openzeppelin/contracts/=npm/@openzeppelin/[email protected]/",
"npm/@openzeppelin/[email protected]/:@openzeppelin/contracts/=npm/@openzeppelin/[email protected]/",
"npm/@openzeppelin/[email protected]/:@openzeppelin/contracts/=npm/@openzeppelin/[email protected]/",
"npm/@openzeppelin/[email protected]/:@openzeppelin/contracts/=npm/@openzeppelin/[email protected]/",
"npm/@openzeppelin/[email protected]/:@openzeppelin/contracts/=npm/@openzeppelin/[email protected]/",
"npm/@openzeppelin/[email protected]/:@openzeppelin/contracts/=npm/@openzeppelin/[email protected]/",
"npm/@openzeppelin/[email protected]/:@openzeppelin/contracts/=npm/@openzeppelin/[email protected]/",
"npm/@openzeppelin/[email protected]/:@openzeppelin/contracts/=npm/@openzeppelin/[email protected]/",
"npm/@openzeppelin/[email protected]/:@openzeppelin/contracts/=npm/@openzeppelin/[email protected]/",
"project/:@openzeppelin/contracts-upgradeable/=npm/@openzeppelin/[email protected]/",
"project/:@openzeppelin/contracts-upgradeable/=npm/@openzeppelin/[email protected]/",
"project/:@openzeppelin/contracts-upgradeable/=npm/@openzeppelin/[email protected]/",
"project/:@openzeppelin/contracts-upgradeable/=npm/@openzeppelin/[email protected]/",
"project/:@openzeppelin/contracts-upgradeable/=npm/@openzeppelin/[email protected]/",
"project/:@openzeppelin/contracts-upgradeable/=npm/@openzeppelin/[email protected]/",
"project/:@openzeppelin/contracts-upgradeable/=npm/@openzeppelin/[email protected]/",
"project/:@openzeppelin/contracts-upgradeable/=npm/@openzeppelin/[email protected]/",
"project/:@openzeppelin/contracts-upgradeable/=npm/@openzeppelin/[email protected]/",
"project/:@openzeppelin/contracts-upgradeable/=npm/@openzeppelin/[email protected]/",
"project/:@openzeppelin/contracts-upgradeable/=npm/@openzeppelin/[email protected]/",
"project/:@openzeppelin/contracts-upgradeable/=npm/@openzeppelin/[email protected]/",
"project/:@openzeppelin/contracts/=npm/@openzeppelin/[email protected]/",
"project/:@openzeppelin/contracts/=npm/@openzeppelin/[email protected]/",
"project/:@openzeppelin/contracts/=npm/@openzeppelin/[email protected]/",
"project/:@openzeppelin/contracts/=npm/@openzeppelin/[email protected]/"
],
"viaIR": true
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"CheckpointUnorderedInsertion","type":"error"},{"inputs":[],"name":"FailedCall","type":"error"},{"inputs":[{"internalType":"address","name":"voter","type":"address"}],"name":"GovernorAlreadyCastVote","type":"error"},{"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"}],"name":"GovernorAlreadyQueuedProposal","type":"error"},{"inputs":[],"name":"GovernorDisabledDeposit","type":"error"},{"inputs":[{"internalType":"address","name":"proposer","type":"address"},{"internalType":"uint256","name":"votes","type":"uint256"},{"internalType":"uint256","name":"threshold","type":"uint256"}],"name":"GovernorInsufficientProposerVotes","type":"error"},{"inputs":[{"internalType":"uint256","name":"targets","type":"uint256"},{"internalType":"uint256","name":"calldatas","type":"uint256"},{"internalType":"uint256","name":"values","type":"uint256"}],"name":"GovernorInvalidProposalLength","type":"error"},{"inputs":[{"internalType":"uint256","name":"quorumNumerator","type":"uint256"},{"internalType":"uint256","name":"quorumDenominator","type":"uint256"}],"name":"GovernorInvalidQuorumFraction","type":"error"},{"inputs":[{"internalType":"address","name":"voter","type":"address"}],"name":"GovernorInvalidSignature","type":"error"},{"inputs":[],"name":"GovernorInvalidVoteParams","type":"error"},{"inputs":[],"name":"GovernorInvalidVoteType","type":"error"},{"inputs":[{"internalType":"uint256","name":"votingPeriod","type":"uint256"}],"name":"GovernorInvalidVotingPeriod","type":"error"},{"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"}],"name":"GovernorNonexistentProposal","type":"error"},{"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"}],"name":"GovernorNotQueuedProposal","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"GovernorOnlyExecutor","type":"error"},{"inputs":[],"name":"GovernorQueueNotImplemented","type":"error"},{"inputs":[{"internalType":"address","name":"proposer","type":"address"}],"name":"GovernorRestrictedProposer","type":"error"},{"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"},{"internalType":"address","name":"account","type":"address"}],"name":"GovernorUnableToCancel","type":"error"},{"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"},{"internalType":"enum IGovernor.ProposalState","name":"current","type":"uint8"},{"internalType":"bytes32","name":"expectedStates","type":"bytes32"}],"name":"GovernorUnexpectedProposalState","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"currentNonce","type":"uint256"}],"name":"InvalidAccountNonce","type":"error"},{"inputs":[],"name":"InvalidInitialization","type":"error"},{"inputs":[],"name":"NotInitializing","type":"error"},{"inputs":[],"name":"OnlyGovernance","type":"error"},{"inputs":[{"internalType":"uint8","name":"bits","type":"uint8"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"SafeCastOverflowedUintDowncast","type":"error"},{"anonymous":false,"inputs":[],"name":"EIP712DomainChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"version","type":"uint64"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousManager","type":"address"},{"indexed":true,"internalType":"address","name":"newManager","type":"address"}],"name":"ManagerChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"proposalId","type":"uint256"}],"name":"ProposalCanceled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"proposalId","type":"uint256"},{"indexed":false,"internalType":"address","name":"proposer","type":"address"},{"indexed":false,"internalType":"address[]","name":"targets","type":"address[]"},{"indexed":false,"internalType":"uint256[]","name":"values","type":"uint256[]"},{"indexed":false,"internalType":"string[]","name":"signatures","type":"string[]"},{"indexed":false,"internalType":"bytes[]","name":"calldatas","type":"bytes[]"},{"indexed":false,"internalType":"uint256","name":"voteStart","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"voteEnd","type":"uint256"},{"indexed":false,"internalType":"string","name":"description","type":"string"}],"name":"ProposalCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"proposalId","type":"uint256"}],"name":"ProposalExecuted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"proposalId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"etaSeconds","type":"uint256"}],"name":"ProposalQueued","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldProposalThreshold","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newProposalThreshold","type":"uint256"}],"name":"ProposalThresholdSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldQuorumNumerator","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newQuorumNumerator","type":"uint256"}],"name":"QuorumNumeratorUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldTimelock","type":"address"},{"indexed":false,"internalType":"address","name":"newTimelock","type":"address"}],"name":"TimelockChange","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"voter","type":"address"},{"indexed":false,"internalType":"uint256","name":"proposalId","type":"uint256"},{"indexed":false,"internalType":"uint8","name":"support","type":"uint8"},{"indexed":false,"internalType":"uint256","name":"weight","type":"uint256"},{"indexed":false,"internalType":"string","name":"reason","type":"string"}],"name":"VoteCast","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"voter","type":"address"},{"indexed":false,"internalType":"uint256","name":"proposalId","type":"uint256"},{"indexed":false,"internalType":"uint8","name":"support","type":"uint8"},{"indexed":false,"internalType":"uint256","name":"weight","type":"uint256"},{"indexed":false,"internalType":"string","name":"reason","type":"string"},{"indexed":false,"internalType":"bytes","name":"params","type":"bytes"}],"name":"VoteCastWithParams","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldVotingDelay","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newVotingDelay","type":"uint256"}],"name":"VotingDelaySet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldVotingPeriod","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newVotingPeriod","type":"uint256"}],"name":"VotingPeriodSet","type":"event"},{"inputs":[],"name":"BALLOT_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"CLOCK_MODE","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"COUNTING_MODE","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"EXTENDED_BALLOT_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"targets","type":"address[]"},{"internalType":"uint256[]","name":"values","type":"uint256[]"},{"internalType":"bytes[]","name":"calldatas","type":"bytes[]"},{"internalType":"bytes32","name":"descriptionHash","type":"bytes32"}],"name":"cancel","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"},{"internalType":"uint8","name":"support","type":"uint8"}],"name":"castVote","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"},{"internalType":"uint8","name":"support","type":"uint8"},{"internalType":"address","name":"voter","type":"address"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"castVoteBySig","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"},{"internalType":"uint8","name":"support","type":"uint8"},{"internalType":"string","name":"reason","type":"string"}],"name":"castVoteWithReason","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"},{"internalType":"uint8","name":"support","type":"uint8"},{"internalType":"string","name":"reason","type":"string"},{"internalType":"bytes","name":"params","type":"bytes"}],"name":"castVoteWithReasonAndParams","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"},{"internalType":"uint8","name":"support","type":"uint8"},{"internalType":"address","name":"voter","type":"address"},{"internalType":"string","name":"reason","type":"string"},{"internalType":"bytes","name":"params","type":"bytes"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"castVoteWithReasonAndParamsBySig","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"clock","outputs":[{"internalType":"uint48","name":"","type":"uint48"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"daoVersion","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"eip712Domain","outputs":[{"internalType":"bytes1","name":"fields","type":"bytes1"},{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"version","type":"string"},{"internalType":"uint256","name":"chainId","type":"uint256"},{"internalType":"address","name":"verifyingContract","type":"address"},{"internalType":"bytes32","name":"salt","type":"bytes32"},{"internalType":"uint256[]","name":"extensions","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"targets","type":"address[]"},{"internalType":"uint256[]","name":"values","type":"uint256[]"},{"internalType":"bytes[]","name":"calldatas","type":"bytes[]"},{"internalType":"bytes32","name":"descriptionHash","type":"bytes32"}],"name":"execute","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address[]","name":"targets","type":"address[]"},{"internalType":"uint256[]","name":"values","type":"uint256[]"},{"internalType":"bytes[]","name":"calldatas","type":"bytes[]"},{"internalType":"bytes32","name":"descriptionHash","type":"bytes32"}],"name":"getProposalId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"timepoint","type":"uint256"}],"name":"getVotes","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"timepoint","type":"uint256"},{"internalType":"bytes","name":"params","type":"bytes"}],"name":"getVotesWithParams","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"},{"internalType":"address","name":"account","type":"address"}],"name":"hasVoted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"targets","type":"address[]"},{"internalType":"uint256[]","name":"values","type":"uint256[]"},{"internalType":"bytes[]","name":"calldatas","type":"bytes[]"},{"internalType":"bytes32","name":"descriptionHash","type":"bytes32"}],"name":"hashProposal","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"string","name":"name_","type":"string"},{"internalType":"contract IVotes","name":"token_","type":"address"},{"internalType":"contract TimelockControllerUpgradeable","name":"timelock_","type":"address"},{"internalType":"uint48","name":"votingDelay_","type":"uint48"},{"internalType":"uint32","name":"votingPeriod_","type":"uint32"},{"internalType":"uint256","name":"proposalThreshold_","type":"uint256"},{"internalType":"address","name":"initialManager_","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"manager","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256[]","name":"","type":"uint256[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC1155BatchReceived","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC1155Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC721Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"}],"name":"proposalDeadline","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"}],"name":"proposalEta","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"}],"name":"proposalNeedsQueuing","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"}],"name":"proposalProposer","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"}],"name":"proposalSnapshot","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"proposalThreshold","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"}],"name":"proposalVotes","outputs":[{"internalType":"uint256","name":"againstVotes","type":"uint256"},{"internalType":"uint256","name":"forVotes","type":"uint256"},{"internalType":"uint256","name":"abstainVotes","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"targets","type":"address[]"},{"internalType":"uint256[]","name":"values","type":"uint256[]"},{"internalType":"bytes[]","name":"calldatas","type":"bytes[]"},{"internalType":"string","name":"description","type":"string"}],"name":"propose","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"targets","type":"address[]"},{"internalType":"uint256[]","name":"values","type":"uint256[]"},{"internalType":"bytes[]","name":"calldatas","type":"bytes[]"},{"internalType":"bytes32","name":"descriptionHash","type":"bytes32"}],"name":"queue","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"blockNumber","type":"uint256"}],"name":"quorum","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"quorumDenominator","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"timepoint","type":"uint256"}],"name":"quorumNumerator","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"quorumNumerator","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"target","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"relay","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"newManager","type":"address"}],"name":"setManager","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newProposalThreshold","type":"uint256"}],"name":"setProposalThreshold","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint48","name":"newVotingDelay","type":"uint48"}],"name":"setVotingDelay","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"newVotingPeriod","type":"uint32"}],"name":"setVotingPeriod","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"}],"name":"state","outputs":[{"internalType":"enum IGovernor.ProposalState","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"timelock","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"token","outputs":[{"internalType":"contract IERC5805","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"newQuorumNumerator","type":"uint256"}],"name":"updateQuorumNumerator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract TimelockControllerUpgradeable","name":"newTimelock","type":"address"}],"name":"updateTimelock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"votingDelay","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"votingPeriod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]Contract Creation Code
60806040523461002257610011610026565b6040516154a461018682396154a490f35b5f80fd5b61002e6100a9565b565b61003d9060401c60ff1690565b90565b61003d9054610030565b61003d905b6001600160401b031690565b61003d905461004a565b61003d9061004f906001600160401b031682565b9061008961003d6100a592610065565b82546001600160401b0319166001600160401b03919091161790565b9055565b5f6100b261013f565b016100bc81610040565b61012e576100c98161005b565b6001600160401b03919082908116036100e0575050565b8161010f7fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29361012993610079565b604051918291826001600160401b03909116815260200190565b0390a1565b63f92ee8a960e01b5f908152600490fd5b61003d61017d565b61003d61003d61003d9290565b61003d7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00610147565b61003d61015456fe60806040526004361015610022575b3615610018575f80fd5b6100206126ca565b005b5f3560e01c806301ffc9a71461037157806302a251a31461036c57806306f3f9e61461036757806306fdde0314610362578063143489d01461035d578063150b7a0214610358578063160cbed7146103535780632656227d1461034e5780632d63f693146103495780632fe3e2611461034457806336834b061461033f5780633932abb11461033a5780633e4f49e6146103355780634385963214610330578063452115d61461032b578063481c6a75146103265780634bf5d7e914610321578063544ffc9c1461031c57806354fd4d501461031757806356781388146103125780635b8d0e0d1461030d5780635f398a141461030857806360c4247f1461030357806379051887146102fe5780637b3c71d3146102f95780637d5e81e2146102f45780637ecebe00146102ef57806380626478146102ea57806384b0196e146102e55780638ff262e3146102e057806391ddadf4146102db57806397c3d334146102d65780639a802a6d146102d1578063a7713a70146102cc578063a890c910146102c7578063a8f8a668146102c2578063a9a95294146102bd578063ab58fb8e146102b8578063b58131b0146102b3578063bc197c81146102ae578063c01f9e37146102a9578063c28bc2fa146102a4578063c59057e41461029f578063d0ebdbe71461029a578063d33219b414610295578063dd4e2ba514610290578063deaaa7cc1461028b578063e540d01d14610286578063eb9019d414610281578063ece40cc11461027c578063f23a6e6114610277578063f8ce560a146102725763fc0c546a0361000e57611461565b611407565b6113e8565b61138f565b611373565b61133f565b611310565b6112c9565b6112ae565b611296565b611277565b611260565b611222565b611203565b611165565b61114a565b61112e565b61110f565b6110f7565b6110c8565b6110ac565b611050565b611029565b610ff1565b610f8c565b610ea3565b610ddf565b610dac565b610d26565b610cc9565b610c79565b610c5a565b610bd2565b610af3565b610a9f565b610a75565b610a38565b610a1d565b6109fe565b6109e2565b610998565b61092e565b610913565b6108f8565b6108b1565b610897565b610878565b610678565b610514565b6104bf565b61044e565b6103fc565b6103c1565b6001600160e01b03191690565b61038c81610376565b0361039357565b5f80fd5b905035906103a482610383565b565b90602082820312610393576103ba91610397565b90565b9052565b34610393576103ee6103dc6103d73660046103a6565b611488565b60405191829182901515815260200190565b0390f35b5f91031261039357565b346103935761040c3660046103f2565b6103ee610417611510565b6040519182918290815260200190565b8061038c565b905035906103a482610427565b90602082820312610393576103ba9161042d565b346103935761046661046136600461043a565b61152d565b604051005b90825f9392825e0152565b6104976104a06020936104aa9361048b815190565b80835293849260200190565b9586910161046b565b601f01601f191690565b0190565b60208082526103ba92910190610476565b34610393576104cf3660046103f2565b6103ee6104da611628565b604051918291826104ae565b6001600160a01b031690565b6103ba906104e6565b6103bd906104f2565b6020810192916103a491906104fb565b34610393576103ee61052f61052a36600461043a565b611667565b60405191829182610504565b61038c816104f2565b905035906103a48261053b565b634e487b7160e01b5f52604160045260245ffd5b90601f01601f191681019081106001600160401b0382111761058657604052565b610551565b906103a461059860405190565b9283610565565b6001600160401b03811161058657602090601f01601f19160190565b90825f939282370152565b909291926105db6105d68261059f565b61058b565b9381855281830111610393576103a49160208501906105bb565b9080601f83011215610393578160206103ba933591016105c6565b90608082820312610393576106258183610544565b926106338260208501610544565b92610641836040830161042d565b9260608201356001600160401b038111610393576103ba92016105f5565b6103bd90610376565b6020810192916103a4919061065f565b34610393576103ee61069761068e366004610610565b929190916116ab565b60405191829182610668565b6001600160401b0381116105865760208091020190565b909291926106ca6105d6826106a3565b938185526020808601920283019281841161039357915b8383106106ee5750505050565b602080916106fc8486610544565b8152019201916106e1565b9080601f83011215610393578160206103ba933591016106ba565b909291926107326105d6826106a3565b938185526020808601920283019281841161039357915b8383106107565750505050565b60208091610764848661042d565b815201920191610749565b9080601f83011215610393578160206103ba93359101610722565b9291906107996105d6826106a3565b93818552602080860192028101918383116103935781905b8382106107bf575050505050565b81356001600160401b038111610393576020916107df87849387016105f5565b8152019101906107b1565b9080601f83011215610393578160206103ba9335910161078a565b6080818303126103935780356001600160401b038111610393578261082b918301610707565b9260208201356001600160401b038111610393578361084b91840161076f565b926040830135906001600160401b038211610393576060610871826103ba9487016107ea565b940161042d565b34610393576103ee61041761088e366004610805565b9291909161177e565b6103ee6104176108a8366004610805565b92919091611898565b34610393576103ee6104176108c736600461043a565b611a49565b7f3e83946653575f9a39005e1545185629e92736b7528ab20ca3816f315424a81190565b6103ba6108cc565b34610393576109083660046103f2565b6103ee6104176108f0565b34610393576109233660046103f2565b6103ee6104da611a9b565b346103935761093e3660046103f2565b6103ee610417611aa3565b634e487b7160e01b5f52602160045260245ffd5b6008111561096757565b610949565b906103a48261095d565b6103ba9061096c565b6103bd90610976565b6020810192916103a4919061097f565b34610393576103ee6109b36109ae36600461043a565b611aab565b60405191829182610988565b9190604083820312610393576103ba9060206109db828661042d565b9401610544565b34610393576103ee6103dc6109f83660046109bf565b90611ad3565b34610393576103ee610417610a14366004610805565b92919091611b14565b3461039357610a2d3660046103f2565b6103ee61052f611b5c565b3461039357610a483660046103f2565b6103ee6104da611b91565b9081526060810193926103a4929091604091610a71905b6020830152565b0152565b34610393576103ee610a90610a8b36600461043a565b611baa565b60405191939193849384610a53565b3461039357610aaf3660046103f2565b6103ee6104da611c00565b60ff811661038c565b905035906103a482610aba565b9190604083820312610393576103ba906020610aec828661042d565b9401610ac3565b34610393576103ee610417610b09366004610ad0565b90611c19565b909182601f83011215610393578135916001600160401b03831161039357602001926001830284011161039357565b919060c08382031261039357610b54818461042d565b92610b628260208301610ac3565b92610b708360408401610544565b9260608301356001600160401b0381116103935781610b90918501610b0f565b909390929060808101356001600160401b0381116103935783610bb49183016105f5565b9260a08201356001600160401b038111610393576103ba92016105f5565b34610393576103ee610417610be8366004610b3e565b95949094939193611c37565b919060808382031261039357610c0a818461042d565b92610c188260208301610ac3565b9260408201356001600160401b0381116103935783610c38918401610b0f565b909390929060608201356001600160401b038111610393576103ba92016105f5565b34610393576103ee610417610c70366004610bf4565b93929092611c90565b34610393576103ee610417610c8f36600461043a565b611ca8565b65ffffffffffff1690565b61038c81610c94565b905035906103a482610c9f565b90602082820312610393576103ba91610ca8565b3461039357610466610cdc366004610cb5565b611cd2565b9160608383031261039357610cf6828461042d565b92610d048360208301610ac3565b9260408201356001600160401b03811161039357610d229201610b0f565b9091565b34610393576103ee610417610d3c366004610ce1565b92919091611cdb565b906080828203126103935781356001600160401b0381116103935781610d6c918401610707565b9260208301356001600160401b0381116103935782610d8c91850161076f565b9260408101356001600160401b03811161039357836106419183016107ea565b34610393576103ee610417610dc2366004610d45565b92919091611d46565b90602082820312610393576103ba91610544565b34610393576103ee610417610df5366004610dcb565b611de7565b6103ba906104f2565b61038c81610dfa565b905035906103a482610e03565b63ffffffff811661038c565b905035906103a482610e19565b60e0818303126103935780356001600160401b0381116103935782610e589183016105f5565b92610e668360208401610e0c565b92610e748160408501610e0c565b92610e828260608301610ca8565b926103ba610e938460808501610e25565b9360c06109db8260a0870161042d565b3461039357610466610eb6366004610e32565b959490949391936120e0565b90610ee2610edb610ed1845190565b8084529260200190565b9260200190565b905f5b818110610ef25750505090565b909192610f0f610f086001928651815260200190565b9460200190565b929101610ee5565b93959194610f6e610f66610f7f95610f58610f78956103ba9c9a610f4b60e08c01925f8d01906001600160f81b0319169052565b8a820360208c0152610476565b9088820360408a0152610476565b976060870152565b60808501906104fb565b60a0830152565b60c0818403910152610ec2565b3461039357610f9c3660046103f2565b6103ee610fa7612168565b93610fb797959793919360405190565b97889788610f17565b9060808282031261039357610fd5818361042d565b92610fe38260208501610ac3565b926106418360408301610544565b34610393576103ee610417611007366004610fc0565b929190916121fa565b6103bd90610c94565b6020810192916103a49190611010565b34610393576110393660046103f2565b6103ee61104461223c565b60405191829182611019565b34610393576110603660046103f2565b6103ee610417612245565b91606083830312610393576110808284610544565b9261108e836020830161042d565b9260408201356001600160401b038111610393576103ba92016105f5565b34610393576103ee6104176110c236600461106b565b9161224f565b34610393576110d83660046103f2565b6103ee610417612275565b90602082820312610393576103ba91610e0c565b346103935761046661110a3660046110e3565b6122a6565b34610393576103ee610417611125366004610805565b929190916122af565b34610393576103ee6103dc61114436600461043a565b50600190565b34610393576103ee61041761116036600461043a565b6122ce565b34610393576111753660046103f2565b6103ee6104176122f1565b91909160a081840312610393576111978382610544565b926111a58160208401610544565b9260408301356001600160401b03811161039357826111c591850161076f565b9260608101356001600160401b03811161039357836111e591830161076f565b9260808201356001600160401b038111610393576103ba92016105f5565b34610393576103ee610697611219366004611180565b939290926122f9565b34610393576103ee61041761123836600461043a565b61237a565b91606083830312610393576112528284610544565b92610d04836020830161042d565b61046661126e36600461123d565b92919091612443565b34610393576103ee61041761128d366004610805565b9291909161255a565b34610393576104666112a9366004610dcb565b61259c565b34610393576112be3660046103f2565b6103ee61052f6125df565b34610393576112d93660046103f2565b6103ee6104da612629565b7ff2aad550cf55f045cb27e9c559f9889fdfb6e6cdaa032301d6ea397784ae51d790565b6103ba6112e4565b34610393576113203660046103f2565b6103ee610417611308565b90602082820312610393576103ba91610e25565b346103935761046661135236600461132b565b612646565b9190604083820312610393576103ba9060206108718286610544565b34610393576103ee610417611389366004611357565b9061264f565b34610393576104666113a236600461043a565b612676565b91909160a081840312610393576113be8382610544565b926113cc8160208401610544565b926113da826040850161042d565b926111e5836060830161042d565b34610393576103ee6106976113fe3660046113a7565b9392909261267f565b34610393576103ee61041761141d36600461043a565b6126b5565b6114316103ba6103ba926104e6565b6104e6565b6103ba90611422565b6103ba90611436565b6103bd9061143f565b6020810192916103a49190611448565b34610393576114713660046103f2565b6103ee61147c6126be565b60405191829182611451565b6366defe7760e11b9061149a82610376565b6114a382610376565b149182156114ea575b5081156114c8575b81156114be575090565b6103ba91506126e8565b90506114da630271189760e51b610376565b6114e382610376565b14906114b4565b9091506114ff9063151f14cd60e31b18610376565b61150882610376565b14905f6114ac565b6103ba61272e565b6103a490611524612749565b6103a4906127e6565b6103a490611518565b634e487b7160e01b5f52602260045260245ffd5b906001600283049216801561156a575b602083101461156557565b611536565b91607f169161155a565b80545f9392916115906115868361154a565b8085529360200190565b91600181169081156115df57506001146115a957505050565b6115ba91929394505f5260205f2090565b915f925b8184106115cb5750500190565b8054848401526020909301926001016115be565b92949550505060ff1916825215156020020190565b906103ba91611574565b906103a46116189261160f60405190565b938480926115f4565b0383610565565b6103ba906115fe565b6103ba5f61163461287c565b0161161f565b6103ba6103ba6103ba9290565b906116519061163a565b5f5260205260405f2090565b6103ba90546104f2565b5f6116876103ba926116765f90565b50600161168161287c565b01611647565b0161165d565b6116a66116a06103ba9263ffffffff1690565b60e01b90565b610376565b505050506116b65f90565b506116bf6128a0565b6116d96116d36116ce3061143f565b6104f2565b916104f2565b036116eb576103ba63150b7a0261168d565b637485328f60e11b5f90815260045b035ffd5b61170b6103ba6103ba9290565b610c94565b9065ffffffffffff905b9181191691161790565b61170b6103ba6103ba92610c94565b906117436103ba61174a92611724565b8254611710565b9055565b6103ba6103ba6103ba92610c94565b6103bd9061174e565b9081526040810192916103a4916020905b019061175d565b926117bc919261178b5f90565b5061179461287c565b936117a1838383896122af565b956117b56117af60046128c1565b8861290c565b5086612958565b906117c65f6116fe565b6117cf83610c94565b1461182457816118117f9a2e42fd6722813d69113e7d0079d3d940171428df7373df9c7f7617cfda289293600161180b878261181e9701611647565b01611733565b6040519182918583611766565b0390a190565b634844252360e11b5f908152600490fd5b9060ff60f01b9060f01b61171a565b906118546103ba61174a92151590565b8254611835565b634e487b7160e01b5f52603260045260245ffd5b90611878825190565b811015611889576020809102010190565b61185b565b6103ba90516104f2565b90926118a261287c565b926118af828287866122af565b946118ce6118bd60046128c1565b6118c760056128c1565b178761290c565b506001936118ea60015f6118e48a838b01611647565b01611844565b6118f26128a0565b946118fc3061143f565b956119096116d3886104f2565b036119a1575b509061191d93929187612a80565b6119316116d361192b6128a0565b926104f2565b141580611988575b611976575b507f712ae1383f79ac853f8d882153778e0260ef8f03b504e2866e0593e04d2b291f61196960405190565b828152806020810161181e565b61198290600201612ad1565b5f61193e565b5061199c61199860028301612a8d565b1590565b611939565b806119ab5f61163a565b905b6119b8575b5061190f565b6119c36103ba845190565b811015611a2e57806119e06119db6119f7938661186f565b61188e565b6119ec6116d38a6104f2565b146119fd5760010190565b816119ad565b611a2860028a01611a0e838961186f565b51611a21611a1a825190565b9160200190565b2090612a1d565b60010190565b6119b2565b6103ba9060a01c610c94565b6103ba9054611a33565b611a615f611a5b6103ba936116765f90565b01611a3f565b61174e565b90611a736105d68361059f565b918252565b611a826005611a66565b640312e302e360dc1b602082015290565b6103ba611a78565b6103ba611a93565b6103ba612aeb565b6103ba90612b2f565b906116519061143f565b6103ba905b60ff1690565b6103ba9054611abe565b6103ba916003611af1611af793611ae75f90565b505f611681612c68565b01611ab4565b611ac9565b9081526040810192916103a4916020905b01906104fb565b93929190611b24838383886122af565b9433611b336119988289612c8c565b611b4357506103ba949550612cc6565b638fe5d8a960e01b5f908152906116fa90886004611afc565b6103ba5f61165d565b611b6f600e611a66565b6d06d6f64653d74696d657374616d760941b602082015290565b6103ba611b65565b6103ba611b89565b6103ba9081565b6103ba9054611b99565b6103ba611bb891611ae75f90565b90611bc282611ba0565b90611bdb6002611bd460018601611ba0565b9401611ba0565b91929190565b611beb6001611a66565b603160f81b602082015290565b6103ba611be1565b6103ba611bf8565b6103ba5f611a66565b6103ba611c08565b6103ba9133611c26611c11565b92612cd2565b6103ba9136916105c6565b93919695611998611c6091949294611c4c5f90565b5087611c588686611c2c565b8b888a612d2a565b611c79576103ba959691611c7391611c2c565b92612e29565b6394ab6c0760e01b5f9081526116fa886004610504565b91611c736103ba9594611ca05f90565b503392611c2c565b6103ba90611cb85f6104aa612f03565b612f27565b6103a490611cc9612749565b6103a490612f7d565b6103a490611cbd565b91611c266103ba94611ca05f90565b634e487b7160e01b5f52601160045260245ffd5b611d0a611d1091610c94565b91610c94565b90039065ffffffffffff8211611d2257565b611cea565b604090610a716103a49496959396610a6a60608401985f8501906104fb565b939290913392611d596119988486612fd4565b611dd057611d656122f1565b95611d6f5f61163a565b8711611d81575b6103ba95965061308d565b611da8611da2611a61611d9261223c565b611d9c60016116fe565b90611cfe565b8661264f565b878110611db55750611d76565b636121770b60e11b5f908152906116fa908990886004611d27565b63d9b3955760e01b5f9081526116fa856004610504565b611e1d6103ba91611df55f90565b505f7f5ab42ced628888259c08ac98db1eb0cf702fc1501344311d8b100cd1bfe4bb00611af1565b611ba0565b6103ba9060401c611ac3565b6103ba9054611e22565b6103ba905b6001600160401b031690565b6103ba9054611e38565b611e3d6103ba6103ba9290565b906001600160401b039061171a565b6103ba90611e3d906001600160401b031682565b90611e936103ba61174a92611e6f565b8254611e60565b9060ff60401b9060401b61171a565b90611eb96103ba61174a92151590565b8254611e9a565b6103bd90611e53565b6020810192916103a49190611ec0565b929490959193611ee761309a565b958695611eff611ef961199889611e2e565b97611e49565b98611f095f611e53565b6001600160401b038b161480612009575b60019a611f36611f298d611e53565b916001600160401b031690565b149081611fe1575b155b9081611fd8575b50611fc757611f709688611f675f611f5e8e611e53565b9c019b8c611e83565b611fb85761204c565b611f78575050565b7fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d291611fa75f611fb393611ea9565b60405191829182611ec9565b0390a1565b611fc28b8b611ea9565b61204c565b63f92ee8a960e01b5f908152600490fd5b1590505f611f47565b9050611f40611fef3061143f565b3b612000611ffc5f61163a565b9190565b14919050611f3e565b5087611f1a565b906001600160a01b039061171a565b9061202f6103ba61174a9261143f565b8254612010565b6114316103ba6103ba9290565b6103ba90612036565b946120689192946120759461206361208c986130c8565b6130ea565b6120706130fd565b61311a565b612087612082600161163a565b613138565b613156565b612096815f61201f565b6120b06120aa6120a55f612043565b61143f565b9161143f565b907f605c2dbf762e5f7d60a546d42e7205dcb1b011ebc62a61736a57c9089d3a43506120db60405190565b5f90a3565b906103a4969594939291611ed9565b156120f657565b60405162461bcd60e51b81526020600482015260156024820152741152540dcc4c8e88155b9a5b9a5d1a585b1a5e9959605a1b6044820152606490fd5b90611a736105d6836106a3565b369037565b906103a461215b61215584612133565b936106a3565b601f190160208401612140565b61219661217361315f565b61217c81611ba0565b612188611ffc5f61163a565b1490816121da575b506120ef565b61219e613183565b906121a7613190565b906121b13061143f565b6121ba5f61163a565b6121cb6121c65f61163a565b612145565b600f60f81b9594934693929190565b6121e79150600101611ba0565b6121f3611ffc5f61163a565b145f612190565b9193926119986122149161220b5f90565b508684866131db565b612225576103ba9293611c26611c11565b6394ab6c0760e01b5f9081526116fa856004610504565b6103ba426116fe565b6103ba606461163a565b6103ba929190613257565b6001600160d01b031690565b6103ba6103ba6103ba9261225a565b6103ba61228c6122875f6104aa612f03565b613307565b612266565b6103a49061229d612749565b6103a490613370565b6103a490612291565b6103ba9392919061255a565b6103ba90610c94565b6103ba90546122bb565b611a6160016122eb6103ba936122e15f90565b508261168161287c565b016122c4565b6103ba6133d2565b50505050506123055f90565b5061230e6128a0565b61231d6116d36116ce3061143f565b036116eb576103ba63bc197c8161168d565b6103ba9060d01c5b63ffffffff1690565b6103ba905461232f565b61170b6103ba6103ba9263ffffffff1690565b611d0a61236991610c94565b019065ffffffffffff8211611d2257565b611a616103ba916123885f90565b506123be6123b95f6123b3600161239d61287c565b01946123ad83611a5b8389611647565b95611647565b01612340565b61234a565b9061235d565b906103a49392916123d3612749565b612410565b90916104aa90839080936105bb565b90916103ba926123d8565b3d1561240b576124013d611a66565b903d5f602084013e565b606090565b612440935f9392849361242e61242560405190565b938492836123e7565b03925af161243a6123f2565b906133e4565b50565b906103a49392916123c4565b906104aa816020936104fb565b9061246b610edb610ed1845190565b905f5b81811061247b5750505090565b90919261248e610f08600192865161244f565b92910161246e565b906103ba91610476565b906124b66124ac835190565b8083529160200190565b90816124c86020830284019460200190565b925f915b8383106124db57505050505090565b909192939460206124fe6124f783856001950387528951612496565b9760200190565b93019301919392906124cc565b9493916103a49361253e61254c9261253060609560808b01908b82035f8d015261245c565b9089820360208b0152610ec2565b9087820360408901526124a0565b940152565b6103ba9061163a565b9061258b9161257f6103ba9561256d5f90565b5060405195869460208601948561250b565b90810382520382610565565b612596611a1a825190565b20612551565b6125a76116ce6128a0565b6125b0336104f2565b036125ce576120b06120aa6125c45f61165d565b6120a5845f61201f565b6354348f0360e01b5f908152600490fd5b6103ba6120a55f6116876133f1565b6125f86020611a66565b7f737570706f72743d627261766f2671756f72756d3d666f722c6162737461696e602082015290565b6103ba6125ee565b6103ba612621565b6103a49061263d612749565b6103a4906134a1565b6103a490612631565b6103ba9161265b613525565b91613257565b6103a49061266d612749565b6103a49061353d565b6103a490612661565b505050505061268b5f90565b506126946128a0565b6126a36116d36116ce3061143f565b036116eb576103ba63f23a6e6161168d565b6103ba9061358a565b6103ba5f61168761360b565b6126d26128a0565b6126e16116d36116ce3061143f565b036116eb57565b6127016126fb6301ffc9a760e01b610376565b91610376565b1490565b6103ba9060301c612337565b6103ba9054612705565b6103ba6103ba6103ba9263ffffffff1690565b6103ba612744600161273e61362f565b01612711565b61271b565b61275161287c565b6127596128a0565b33906127676116d3836104f2565b036127bb57506127756128a0565b6127846116d36116ce3061143f565b0361278c5750565b612796365f611c2c565b6127a1611a1a825190565b20905b6127b060028201613691565b8290036127a4575050565b6347096e4760e01b5f908152906116fa906004610504565b9081526040810192916103a49160200152565b6127ee612f03565b6127f6612245565b8083116128635750907f0553476bf02ef2726e8ce5ced78d63e26e602e4a2257b1f559418e24b46339979161284c6128355f612830612275565b930190565b61283d61223c565b61284685613730565b91613769565b5050611fb361285a60405190565b928392836127d3565b63243e544560e01b5f908152906116fa908460046127d3565b7f7c712897014dbe49c045ef1299aa2d5f9e67e48eea4403efa21f1e0f3ac0cb0090565b6103ba6125df565b6103ba906128bc611ffc6103ba9460ff1690565b901b90565b6128e76128d86103ba926128d25f90565b50610976565b6128e2600161163a565b6128a8565b61163a565b9081526060810193926103a4929091604091610a7190602083019061097f565b9061291682611aab565b91612920836128c1565b612935836129306103ba5f61163a565b921690565b1461293f57505090565b6331b75e4d60e01b5f908152926116fa929160046128ec565b6103ba949392919061383d565b6103ba9060801c5b6001600160801b031690565b6103ba9054612965565b6129906103ba6103ba9290565b61296d565b6103ba910161296d565b6103ba9061296d565b6103ba905461299f565b6103ba604161163a565b6129906103ba6103ba9261296d565b90611651906129bc565b905f199061171a565b906129ec6103ba61174a9290565b82546129d5565b906001600160801b03199060801b61171a565b90612a166103ba61174a926129bc565b82546129f3565b9081612a2881612979565b612a3b612a356001612983565b82612995565b92612a48612990846129a8565b612a518561296d565b14612a7357612a69612a6e9260016103a497016129cb565b6129de565b612a06565b612a7b6129b2565b6139d2565b906103a4949392916139e2565b612701612aa5612990612a9f84612979565b936129a8565b9161296d565b906001600160801b039061171a565b90612aca6103ba61174a926129bc565b8254612aab565b6103a4905f612adf81612983565b9101612a6e8282612aba565b6103ba611a6160016122eb61362f565b80151561038c565b905051906103a482612afb565b90602082820312610393576103ba91612b03565b6040513d5f823e3d90fd5b612b376133f1565b90612b4181613a9e565b612b4b600561096c565b612b548261096c565b03612c625750612b6b611e1d5f9260018501611647565b9101612b796120a58261165d565b6020612b8460405190565b632c258a9f60e11b81526004810185905291829060249082905afa908115612c3e575f91612c43575b5015612bba575050600590565b612bed91612bcc6120a560209361165d565b60405193849283918291632ab0f52960e01b5b835260048301526024820190565b03915afa908115612c3e575f91612c0f575b5015612c0a57600790565b600290565b612c31915060203d602011612c37575b612c298183610565565b810190612b10565b5f612bff565b503d612c1f565b612b24565b612c5c915060203d602011612c3757612c298183610565565b5f612bad565b91505090565b7fa1cefa0f43667ef127a258e673c94202a79b656e62899531c4376d87a7f3980090565b90612c9682611aab565b612ca8612ca25f61096c565b9161096c565b149182612cb457505090565b6127019192506116ce6116d391611667565b6103ba93929190613b8e565b916103ba9391612cdf5f90565b50612ce8613525565b93612e29565b90815260e081019796959094909390929091602086015260ff16604085015260608401612d1a916104fb565b608083015260a082015260c00152565b612d8e906103ba969561257f612d9f9596612d425f90565b50612d4b6108cc565b92612d5c612d588a613c4b565b9290565b612d67611a1a825190565b2090612d74611a1a825190565b209189612d8060405190565b988997602089019788612cee565b612d99611a1a825190565b20613c6d565b90613caa565b93612dd46103ba9694612dcd612de195612dc360a08a01965f8b0152565b60ff166020890152565b6040870152565b8482036060860152610476565b916080818403910152610476565b9092612e1c90612e156103ba9694612e0b60808601975f870152565b60ff166020850152565b6040830152565b6060818403910152610476565b909190612e3f612e3960016128c1565b8261290c565b50612e5f85612e5781612e5185611a49565b87613257565b848685613d2e565b94612e68815190565b612e74611ffc5f61163a565b03612ec15750612ebb612ea77fb8e138887d0aa13bab447e82de9d5c1777041ecd21ca36ba824ff1e6c07ddda49461143f565b9486612eb260405190565b94859485612def565b0390a290565b612ebb90612eef7fe2babfbac5889a709b63bb7f598b324e08bc5a4fb9ec647fb3cbc9ec07eb87129561143f565b9587612efa60405190565b95869586612da5565b7fe770710421fd2cad75ad828c61aa98f2d77d423a440b67872d0f65554148e00090565b6103ba9190612f3581613e19565b939150612f43825b9161174e565b11612f4f575050612266565b61228c9250612f5d90613e75565b90613ead565b9160206103a492949361177760408201965f83019061175d565b6103a4906001612f8b61362f565b017fc565b045403dc03c2eea82b81a0465edad9e2e7fc4d97e11421c209da93d7a9382612fb7836122c4565b612fcc612fc360405190565b92839283612f63565b0390a1611733565b9080612fde825190565b91612fe9603461163a565b83106130845761301061301d91613008613003603461163a565b860390565b016020015190565b6001600160b01b03191690565b692370726f706f7365723d60b01b906001600160b01b0319160361307c576130619161305b91613055613050602a61163a565b830390565b90613f4f565b91901590565b91821561306d57505090565b6127019192506116d3906104f2565b505050600190565b50505050600190565b6103ba94939291906141b0565b6103ba614396565b6103a4906130ae61439e565b6103a4906130c36130bd611c00565b82614597565b6145c0565b6103a4906130a2565b906103a492916130df61439e565b906103a492916145f2565b906103a492916130d1565b6103a461439e565b6103a46130f5565b6103a49061311161439e565b6103a490614629565b6103a490613105565b6103a49061312f61439e565b6103a49061463e565b6103a490613123565b6103a49061314d61439e565b6103a490614653565b6103a490613141565b7fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d10090565b6103ba600261163461315f565b6103ba600361163461315f565b909594926103a4946131d1610a71926131c76080966131c060a088019c5f890152565b6020870152565b60ff166040850152565b60608301906104fb565b6103ba939291612d8e612d9f926131ef5f90565b506131f86112e4565b61257f61320487613c4b565b8761320e60405190565b96879560208701958661319d565b905051906103a482610427565b90602082820312610393576103ba9161321c565b9160206103a4929493610a7160408201965f8301906104fb565b61329492506020919061326b6120a56126be565b9061327560405190565b809581948293613289633a46b1a860e01b90565b84526004840161323d565b03915afa908115612c3e575f916132a9575090565b6103ba915060203d6020116132cb575b6132c38183610565565b810190613229565b503d6132b9565b91908203918211611d2257565b6103ba9060301c61225a565b6103ba90546132df565b6133026103ba6103ba9290565b61225a565b80545b6133135f61163a565b81036133245750506103ba5f6132f5565b6133505f91613346611ffc846103ba960192613340600161163a565b906132d2565b5f5260205f200190565b016132eb565b9160206103a4929493611b0d60408201965f8301906104fb565b6103a4905f61337d6133f1565b017f08f74ea46ef7894f65eabfb5e6e695de773a000b47c529ab559178069b2264016133ab6120a58361165d565b6133b48461143f565b906133ca6133c160405190565b92839283613356565b0390a161201f565b6103ba5f6133de61362f565b01611ba0565b9091906103a4575061465c565b7f0d5829787b8befdbc6044ef7457d8a95c2a04bc99235349f1a212c063e59d40090565b6123376103ba6103ba9290565b6103bd9061163a565b6020810192916103a49190613422565b6103bd9061271b565b9160206103a492949361345e60408201965f83019061343b565b019061343b565b9063ffffffff60301b9060301b61171a565b6123376103ba6103ba9263ffffffff1690565b9061349a6103ba61174a92613477565b8254613465565b6134a961362f565b906134b35f613415565b63ffffffff82161461350e5760016103a492017f7e3f7f0708a84de9203036abaa450dccc85ad5ff52f78c170f3edb55cf5e8828826134f183612711565b6135066134fd60405190565b92839283613444565b0390a161348a565b63f1cfbf0560e01b5f9081526116fa81600461342b565b6103ba611c11565b906129ec6103ba61174a9261163a565b6103a4905f61354a61362f565b017fccb45da8d5717e6c4544694297c4ba5cf151d455c9bb0ed4fc7a38411bc054618261357683611ba0565b61358261285a60405190565b0390a161352d565b6135956120a56126be565b9060206135a160405190565b632394e7a360e21b81526004810183905292839060249082905afa908115612c3e576103ba925f926135e6575b506135d890611ca8565b6135e0612245565b916146c0565b6135d89192506136049060203d6020116132cb576132c38183610565565b91906135ce565b7f3ba4977254e415696610a40ebf2258dbfa0ec6a2ff64e84bfe715ff16977cc0090565b7ed7616c8fe29c6c2fbe1d0c5bc8f2faa4c35b43746e70b24b4d532752affd0090565b6103ba603161163a565b915f1960089290920291821b911b61171a565b919061367e6103ba61174a9390565b90835461365c565b6103a4915f9161366f565b908161369c816129a8565b926136a961299082612979565b6136b28561296d565b146136f8576136f260016103a49301946136e25f6136dd836136d7611e1d828c6129cb565b996129cb565b613686565b6136ec6001612983565b90612995565b90612aba565b612a7b613652565b611ac36103ba6103ba9290565b6103bd90613700565b9160206103a4929493610a7160408201965f83019061370d565b6137406001600160d01b03612266565b811161374f576103ba906132f5565b6306dfcc6560e41b5f908152906116fa9060d06004613716565b9061377f5f610d22949361377a5f90565b500190565b6148de565b906137c96103a4959796946137bb6080956137ad610a719560a08801908882035f8a015261245c565b908682036020880152610ec2565b9084820360408601526124a0565b966060830190613422565b919461382961381e60a0956138106103a499613802610a71979d9c9a9d60c08a01908a82035f8c015261245c565b9088820360208a0152610ec2565b9086820360408801526124a0565b986060850190613422565b6080830152565b91908201809211611d2257565b939290916138496133f1565b9485906138586120a58361165d565b95602061386460405190565b63793d064960e11b815297889060049082905afa968715612c3e575f9761399c575b50906020856138a26120a561389c5f97966149e8565b9b61165d565b86896138cc8d6138b160405190565b998a968795869563b1c5f42760e01b5b875260048701613784565b03915afa918215612c3e576116876120a5935f936138f9968592613977575b50612a699060018501611647565b90813b15610393575f80969461392e87839761391460405190565b9a8b98899788966308f2a0bb60e41b8852600488016137d4565b03925af1908115612c3e576103ba9261394d92613952575b5042613830565b613e75565b61396a905f5b6139628183610565565b8101906103f2565b5f613946565b503d613958565b612a699192506139959060203d6020116132cb576132c38183610565565b91906138eb565b5f9392919750856138a26120a561389c6139c4602095863d88116132cb576132c38183610565565b9b9596975050505050613886565b634e487b715f526020526024601cfd5b9392906139ed6133f1565b936139fa6120a58661165d565b90613a0963e38335e5916149e8565b90823b1561039357613a316138c1925f8097613a2460405190565b998a988997889760e01b90565b039134905af1928315612c3e5760015f936136dd936103a496613a56575b5001611647565b613a6c90863d8811613970576139628183610565565b5f613a4f565b6103ba9060f01c611ac3565b6103ba9054613a72565b6103ba9060f81c611ac3565b6103ba9054613a88565b5f613ab06103ba83600161168161287c565b01613ac3613abd82613a7e565b91613a94565b90613b8757613b8157613ad581611a49565b613ade5f61163a565b8114613b6b57613aef611a6161223c565b90811115613b6557613b06611ffc612d588461237a565b10613b115750600190565b613b1d61199882614a05565b8015613b53575b15613b2f5750600390565b613b38906122ce565b613b44611ffc5f61163a565b03613b4e57600490565b600590565b50613b6061199882614a48565b613b24565b50505f90565b636ad0607560e01b5f9081526004839052602490fd5b50600290565b5050600790565b92613ba3929091613b9d6133f1565b94614af8565b9060018101613bb5611e1d8483611647565b91613bbf5f61163a565b8303613bcc575b50505090565b613bd9906120a59061165d565b803b1561039357613c065f93918492613bf160405190565b958693849283919063c4d252f560e01b612bdf565b03925af1918215612c3e57835f926136dd92613c2795613c2f575b50611647565b5f8080613bc6565b613c4590853d8711613970576139628183610565565b5f613c21565b613c55905f611df5565b6103ba613c6182611ba0565b91600183015b9061352d565b6103ba90613c79614b86565b6042916040519161190160f01b8352600283015260228201522090565b6004111561096757565b906103a482613c96565b9190823b613cba611ffc5f61163a565b03613ce85790613cc991614c62565b50613cdc613cd65f613ca0565b91613ca0565b14918261306d57505090565b6103ba92614baf565b9060ff9061171a565b90613d0a6103ba61174a92151590565b8254613cf1565b6003111561096757565b906103a482613d11565b6103ba90613d1b565b613d40919394506103ba90611ae75f90565b9160038301613d52611af78383611ab4565b613e0257613d65613d6a92600192611ab4565b613cfa565b613d76611ac35f613d25565b60ff821603613d9657506103ba90613c6783613d9183611ba0565b613830565b613da3611ac36001613d25565b60ff821603613dc1575060016103ba9101613c6783613d9183611ba0565b613dd8613dd1611ac36002613d25565b9160ff1690565b03613df15760026103ba9101613c6783613d9183611ba0565b6303599be160e11b5f908152600490fd5b6371c6af4960e01b5f9081526116fa836004610504565b805490613e255f61163a565b8203613e425750505f90613e385f6116fe565b906103ba5f6132f5565b5f91613346611ffc84613e5b940192613340600161163a565b0190613e6f613e69836122c4565b926132eb565b60019291565b613e8465ffffffffffff61174e565b8111613e93576103ba906116fe565b6306dfcc6560e41b5f908152906116fa9060306004613716565b9061330a90825490613ebe5f61163a565b9082613eca600561163a565b8111613ed8575b5084614f27565b80613340613ee892959395614cdb565b90613efa61170b5f6122eb858a613346565b613f0385610c94565b1015613f125750915b5f613ed1565b929150613f2990613f23600161163a565b90613830565b90613f0c565b6001600160f01b03191690565b81810292918115918404141715611d2257565b80613f5b6103ba825190565b84118015614038575b61402b57613fa9613f99613fb39285613f896103ba613f83600161163a565b83613830565b88119182613ff7575b5050151590565b613fa3600261163a565b90613f3c565b613d91602861163a565b613fc3611ffc612d5885876132d2565b03613fe757613fe293926103ba92613fda92614fa4565b939093612036565b611436565b505050613ff35f612043565b5f91565b016020015161400b9150613f2f565b613f2f565b61402361060f60f31b5b916001600160f01b03191690565b14855f613f92565b50505050613ff35f612043565b50838311613f64565b9065ffffffffffff60a01b9060a01b61171a565b906140656103ba61174a92611724565b8254614041565b9063ffffffff60d01b9060d01b61171a565b9061408e6103ba61174a92613477565b825461406c565b5f5b8281106140a357505050565b606082820152602001614097565b906103a46140c161215584612133565b601f190160208401614095565b906140da6124ac835190565b90816140ec6020830284019460200190565b925f915b8383106140ff57505050505090565b9091929394602061411b6124f783856001950387528951612496565b93019301919392906140f0565b95906141a2956141776103ba9b999a966141696141859461419b9861415c6141939960208f611b0d6101208201965f830152565b8c820360408e015261245c565b908a820360608c0152610ec2565b9088820360808a01526140ce565b9086820360a08801526124a0565b9560c0850152565b60e0830152565b610100818403910152610476565b9492909391946141bd5f90565b506141c661287c565b946141df836141d6611a1a825190565b208883856122af565b9687966141ea845190565b6141f8611ffc6103ba865190565b14158015614355575b8015614340575b61430e5760010161421d5f611a5b8b84611647565b614229611d0a5f6116fe565b036142e35791611fb393917f7d84a6263ae0d98d3329bd7b46bb4e8d6f98cd35a7adb45c274c8b7fd5ebd5e0979899959361427061426561223c565b613d91612f3d611aa3565b926142b65f61428a6103ba8b614284611510565b96611647565b016142958b8261201f565b6142a76142a187613e75565b82614055565b6142b0846150c1565b9061407e565b6142d06142c96142c4875190565b6140b1565b9285613830565b946142da60405190565b998a998a614128565b5f6116fa8a6142f181611aab565b6142fa8461163a565b6331b75e4d60e01b855291600485016128ec565b506116fa9161432c6143276143225f965190565b935190565b915190565b630447b05d60e41b85529160048501610a53565b50835161434f611ffc5f61163a565b14614208565b508351614366611ffc6103ba855190565b1415614201565b6103ba7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0061163a565b6103ba61436d565b6143a96119986150f7565b6143af57565b631afcd79f60e31b5f908152600490fd5b906103a4916143cd61439e565b614556565b634e487b7160e01b5f525f60045260245ffd5b919061367e6103ba61174a9361163a565b6103a4915f916143e5565b81811061440c575050565b806144195f6001936143f6565b01614401565b9190601f811161442e57505050565b61443e6103a4935f5260205f2090565b906020601f840181900483019310614460575b6020601f909101040190614401565b9091508190614451565b905f1960089091021c191690565b816144829161446a565b906002021790565b90614493815190565b906001600160401b038211610586576144b6826144b0855461154a565b8561441f565b602090601f83116001146144e35761174a92915f91836144d8575b5050614478565b015190505f806144d1565b601f198316916144f6855f5260205f2090565b925f5b8181106145345750916002939185600196941061451a575b50505002019055565b61452a910151601f84169061446a565b90555f8080614511565b919360206001819287870151815501950192016144f9565b906103a49161448a565b61457b6103a49261457261456861315f565b936002850161454c565b6003830161454c565b60016145865f61163a565b9161459183826129de565b016129de565b906103a4916143c0565b6103a4906145ad61439e565b6103a4905f6145ba61287c565b0161454c565b6103a4906145a1565b906103a492916145d761439e565b6103a492916145e86145ed92612f7d565b6134a1565b61353d565b906103a492916145c9565b6103a49061460961439e565b6103a4905f6146226120a561461c61360b565b9361143f565b910161201f565b6103a4906145fd565b6103a49061152461439e565b6103a490614632565b6103a49061229d61439e565b6103a490614647565b805161466a611ffc5f61163a565b111561467857602081519101fd5b63d6bda27560e01b5f908152600490fd5b634e487b7160e01b5f52601260045260245ffd5b81156146a7570490565b614689565b6103ba601261163a565b6103ba601161163a565b919291905f906146d08184615109565b9390926146dc5f61163a565b84146147df57838711156147b85792866103ba9697936147289361473b965009808603951090036001614716846147125f61163a565b0390565b841680809504960493805f0304010290565b179161473b61473f8261473b600361163a565b0290565b6147126147b26147ac61479d61478e61477f6147706002976147608961163a565b1861473b8b82026147128b61163a565b61473b8a82026147128a61163a565b61473b8982026147128961163a565b61473b8882026147128861163a565b61473b8782026147128761163a565b80950290565b9161163a565b612a7b876147c8611ffc5f61163a565b146147d16146ac565b6147d96146b6565b9161511c565b50505050916103ba919261469d565b6103ba604061058b565b906103bd90610c94565b906103bd9061225a565b8054821015611889576148246001915f5260205f2090565b910201905f90565b6103ba9051610c94565b6103ba905161225a565b9065ffffffffffff199060301b61171a565b6133026103ba6103ba9261225a565b906148716103ba61174a92614852565b8254614840565b6103a49161489b9060209061489561488f8261482c565b85611733565b01614836565b90614861565b91906148b0576103a491614878565b6143d2565b80549190600160401b83101561058657826148d89160016103a49501815561480c565b906148a1565b91929180546148ec5f61163a565b811115614996576149106149055f92613340600161163a565b835f5260205f200190565b0161491a816122c4565b90614924816132eb565b9361492e81610c94565b61493784610c94565b1161498557869261494a611d0a83610c94565b0361495a5750611ffc9250614861565b915050611ffc9161497361496c6147ee565b92836147f8565b6149808660208401614802565b6148b5565b632520601d60e01b5f908152600490fd5b50906149b4916149a761496c6147ee565b6149808560208401614802565b611ffc5f6132f5565b6149d26149cc6103ba926104e6565b60601b90565b6001600160601b03191690565b6103ba906149bd565b614a016149fc6149f73061143f565b6149df565b6149d2565b1890565b614a43611ffc6103ba614a2a61141d614a246103ba875f611681612c68565b95611a49565b93613f236002614a3c60018401611ba0565b9201611ba0565b111590565b6103ba614a5691611ae75f90565b614a6c611ffc6103ba5f611bd460018601611ba0565b1190565b614a7c9060ff16613dd1565b019060ff8211611d2257565b60ff1660ff8111611d225760020a90565b6103ba6128e7614ac4614abf614aaf6007610976565b614ab96001613700565b90614a70565b614a88565b613340600161163a565b906001600160f81b03199060f81b61171a565b90614af16103ba61174a92151590565b8254614ace565b614b565f91614b1f600196614b5c968896614b105f90565b50614b1961287c565b946122af565b958691613a4f614b2d614a99565b614b3760026128c1565b614b4160066128c1565b90614b4c60076128c1565b921818188461290c565b01614ae1565b7f789cf55be980739dad1d0699b93b58e806b51c9d96619bfa8fe0a28abaa7b30c61196960405190565b6103ba615164565b9081526040602082018190526103ba92910190610476565b6103ba90610376565b915f92614bf38493614bbe5f90565b50614be4614bcb60405190565b630b135d3f60e11b602082015294859260248401614b8e565b60208201810382520383610565565b602082519201905afa614c046123f2565b81614c43575b81614c13575090565b614c2d91506020614c22825190565b818301019101613229565b612701611ffc6103ba630b135d3f60e11b614ba6565b9050614c4d815190565b614c5a611ffc602061163a565b101590614c0a565b905f91614c6d825190565b614c7a611ffc604161163a565b03614ca357614c9c9250602082015190606060408401519301515f1a906151e5565b9192909190565b509050614cba6128e7614cb55f612043565b925190565b909160029190565b6103ba90614cd6611ffc6103ba9460ff1690565b901c90565b6001614ce68161163a565b821115614f235790614e2e614e296103ba614e22614dee614dee614e18614df3614dee614e0e614dee614dee8c6104aa6103ba9f614de4614dee614dfd614e0793614dd4614dce88614d378461163a565b90614d45600160801b61163a565b8b1015614efb575b614d5a600160401b61163a565b811015614ed9575b614d6f600160201b61163a565b811015614eb7575b614d836201000061163a565b811015614e95575b614d9661010061163a565b811015614e73575b614da8601061163a565b811015614e4b575b614dbd611ffc600461163a565b1015614e33575b61473b600361163a565b91613700565b9e8f9c8d809b8197828096614cc2565b6104aa818d61469d565b614cc2565b6104aa818a61469d565b6104aa818761469d565b809261469d565b6104aa818c61469d565b6104aa818961469d565b809461469d565b821190565b900390565b614e4690614e4085613700565b906128a8565b614dc4565b614e62614e6d91614e5c6004613700565b90614cc2565b91614e406002613700565b90614db0565b614e84614e8f91614e5c6008613700565b91614e406004613700565b90614d9e565b614ea6614eb191614e5c6010613700565b91614e406008613700565b90614d8b565b614ec8614ed391614e5c6020613700565b91614e406010613700565b90614d77565b614eea614ef591614e5c6040613700565b91614e406020613700565b90614d62565b50614f1d614f12614f0c6080613700565b8c614cc2565b91614e406040613700565b90614d4d565b5090565b93919092614f325f90565b505b80821015614f8c57614f46818361529a565b90614f5a5f6122eb84895f5260205f200190565b614f66611d0a87610c94565b1115614f755750915b91614f34565b929150614f8690613f23600161163a565b90614f6f565b925050915090565b6103ba6103ba6103ba9260ff1690565b90929190600191614fc16103ba614fbb600161163a565b87613830565b81118061508c575b90614fea614fdb613f99869594151590565b614fe45f61163a565b97613830565b935b614ffb575b5050505060019190565b909192946150068290565b8610156150865761503261502d6150208886602001015190565b6001600160f81b03191690565b6152da565b9061503d600f613700565b60ff8316116150745761506b916104aa61505e61506493613fa3601061163a565b91614f94565b9560010190565b92919082614fec565b505050505090505f906103ba5f61163a565b94614ff1565b50614fea614fdb613f996150a66140068987602001015190565b6150b761401561060f60f31b613f2f565b1492505050614fc9565b6150ce63ffffffff61271b565b81116150dd576103ba90613415565b6306dfcc6560e41b5f908152906116fa9060206004613716565b6103ba5f61510361309a565b01611e2e565b905f198183099102908180821091030391565b61473b83614a019361512b5f90565b501891151590565b909594926103a49461515d611b0d926151566080966131c060a088019c5f890152565b6040850152565b6060830152565b7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6151b86151906153ac565b615198615427565b9061257f6151a53061143f565b6040519586946020860194469286615133565b6151c3611a1a825190565b2090565b610a716103a494612e15606094989795612e0b608086019a5f870152565b90916151f084612551565b615212611ffc6fa2a8918ca85bafe22016d0b997e4df60600160ff1b0361163a565b1161528757906152336020945f949361522a60405190565b948594856151c7565b838052039060015afa15612c3e575f5161524c5f612043565b615255816104f2565b61525e836104f2565b14615274575061526d5f61163a565b90915f9190565b905061527f5f61163a565b909160019190565b5050506152935f612043565b9160039190565b613f236103ba926152a85f90565b5080831692186152b8600261163a565b9061469d565b611ac36103ba6103ba9260ff1690565b6103ba9060f81c6152be565b6152e3906152ce565b806152ee602f613700565b60ff83161180615397575b15615315576103ba915061530d6030613700565b900360ff1690565b61531f6060613700565b60ff83161180615382575b1561533e576103ba915061530d6057613700565b506153496040613700565b60ff8216118061536d575b15615367576103ba9061530d6037613700565b5060ff90565b506153786047613700565b60ff821610615354565b5061538d6067613700565b60ff83161061532a565b506153a2603a613700565b60ff8316106152f9565b6153b461315f565b6153bf6103ba613183565b906153c8825190565b6153d4611ffc5f61163a565b11156153e657506151c3611a1a825190565b6153f09150611ba0565b6153f95f61163a565b81146154025790565b507fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47090565b61542f61315f565b61543a6103ba613190565b90615443825190565b61544f611ffc5f61163a565b111561546157506151c3611a1a825190565b6153f09150600101611ba056fea2646970667358221220118f3b52cba92dce33bd61d31e2f09521127dee95dab3924fe430e92787dd18964736f6c634300081c0033
Deployed Bytecode
0x60806040526004361015610022575b3615610018575f80fd5b6100206126ca565b005b5f3560e01c806301ffc9a71461037157806302a251a31461036c57806306f3f9e61461036757806306fdde0314610362578063143489d01461035d578063150b7a0214610358578063160cbed7146103535780632656227d1461034e5780632d63f693146103495780632fe3e2611461034457806336834b061461033f5780633932abb11461033a5780633e4f49e6146103355780634385963214610330578063452115d61461032b578063481c6a75146103265780634bf5d7e914610321578063544ffc9c1461031c57806354fd4d501461031757806356781388146103125780635b8d0e0d1461030d5780635f398a141461030857806360c4247f1461030357806379051887146102fe5780637b3c71d3146102f95780637d5e81e2146102f45780637ecebe00146102ef57806380626478146102ea57806384b0196e146102e55780638ff262e3146102e057806391ddadf4146102db57806397c3d334146102d65780639a802a6d146102d1578063a7713a70146102cc578063a890c910146102c7578063a8f8a668146102c2578063a9a95294146102bd578063ab58fb8e146102b8578063b58131b0146102b3578063bc197c81146102ae578063c01f9e37146102a9578063c28bc2fa146102a4578063c59057e41461029f578063d0ebdbe71461029a578063d33219b414610295578063dd4e2ba514610290578063deaaa7cc1461028b578063e540d01d14610286578063eb9019d414610281578063ece40cc11461027c578063f23a6e6114610277578063f8ce560a146102725763fc0c546a0361000e57611461565b611407565b6113e8565b61138f565b611373565b61133f565b611310565b6112c9565b6112ae565b611296565b611277565b611260565b611222565b611203565b611165565b61114a565b61112e565b61110f565b6110f7565b6110c8565b6110ac565b611050565b611029565b610ff1565b610f8c565b610ea3565b610ddf565b610dac565b610d26565b610cc9565b610c79565b610c5a565b610bd2565b610af3565b610a9f565b610a75565b610a38565b610a1d565b6109fe565b6109e2565b610998565b61092e565b610913565b6108f8565b6108b1565b610897565b610878565b610678565b610514565b6104bf565b61044e565b6103fc565b6103c1565b6001600160e01b03191690565b61038c81610376565b0361039357565b5f80fd5b905035906103a482610383565b565b90602082820312610393576103ba91610397565b90565b9052565b34610393576103ee6103dc6103d73660046103a6565b611488565b60405191829182901515815260200190565b0390f35b5f91031261039357565b346103935761040c3660046103f2565b6103ee610417611510565b6040519182918290815260200190565b8061038c565b905035906103a482610427565b90602082820312610393576103ba9161042d565b346103935761046661046136600461043a565b61152d565b604051005b90825f9392825e0152565b6104976104a06020936104aa9361048b815190565b80835293849260200190565b9586910161046b565b601f01601f191690565b0190565b60208082526103ba92910190610476565b34610393576104cf3660046103f2565b6103ee6104da611628565b604051918291826104ae565b6001600160a01b031690565b6103ba906104e6565b6103bd906104f2565b6020810192916103a491906104fb565b34610393576103ee61052f61052a36600461043a565b611667565b60405191829182610504565b61038c816104f2565b905035906103a48261053b565b634e487b7160e01b5f52604160045260245ffd5b90601f01601f191681019081106001600160401b0382111761058657604052565b610551565b906103a461059860405190565b9283610565565b6001600160401b03811161058657602090601f01601f19160190565b90825f939282370152565b909291926105db6105d68261059f565b61058b565b9381855281830111610393576103a49160208501906105bb565b9080601f83011215610393578160206103ba933591016105c6565b90608082820312610393576106258183610544565b926106338260208501610544565b92610641836040830161042d565b9260608201356001600160401b038111610393576103ba92016105f5565b6103bd90610376565b6020810192916103a4919061065f565b34610393576103ee61069761068e366004610610565b929190916116ab565b60405191829182610668565b6001600160401b0381116105865760208091020190565b909291926106ca6105d6826106a3565b938185526020808601920283019281841161039357915b8383106106ee5750505050565b602080916106fc8486610544565b8152019201916106e1565b9080601f83011215610393578160206103ba933591016106ba565b909291926107326105d6826106a3565b938185526020808601920283019281841161039357915b8383106107565750505050565b60208091610764848661042d565b815201920191610749565b9080601f83011215610393578160206103ba93359101610722565b9291906107996105d6826106a3565b93818552602080860192028101918383116103935781905b8382106107bf575050505050565b81356001600160401b038111610393576020916107df87849387016105f5565b8152019101906107b1565b9080601f83011215610393578160206103ba9335910161078a565b6080818303126103935780356001600160401b038111610393578261082b918301610707565b9260208201356001600160401b038111610393578361084b91840161076f565b926040830135906001600160401b038211610393576060610871826103ba9487016107ea565b940161042d565b34610393576103ee61041761088e366004610805565b9291909161177e565b6103ee6104176108a8366004610805565b92919091611898565b34610393576103ee6104176108c736600461043a565b611a49565b7f3e83946653575f9a39005e1545185629e92736b7528ab20ca3816f315424a81190565b6103ba6108cc565b34610393576109083660046103f2565b6103ee6104176108f0565b34610393576109233660046103f2565b6103ee6104da611a9b565b346103935761093e3660046103f2565b6103ee610417611aa3565b634e487b7160e01b5f52602160045260245ffd5b6008111561096757565b610949565b906103a48261095d565b6103ba9061096c565b6103bd90610976565b6020810192916103a4919061097f565b34610393576103ee6109b36109ae36600461043a565b611aab565b60405191829182610988565b9190604083820312610393576103ba9060206109db828661042d565b9401610544565b34610393576103ee6103dc6109f83660046109bf565b90611ad3565b34610393576103ee610417610a14366004610805565b92919091611b14565b3461039357610a2d3660046103f2565b6103ee61052f611b5c565b3461039357610a483660046103f2565b6103ee6104da611b91565b9081526060810193926103a4929091604091610a71905b6020830152565b0152565b34610393576103ee610a90610a8b36600461043a565b611baa565b60405191939193849384610a53565b3461039357610aaf3660046103f2565b6103ee6104da611c00565b60ff811661038c565b905035906103a482610aba565b9190604083820312610393576103ba906020610aec828661042d565b9401610ac3565b34610393576103ee610417610b09366004610ad0565b90611c19565b909182601f83011215610393578135916001600160401b03831161039357602001926001830284011161039357565b919060c08382031261039357610b54818461042d565b92610b628260208301610ac3565b92610b708360408401610544565b9260608301356001600160401b0381116103935781610b90918501610b0f565b909390929060808101356001600160401b0381116103935783610bb49183016105f5565b9260a08201356001600160401b038111610393576103ba92016105f5565b34610393576103ee610417610be8366004610b3e565b95949094939193611c37565b919060808382031261039357610c0a818461042d565b92610c188260208301610ac3565b9260408201356001600160401b0381116103935783610c38918401610b0f565b909390929060608201356001600160401b038111610393576103ba92016105f5565b34610393576103ee610417610c70366004610bf4565b93929092611c90565b34610393576103ee610417610c8f36600461043a565b611ca8565b65ffffffffffff1690565b61038c81610c94565b905035906103a482610c9f565b90602082820312610393576103ba91610ca8565b3461039357610466610cdc366004610cb5565b611cd2565b9160608383031261039357610cf6828461042d565b92610d048360208301610ac3565b9260408201356001600160401b03811161039357610d229201610b0f565b9091565b34610393576103ee610417610d3c366004610ce1565b92919091611cdb565b906080828203126103935781356001600160401b0381116103935781610d6c918401610707565b9260208301356001600160401b0381116103935782610d8c91850161076f565b9260408101356001600160401b03811161039357836106419183016107ea565b34610393576103ee610417610dc2366004610d45565b92919091611d46565b90602082820312610393576103ba91610544565b34610393576103ee610417610df5366004610dcb565b611de7565b6103ba906104f2565b61038c81610dfa565b905035906103a482610e03565b63ffffffff811661038c565b905035906103a482610e19565b60e0818303126103935780356001600160401b0381116103935782610e589183016105f5565b92610e668360208401610e0c565b92610e748160408501610e0c565b92610e828260608301610ca8565b926103ba610e938460808501610e25565b9360c06109db8260a0870161042d565b3461039357610466610eb6366004610e32565b959490949391936120e0565b90610ee2610edb610ed1845190565b8084529260200190565b9260200190565b905f5b818110610ef25750505090565b909192610f0f610f086001928651815260200190565b9460200190565b929101610ee5565b93959194610f6e610f66610f7f95610f58610f78956103ba9c9a610f4b60e08c01925f8d01906001600160f81b0319169052565b8a820360208c0152610476565b9088820360408a0152610476565b976060870152565b60808501906104fb565b60a0830152565b60c0818403910152610ec2565b3461039357610f9c3660046103f2565b6103ee610fa7612168565b93610fb797959793919360405190565b97889788610f17565b9060808282031261039357610fd5818361042d565b92610fe38260208501610ac3565b926106418360408301610544565b34610393576103ee610417611007366004610fc0565b929190916121fa565b6103bd90610c94565b6020810192916103a49190611010565b34610393576110393660046103f2565b6103ee61104461223c565b60405191829182611019565b34610393576110603660046103f2565b6103ee610417612245565b91606083830312610393576110808284610544565b9261108e836020830161042d565b9260408201356001600160401b038111610393576103ba92016105f5565b34610393576103ee6104176110c236600461106b565b9161224f565b34610393576110d83660046103f2565b6103ee610417612275565b90602082820312610393576103ba91610e0c565b346103935761046661110a3660046110e3565b6122a6565b34610393576103ee610417611125366004610805565b929190916122af565b34610393576103ee6103dc61114436600461043a565b50600190565b34610393576103ee61041761116036600461043a565b6122ce565b34610393576111753660046103f2565b6103ee6104176122f1565b91909160a081840312610393576111978382610544565b926111a58160208401610544565b9260408301356001600160401b03811161039357826111c591850161076f565b9260608101356001600160401b03811161039357836111e591830161076f565b9260808201356001600160401b038111610393576103ba92016105f5565b34610393576103ee610697611219366004611180565b939290926122f9565b34610393576103ee61041761123836600461043a565b61237a565b91606083830312610393576112528284610544565b92610d04836020830161042d565b61046661126e36600461123d565b92919091612443565b34610393576103ee61041761128d366004610805565b9291909161255a565b34610393576104666112a9366004610dcb565b61259c565b34610393576112be3660046103f2565b6103ee61052f6125df565b34610393576112d93660046103f2565b6103ee6104da612629565b7ff2aad550cf55f045cb27e9c559f9889fdfb6e6cdaa032301d6ea397784ae51d790565b6103ba6112e4565b34610393576113203660046103f2565b6103ee610417611308565b90602082820312610393576103ba91610e25565b346103935761046661135236600461132b565b612646565b9190604083820312610393576103ba9060206108718286610544565b34610393576103ee610417611389366004611357565b9061264f565b34610393576104666113a236600461043a565b612676565b91909160a081840312610393576113be8382610544565b926113cc8160208401610544565b926113da826040850161042d565b926111e5836060830161042d565b34610393576103ee6106976113fe3660046113a7565b9392909261267f565b34610393576103ee61041761141d36600461043a565b6126b5565b6114316103ba6103ba926104e6565b6104e6565b6103ba90611422565b6103ba90611436565b6103bd9061143f565b6020810192916103a49190611448565b34610393576114713660046103f2565b6103ee61147c6126be565b60405191829182611451565b6366defe7760e11b9061149a82610376565b6114a382610376565b149182156114ea575b5081156114c8575b81156114be575090565b6103ba91506126e8565b90506114da630271189760e51b610376565b6114e382610376565b14906114b4565b9091506114ff9063151f14cd60e31b18610376565b61150882610376565b14905f6114ac565b6103ba61272e565b6103a490611524612749565b6103a4906127e6565b6103a490611518565b634e487b7160e01b5f52602260045260245ffd5b906001600283049216801561156a575b602083101461156557565b611536565b91607f169161155a565b80545f9392916115906115868361154a565b8085529360200190565b91600181169081156115df57506001146115a957505050565b6115ba91929394505f5260205f2090565b915f925b8184106115cb5750500190565b8054848401526020909301926001016115be565b92949550505060ff1916825215156020020190565b906103ba91611574565b906103a46116189261160f60405190565b938480926115f4565b0383610565565b6103ba906115fe565b6103ba5f61163461287c565b0161161f565b6103ba6103ba6103ba9290565b906116519061163a565b5f5260205260405f2090565b6103ba90546104f2565b5f6116876103ba926116765f90565b50600161168161287c565b01611647565b0161165d565b6116a66116a06103ba9263ffffffff1690565b60e01b90565b610376565b505050506116b65f90565b506116bf6128a0565b6116d96116d36116ce3061143f565b6104f2565b916104f2565b036116eb576103ba63150b7a0261168d565b637485328f60e11b5f90815260045b035ffd5b61170b6103ba6103ba9290565b610c94565b9065ffffffffffff905b9181191691161790565b61170b6103ba6103ba92610c94565b906117436103ba61174a92611724565b8254611710565b9055565b6103ba6103ba6103ba92610c94565b6103bd9061174e565b9081526040810192916103a4916020905b019061175d565b926117bc919261178b5f90565b5061179461287c565b936117a1838383896122af565b956117b56117af60046128c1565b8861290c565b5086612958565b906117c65f6116fe565b6117cf83610c94565b1461182457816118117f9a2e42fd6722813d69113e7d0079d3d940171428df7373df9c7f7617cfda289293600161180b878261181e9701611647565b01611733565b6040519182918583611766565b0390a190565b634844252360e11b5f908152600490fd5b9060ff60f01b9060f01b61171a565b906118546103ba61174a92151590565b8254611835565b634e487b7160e01b5f52603260045260245ffd5b90611878825190565b811015611889576020809102010190565b61185b565b6103ba90516104f2565b90926118a261287c565b926118af828287866122af565b946118ce6118bd60046128c1565b6118c760056128c1565b178761290c565b506001936118ea60015f6118e48a838b01611647565b01611844565b6118f26128a0565b946118fc3061143f565b956119096116d3886104f2565b036119a1575b509061191d93929187612a80565b6119316116d361192b6128a0565b926104f2565b141580611988575b611976575b507f712ae1383f79ac853f8d882153778e0260ef8f03b504e2866e0593e04d2b291f61196960405190565b828152806020810161181e565b61198290600201612ad1565b5f61193e565b5061199c61199860028301612a8d565b1590565b611939565b806119ab5f61163a565b905b6119b8575b5061190f565b6119c36103ba845190565b811015611a2e57806119e06119db6119f7938661186f565b61188e565b6119ec6116d38a6104f2565b146119fd5760010190565b816119ad565b611a2860028a01611a0e838961186f565b51611a21611a1a825190565b9160200190565b2090612a1d565b60010190565b6119b2565b6103ba9060a01c610c94565b6103ba9054611a33565b611a615f611a5b6103ba936116765f90565b01611a3f565b61174e565b90611a736105d68361059f565b918252565b611a826005611a66565b640312e302e360dc1b602082015290565b6103ba611a78565b6103ba611a93565b6103ba612aeb565b6103ba90612b2f565b906116519061143f565b6103ba905b60ff1690565b6103ba9054611abe565b6103ba916003611af1611af793611ae75f90565b505f611681612c68565b01611ab4565b611ac9565b9081526040810192916103a4916020905b01906104fb565b93929190611b24838383886122af565b9433611b336119988289612c8c565b611b4357506103ba949550612cc6565b638fe5d8a960e01b5f908152906116fa90886004611afc565b6103ba5f61165d565b611b6f600e611a66565b6d06d6f64653d74696d657374616d760941b602082015290565b6103ba611b65565b6103ba611b89565b6103ba9081565b6103ba9054611b99565b6103ba611bb891611ae75f90565b90611bc282611ba0565b90611bdb6002611bd460018601611ba0565b9401611ba0565b91929190565b611beb6001611a66565b603160f81b602082015290565b6103ba611be1565b6103ba611bf8565b6103ba5f611a66565b6103ba611c08565b6103ba9133611c26611c11565b92612cd2565b6103ba9136916105c6565b93919695611998611c6091949294611c4c5f90565b5087611c588686611c2c565b8b888a612d2a565b611c79576103ba959691611c7391611c2c565b92612e29565b6394ab6c0760e01b5f9081526116fa886004610504565b91611c736103ba9594611ca05f90565b503392611c2c565b6103ba90611cb85f6104aa612f03565b612f27565b6103a490611cc9612749565b6103a490612f7d565b6103a490611cbd565b91611c266103ba94611ca05f90565b634e487b7160e01b5f52601160045260245ffd5b611d0a611d1091610c94565b91610c94565b90039065ffffffffffff8211611d2257565b611cea565b604090610a716103a49496959396610a6a60608401985f8501906104fb565b939290913392611d596119988486612fd4565b611dd057611d656122f1565b95611d6f5f61163a565b8711611d81575b6103ba95965061308d565b611da8611da2611a61611d9261223c565b611d9c60016116fe565b90611cfe565b8661264f565b878110611db55750611d76565b636121770b60e11b5f908152906116fa908990886004611d27565b63d9b3955760e01b5f9081526116fa856004610504565b611e1d6103ba91611df55f90565b505f7f5ab42ced628888259c08ac98db1eb0cf702fc1501344311d8b100cd1bfe4bb00611af1565b611ba0565b6103ba9060401c611ac3565b6103ba9054611e22565b6103ba905b6001600160401b031690565b6103ba9054611e38565b611e3d6103ba6103ba9290565b906001600160401b039061171a565b6103ba90611e3d906001600160401b031682565b90611e936103ba61174a92611e6f565b8254611e60565b9060ff60401b9060401b61171a565b90611eb96103ba61174a92151590565b8254611e9a565b6103bd90611e53565b6020810192916103a49190611ec0565b929490959193611ee761309a565b958695611eff611ef961199889611e2e565b97611e49565b98611f095f611e53565b6001600160401b038b161480612009575b60019a611f36611f298d611e53565b916001600160401b031690565b149081611fe1575b155b9081611fd8575b50611fc757611f709688611f675f611f5e8e611e53565b9c019b8c611e83565b611fb85761204c565b611f78575050565b7fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d291611fa75f611fb393611ea9565b60405191829182611ec9565b0390a1565b611fc28b8b611ea9565b61204c565b63f92ee8a960e01b5f908152600490fd5b1590505f611f47565b9050611f40611fef3061143f565b3b612000611ffc5f61163a565b9190565b14919050611f3e565b5087611f1a565b906001600160a01b039061171a565b9061202f6103ba61174a9261143f565b8254612010565b6114316103ba6103ba9290565b6103ba90612036565b946120689192946120759461206361208c986130c8565b6130ea565b6120706130fd565b61311a565b612087612082600161163a565b613138565b613156565b612096815f61201f565b6120b06120aa6120a55f612043565b61143f565b9161143f565b907f605c2dbf762e5f7d60a546d42e7205dcb1b011ebc62a61736a57c9089d3a43506120db60405190565b5f90a3565b906103a4969594939291611ed9565b156120f657565b60405162461bcd60e51b81526020600482015260156024820152741152540dcc4c8e88155b9a5b9a5d1a585b1a5e9959605a1b6044820152606490fd5b90611a736105d6836106a3565b369037565b906103a461215b61215584612133565b936106a3565b601f190160208401612140565b61219661217361315f565b61217c81611ba0565b612188611ffc5f61163a565b1490816121da575b506120ef565b61219e613183565b906121a7613190565b906121b13061143f565b6121ba5f61163a565b6121cb6121c65f61163a565b612145565b600f60f81b9594934693929190565b6121e79150600101611ba0565b6121f3611ffc5f61163a565b145f612190565b9193926119986122149161220b5f90565b508684866131db565b612225576103ba9293611c26611c11565b6394ab6c0760e01b5f9081526116fa856004610504565b6103ba426116fe565b6103ba606461163a565b6103ba929190613257565b6001600160d01b031690565b6103ba6103ba6103ba9261225a565b6103ba61228c6122875f6104aa612f03565b613307565b612266565b6103a49061229d612749565b6103a490613370565b6103a490612291565b6103ba9392919061255a565b6103ba90610c94565b6103ba90546122bb565b611a6160016122eb6103ba936122e15f90565b508261168161287c565b016122c4565b6103ba6133d2565b50505050506123055f90565b5061230e6128a0565b61231d6116d36116ce3061143f565b036116eb576103ba63bc197c8161168d565b6103ba9060d01c5b63ffffffff1690565b6103ba905461232f565b61170b6103ba6103ba9263ffffffff1690565b611d0a61236991610c94565b019065ffffffffffff8211611d2257565b611a616103ba916123885f90565b506123be6123b95f6123b3600161239d61287c565b01946123ad83611a5b8389611647565b95611647565b01612340565b61234a565b9061235d565b906103a49392916123d3612749565b612410565b90916104aa90839080936105bb565b90916103ba926123d8565b3d1561240b576124013d611a66565b903d5f602084013e565b606090565b612440935f9392849361242e61242560405190565b938492836123e7565b03925af161243a6123f2565b906133e4565b50565b906103a49392916123c4565b906104aa816020936104fb565b9061246b610edb610ed1845190565b905f5b81811061247b5750505090565b90919261248e610f08600192865161244f565b92910161246e565b906103ba91610476565b906124b66124ac835190565b8083529160200190565b90816124c86020830284019460200190565b925f915b8383106124db57505050505090565b909192939460206124fe6124f783856001950387528951612496565b9760200190565b93019301919392906124cc565b9493916103a49361253e61254c9261253060609560808b01908b82035f8d015261245c565b9089820360208b0152610ec2565b9087820360408901526124a0565b940152565b6103ba9061163a565b9061258b9161257f6103ba9561256d5f90565b5060405195869460208601948561250b565b90810382520382610565565b612596611a1a825190565b20612551565b6125a76116ce6128a0565b6125b0336104f2565b036125ce576120b06120aa6125c45f61165d565b6120a5845f61201f565b6354348f0360e01b5f908152600490fd5b6103ba6120a55f6116876133f1565b6125f86020611a66565b7f737570706f72743d627261766f2671756f72756d3d666f722c6162737461696e602082015290565b6103ba6125ee565b6103ba612621565b6103a49061263d612749565b6103a4906134a1565b6103a490612631565b6103ba9161265b613525565b91613257565b6103a49061266d612749565b6103a49061353d565b6103a490612661565b505050505061268b5f90565b506126946128a0565b6126a36116d36116ce3061143f565b036116eb576103ba63f23a6e6161168d565b6103ba9061358a565b6103ba5f61168761360b565b6126d26128a0565b6126e16116d36116ce3061143f565b036116eb57565b6127016126fb6301ffc9a760e01b610376565b91610376565b1490565b6103ba9060301c612337565b6103ba9054612705565b6103ba6103ba6103ba9263ffffffff1690565b6103ba612744600161273e61362f565b01612711565b61271b565b61275161287c565b6127596128a0565b33906127676116d3836104f2565b036127bb57506127756128a0565b6127846116d36116ce3061143f565b0361278c5750565b612796365f611c2c565b6127a1611a1a825190565b20905b6127b060028201613691565b8290036127a4575050565b6347096e4760e01b5f908152906116fa906004610504565b9081526040810192916103a49160200152565b6127ee612f03565b6127f6612245565b8083116128635750907f0553476bf02ef2726e8ce5ced78d63e26e602e4a2257b1f559418e24b46339979161284c6128355f612830612275565b930190565b61283d61223c565b61284685613730565b91613769565b5050611fb361285a60405190565b928392836127d3565b63243e544560e01b5f908152906116fa908460046127d3565b7f7c712897014dbe49c045ef1299aa2d5f9e67e48eea4403efa21f1e0f3ac0cb0090565b6103ba6125df565b6103ba906128bc611ffc6103ba9460ff1690565b901b90565b6128e76128d86103ba926128d25f90565b50610976565b6128e2600161163a565b6128a8565b61163a565b9081526060810193926103a4929091604091610a7190602083019061097f565b9061291682611aab565b91612920836128c1565b612935836129306103ba5f61163a565b921690565b1461293f57505090565b6331b75e4d60e01b5f908152926116fa929160046128ec565b6103ba949392919061383d565b6103ba9060801c5b6001600160801b031690565b6103ba9054612965565b6129906103ba6103ba9290565b61296d565b6103ba910161296d565b6103ba9061296d565b6103ba905461299f565b6103ba604161163a565b6129906103ba6103ba9261296d565b90611651906129bc565b905f199061171a565b906129ec6103ba61174a9290565b82546129d5565b906001600160801b03199060801b61171a565b90612a166103ba61174a926129bc565b82546129f3565b9081612a2881612979565b612a3b612a356001612983565b82612995565b92612a48612990846129a8565b612a518561296d565b14612a7357612a69612a6e9260016103a497016129cb565b6129de565b612a06565b612a7b6129b2565b6139d2565b906103a4949392916139e2565b612701612aa5612990612a9f84612979565b936129a8565b9161296d565b906001600160801b039061171a565b90612aca6103ba61174a926129bc565b8254612aab565b6103a4905f612adf81612983565b9101612a6e8282612aba565b6103ba611a6160016122eb61362f565b80151561038c565b905051906103a482612afb565b90602082820312610393576103ba91612b03565b6040513d5f823e3d90fd5b612b376133f1565b90612b4181613a9e565b612b4b600561096c565b612b548261096c565b03612c625750612b6b611e1d5f9260018501611647565b9101612b796120a58261165d565b6020612b8460405190565b632c258a9f60e11b81526004810185905291829060249082905afa908115612c3e575f91612c43575b5015612bba575050600590565b612bed91612bcc6120a560209361165d565b60405193849283918291632ab0f52960e01b5b835260048301526024820190565b03915afa908115612c3e575f91612c0f575b5015612c0a57600790565b600290565b612c31915060203d602011612c37575b612c298183610565565b810190612b10565b5f612bff565b503d612c1f565b612b24565b612c5c915060203d602011612c3757612c298183610565565b5f612bad565b91505090565b7fa1cefa0f43667ef127a258e673c94202a79b656e62899531c4376d87a7f3980090565b90612c9682611aab565b612ca8612ca25f61096c565b9161096c565b149182612cb457505090565b6127019192506116ce6116d391611667565b6103ba93929190613b8e565b916103ba9391612cdf5f90565b50612ce8613525565b93612e29565b90815260e081019796959094909390929091602086015260ff16604085015260608401612d1a916104fb565b608083015260a082015260c00152565b612d8e906103ba969561257f612d9f9596612d425f90565b50612d4b6108cc565b92612d5c612d588a613c4b565b9290565b612d67611a1a825190565b2090612d74611a1a825190565b209189612d8060405190565b988997602089019788612cee565b612d99611a1a825190565b20613c6d565b90613caa565b93612dd46103ba9694612dcd612de195612dc360a08a01965f8b0152565b60ff166020890152565b6040870152565b8482036060860152610476565b916080818403910152610476565b9092612e1c90612e156103ba9694612e0b60808601975f870152565b60ff166020850152565b6040830152565b6060818403910152610476565b909190612e3f612e3960016128c1565b8261290c565b50612e5f85612e5781612e5185611a49565b87613257565b848685613d2e565b94612e68815190565b612e74611ffc5f61163a565b03612ec15750612ebb612ea77fb8e138887d0aa13bab447e82de9d5c1777041ecd21ca36ba824ff1e6c07ddda49461143f565b9486612eb260405190565b94859485612def565b0390a290565b612ebb90612eef7fe2babfbac5889a709b63bb7f598b324e08bc5a4fb9ec647fb3cbc9ec07eb87129561143f565b9587612efa60405190565b95869586612da5565b7fe770710421fd2cad75ad828c61aa98f2d77d423a440b67872d0f65554148e00090565b6103ba9190612f3581613e19565b939150612f43825b9161174e565b11612f4f575050612266565b61228c9250612f5d90613e75565b90613ead565b9160206103a492949361177760408201965f83019061175d565b6103a4906001612f8b61362f565b017fc565b045403dc03c2eea82b81a0465edad9e2e7fc4d97e11421c209da93d7a9382612fb7836122c4565b612fcc612fc360405190565b92839283612f63565b0390a1611733565b9080612fde825190565b91612fe9603461163a565b83106130845761301061301d91613008613003603461163a565b860390565b016020015190565b6001600160b01b03191690565b692370726f706f7365723d60b01b906001600160b01b0319160361307c576130619161305b91613055613050602a61163a565b830390565b90613f4f565b91901590565b91821561306d57505090565b6127019192506116d3906104f2565b505050600190565b50505050600190565b6103ba94939291906141b0565b6103ba614396565b6103a4906130ae61439e565b6103a4906130c36130bd611c00565b82614597565b6145c0565b6103a4906130a2565b906103a492916130df61439e565b906103a492916145f2565b906103a492916130d1565b6103a461439e565b6103a46130f5565b6103a49061311161439e565b6103a490614629565b6103a490613105565b6103a49061312f61439e565b6103a49061463e565b6103a490613123565b6103a49061314d61439e565b6103a490614653565b6103a490613141565b7fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d10090565b6103ba600261163461315f565b6103ba600361163461315f565b909594926103a4946131d1610a71926131c76080966131c060a088019c5f890152565b6020870152565b60ff166040850152565b60608301906104fb565b6103ba939291612d8e612d9f926131ef5f90565b506131f86112e4565b61257f61320487613c4b565b8761320e60405190565b96879560208701958661319d565b905051906103a482610427565b90602082820312610393576103ba9161321c565b9160206103a4929493610a7160408201965f8301906104fb565b61329492506020919061326b6120a56126be565b9061327560405190565b809581948293613289633a46b1a860e01b90565b84526004840161323d565b03915afa908115612c3e575f916132a9575090565b6103ba915060203d6020116132cb575b6132c38183610565565b810190613229565b503d6132b9565b91908203918211611d2257565b6103ba9060301c61225a565b6103ba90546132df565b6133026103ba6103ba9290565b61225a565b80545b6133135f61163a565b81036133245750506103ba5f6132f5565b6133505f91613346611ffc846103ba960192613340600161163a565b906132d2565b5f5260205f200190565b016132eb565b9160206103a4929493611b0d60408201965f8301906104fb565b6103a4905f61337d6133f1565b017f08f74ea46ef7894f65eabfb5e6e695de773a000b47c529ab559178069b2264016133ab6120a58361165d565b6133b48461143f565b906133ca6133c160405190565b92839283613356565b0390a161201f565b6103ba5f6133de61362f565b01611ba0565b9091906103a4575061465c565b7f0d5829787b8befdbc6044ef7457d8a95c2a04bc99235349f1a212c063e59d40090565b6123376103ba6103ba9290565b6103bd9061163a565b6020810192916103a49190613422565b6103bd9061271b565b9160206103a492949361345e60408201965f83019061343b565b019061343b565b9063ffffffff60301b9060301b61171a565b6123376103ba6103ba9263ffffffff1690565b9061349a6103ba61174a92613477565b8254613465565b6134a961362f565b906134b35f613415565b63ffffffff82161461350e5760016103a492017f7e3f7f0708a84de9203036abaa450dccc85ad5ff52f78c170f3edb55cf5e8828826134f183612711565b6135066134fd60405190565b92839283613444565b0390a161348a565b63f1cfbf0560e01b5f9081526116fa81600461342b565b6103ba611c11565b906129ec6103ba61174a9261163a565b6103a4905f61354a61362f565b017fccb45da8d5717e6c4544694297c4ba5cf151d455c9bb0ed4fc7a38411bc054618261357683611ba0565b61358261285a60405190565b0390a161352d565b6135956120a56126be565b9060206135a160405190565b632394e7a360e21b81526004810183905292839060249082905afa908115612c3e576103ba925f926135e6575b506135d890611ca8565b6135e0612245565b916146c0565b6135d89192506136049060203d6020116132cb576132c38183610565565b91906135ce565b7f3ba4977254e415696610a40ebf2258dbfa0ec6a2ff64e84bfe715ff16977cc0090565b7ed7616c8fe29c6c2fbe1d0c5bc8f2faa4c35b43746e70b24b4d532752affd0090565b6103ba603161163a565b915f1960089290920291821b911b61171a565b919061367e6103ba61174a9390565b90835461365c565b6103a4915f9161366f565b908161369c816129a8565b926136a961299082612979565b6136b28561296d565b146136f8576136f260016103a49301946136e25f6136dd836136d7611e1d828c6129cb565b996129cb565b613686565b6136ec6001612983565b90612995565b90612aba565b612a7b613652565b611ac36103ba6103ba9290565b6103bd90613700565b9160206103a4929493610a7160408201965f83019061370d565b6137406001600160d01b03612266565b811161374f576103ba906132f5565b6306dfcc6560e41b5f908152906116fa9060d06004613716565b9061377f5f610d22949361377a5f90565b500190565b6148de565b906137c96103a4959796946137bb6080956137ad610a719560a08801908882035f8a015261245c565b908682036020880152610ec2565b9084820360408601526124a0565b966060830190613422565b919461382961381e60a0956138106103a499613802610a71979d9c9a9d60c08a01908a82035f8c015261245c565b9088820360208a0152610ec2565b9086820360408801526124a0565b986060850190613422565b6080830152565b91908201809211611d2257565b939290916138496133f1565b9485906138586120a58361165d565b95602061386460405190565b63793d064960e11b815297889060049082905afa968715612c3e575f9761399c575b50906020856138a26120a561389c5f97966149e8565b9b61165d565b86896138cc8d6138b160405190565b998a968795869563b1c5f42760e01b5b875260048701613784565b03915afa918215612c3e576116876120a5935f936138f9968592613977575b50612a699060018501611647565b90813b15610393575f80969461392e87839761391460405190565b9a8b98899788966308f2a0bb60e41b8852600488016137d4565b03925af1908115612c3e576103ba9261394d92613952575b5042613830565b613e75565b61396a905f5b6139628183610565565b8101906103f2565b5f613946565b503d613958565b612a699192506139959060203d6020116132cb576132c38183610565565b91906138eb565b5f9392919750856138a26120a561389c6139c4602095863d88116132cb576132c38183610565565b9b9596975050505050613886565b634e487b715f526020526024601cfd5b9392906139ed6133f1565b936139fa6120a58661165d565b90613a0963e38335e5916149e8565b90823b1561039357613a316138c1925f8097613a2460405190565b998a988997889760e01b90565b039134905af1928315612c3e5760015f936136dd936103a496613a56575b5001611647565b613a6c90863d8811613970576139628183610565565b5f613a4f565b6103ba9060f01c611ac3565b6103ba9054613a72565b6103ba9060f81c611ac3565b6103ba9054613a88565b5f613ab06103ba83600161168161287c565b01613ac3613abd82613a7e565b91613a94565b90613b8757613b8157613ad581611a49565b613ade5f61163a565b8114613b6b57613aef611a6161223c565b90811115613b6557613b06611ffc612d588461237a565b10613b115750600190565b613b1d61199882614a05565b8015613b53575b15613b2f5750600390565b613b38906122ce565b613b44611ffc5f61163a565b03613b4e57600490565b600590565b50613b6061199882614a48565b613b24565b50505f90565b636ad0607560e01b5f9081526004839052602490fd5b50600290565b5050600790565b92613ba3929091613b9d6133f1565b94614af8565b9060018101613bb5611e1d8483611647565b91613bbf5f61163a565b8303613bcc575b50505090565b613bd9906120a59061165d565b803b1561039357613c065f93918492613bf160405190565b958693849283919063c4d252f560e01b612bdf565b03925af1918215612c3e57835f926136dd92613c2795613c2f575b50611647565b5f8080613bc6565b613c4590853d8711613970576139628183610565565b5f613c21565b613c55905f611df5565b6103ba613c6182611ba0565b91600183015b9061352d565b6103ba90613c79614b86565b6042916040519161190160f01b8352600283015260228201522090565b6004111561096757565b906103a482613c96565b9190823b613cba611ffc5f61163a565b03613ce85790613cc991614c62565b50613cdc613cd65f613ca0565b91613ca0565b14918261306d57505090565b6103ba92614baf565b9060ff9061171a565b90613d0a6103ba61174a92151590565b8254613cf1565b6003111561096757565b906103a482613d11565b6103ba90613d1b565b613d40919394506103ba90611ae75f90565b9160038301613d52611af78383611ab4565b613e0257613d65613d6a92600192611ab4565b613cfa565b613d76611ac35f613d25565b60ff821603613d9657506103ba90613c6783613d9183611ba0565b613830565b613da3611ac36001613d25565b60ff821603613dc1575060016103ba9101613c6783613d9183611ba0565b613dd8613dd1611ac36002613d25565b9160ff1690565b03613df15760026103ba9101613c6783613d9183611ba0565b6303599be160e11b5f908152600490fd5b6371c6af4960e01b5f9081526116fa836004610504565b805490613e255f61163a565b8203613e425750505f90613e385f6116fe565b906103ba5f6132f5565b5f91613346611ffc84613e5b940192613340600161163a565b0190613e6f613e69836122c4565b926132eb565b60019291565b613e8465ffffffffffff61174e565b8111613e93576103ba906116fe565b6306dfcc6560e41b5f908152906116fa9060306004613716565b9061330a90825490613ebe5f61163a565b9082613eca600561163a565b8111613ed8575b5084614f27565b80613340613ee892959395614cdb565b90613efa61170b5f6122eb858a613346565b613f0385610c94565b1015613f125750915b5f613ed1565b929150613f2990613f23600161163a565b90613830565b90613f0c565b6001600160f01b03191690565b81810292918115918404141715611d2257565b80613f5b6103ba825190565b84118015614038575b61402b57613fa9613f99613fb39285613f896103ba613f83600161163a565b83613830565b88119182613ff7575b5050151590565b613fa3600261163a565b90613f3c565b613d91602861163a565b613fc3611ffc612d5885876132d2565b03613fe757613fe293926103ba92613fda92614fa4565b939093612036565b611436565b505050613ff35f612043565b5f91565b016020015161400b9150613f2f565b613f2f565b61402361060f60f31b5b916001600160f01b03191690565b14855f613f92565b50505050613ff35f612043565b50838311613f64565b9065ffffffffffff60a01b9060a01b61171a565b906140656103ba61174a92611724565b8254614041565b9063ffffffff60d01b9060d01b61171a565b9061408e6103ba61174a92613477565b825461406c565b5f5b8281106140a357505050565b606082820152602001614097565b906103a46140c161215584612133565b601f190160208401614095565b906140da6124ac835190565b90816140ec6020830284019460200190565b925f915b8383106140ff57505050505090565b9091929394602061411b6124f783856001950387528951612496565b93019301919392906140f0565b95906141a2956141776103ba9b999a966141696141859461419b9861415c6141939960208f611b0d6101208201965f830152565b8c820360408e015261245c565b908a820360608c0152610ec2565b9088820360808a01526140ce565b9086820360a08801526124a0565b9560c0850152565b60e0830152565b610100818403910152610476565b9492909391946141bd5f90565b506141c661287c565b946141df836141d6611a1a825190565b208883856122af565b9687966141ea845190565b6141f8611ffc6103ba865190565b14158015614355575b8015614340575b61430e5760010161421d5f611a5b8b84611647565b614229611d0a5f6116fe565b036142e35791611fb393917f7d84a6263ae0d98d3329bd7b46bb4e8d6f98cd35a7adb45c274c8b7fd5ebd5e0979899959361427061426561223c565b613d91612f3d611aa3565b926142b65f61428a6103ba8b614284611510565b96611647565b016142958b8261201f565b6142a76142a187613e75565b82614055565b6142b0846150c1565b9061407e565b6142d06142c96142c4875190565b6140b1565b9285613830565b946142da60405190565b998a998a614128565b5f6116fa8a6142f181611aab565b6142fa8461163a565b6331b75e4d60e01b855291600485016128ec565b506116fa9161432c6143276143225f965190565b935190565b915190565b630447b05d60e41b85529160048501610a53565b50835161434f611ffc5f61163a565b14614208565b508351614366611ffc6103ba855190565b1415614201565b6103ba7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0061163a565b6103ba61436d565b6143a96119986150f7565b6143af57565b631afcd79f60e31b5f908152600490fd5b906103a4916143cd61439e565b614556565b634e487b7160e01b5f525f60045260245ffd5b919061367e6103ba61174a9361163a565b6103a4915f916143e5565b81811061440c575050565b806144195f6001936143f6565b01614401565b9190601f811161442e57505050565b61443e6103a4935f5260205f2090565b906020601f840181900483019310614460575b6020601f909101040190614401565b9091508190614451565b905f1960089091021c191690565b816144829161446a565b906002021790565b90614493815190565b906001600160401b038211610586576144b6826144b0855461154a565b8561441f565b602090601f83116001146144e35761174a92915f91836144d8575b5050614478565b015190505f806144d1565b601f198316916144f6855f5260205f2090565b925f5b8181106145345750916002939185600196941061451a575b50505002019055565b61452a910151601f84169061446a565b90555f8080614511565b919360206001819287870151815501950192016144f9565b906103a49161448a565b61457b6103a49261457261456861315f565b936002850161454c565b6003830161454c565b60016145865f61163a565b9161459183826129de565b016129de565b906103a4916143c0565b6103a4906145ad61439e565b6103a4905f6145ba61287c565b0161454c565b6103a4906145a1565b906103a492916145d761439e565b6103a492916145e86145ed92612f7d565b6134a1565b61353d565b906103a492916145c9565b6103a49061460961439e565b6103a4905f6146226120a561461c61360b565b9361143f565b910161201f565b6103a4906145fd565b6103a49061152461439e565b6103a490614632565b6103a49061229d61439e565b6103a490614647565b805161466a611ffc5f61163a565b111561467857602081519101fd5b63d6bda27560e01b5f908152600490fd5b634e487b7160e01b5f52601260045260245ffd5b81156146a7570490565b614689565b6103ba601261163a565b6103ba601161163a565b919291905f906146d08184615109565b9390926146dc5f61163a565b84146147df57838711156147b85792866103ba9697936147289361473b965009808603951090036001614716846147125f61163a565b0390565b841680809504960493805f0304010290565b179161473b61473f8261473b600361163a565b0290565b6147126147b26147ac61479d61478e61477f6147706002976147608961163a565b1861473b8b82026147128b61163a565b61473b8a82026147128a61163a565b61473b8982026147128961163a565b61473b8882026147128861163a565b61473b8782026147128761163a565b80950290565b9161163a565b612a7b876147c8611ffc5f61163a565b146147d16146ac565b6147d96146b6565b9161511c565b50505050916103ba919261469d565b6103ba604061058b565b906103bd90610c94565b906103bd9061225a565b8054821015611889576148246001915f5260205f2090565b910201905f90565b6103ba9051610c94565b6103ba905161225a565b9065ffffffffffff199060301b61171a565b6133026103ba6103ba9261225a565b906148716103ba61174a92614852565b8254614840565b6103a49161489b9060209061489561488f8261482c565b85611733565b01614836565b90614861565b91906148b0576103a491614878565b6143d2565b80549190600160401b83101561058657826148d89160016103a49501815561480c565b906148a1565b91929180546148ec5f61163a565b811115614996576149106149055f92613340600161163a565b835f5260205f200190565b0161491a816122c4565b90614924816132eb565b9361492e81610c94565b61493784610c94565b1161498557869261494a611d0a83610c94565b0361495a5750611ffc9250614861565b915050611ffc9161497361496c6147ee565b92836147f8565b6149808660208401614802565b6148b5565b632520601d60e01b5f908152600490fd5b50906149b4916149a761496c6147ee565b6149808560208401614802565b611ffc5f6132f5565b6149d26149cc6103ba926104e6565b60601b90565b6001600160601b03191690565b6103ba906149bd565b614a016149fc6149f73061143f565b6149df565b6149d2565b1890565b614a43611ffc6103ba614a2a61141d614a246103ba875f611681612c68565b95611a49565b93613f236002614a3c60018401611ba0565b9201611ba0565b111590565b6103ba614a5691611ae75f90565b614a6c611ffc6103ba5f611bd460018601611ba0565b1190565b614a7c9060ff16613dd1565b019060ff8211611d2257565b60ff1660ff8111611d225760020a90565b6103ba6128e7614ac4614abf614aaf6007610976565b614ab96001613700565b90614a70565b614a88565b613340600161163a565b906001600160f81b03199060f81b61171a565b90614af16103ba61174a92151590565b8254614ace565b614b565f91614b1f600196614b5c968896614b105f90565b50614b1961287c565b946122af565b958691613a4f614b2d614a99565b614b3760026128c1565b614b4160066128c1565b90614b4c60076128c1565b921818188461290c565b01614ae1565b7f789cf55be980739dad1d0699b93b58e806b51c9d96619bfa8fe0a28abaa7b30c61196960405190565b6103ba615164565b9081526040602082018190526103ba92910190610476565b6103ba90610376565b915f92614bf38493614bbe5f90565b50614be4614bcb60405190565b630b135d3f60e11b602082015294859260248401614b8e565b60208201810382520383610565565b602082519201905afa614c046123f2565b81614c43575b81614c13575090565b614c2d91506020614c22825190565b818301019101613229565b612701611ffc6103ba630b135d3f60e11b614ba6565b9050614c4d815190565b614c5a611ffc602061163a565b101590614c0a565b905f91614c6d825190565b614c7a611ffc604161163a565b03614ca357614c9c9250602082015190606060408401519301515f1a906151e5565b9192909190565b509050614cba6128e7614cb55f612043565b925190565b909160029190565b6103ba90614cd6611ffc6103ba9460ff1690565b901c90565b6001614ce68161163a565b821115614f235790614e2e614e296103ba614e22614dee614dee614e18614df3614dee614e0e614dee614dee8c6104aa6103ba9f614de4614dee614dfd614e0793614dd4614dce88614d378461163a565b90614d45600160801b61163a565b8b1015614efb575b614d5a600160401b61163a565b811015614ed9575b614d6f600160201b61163a565b811015614eb7575b614d836201000061163a565b811015614e95575b614d9661010061163a565b811015614e73575b614da8601061163a565b811015614e4b575b614dbd611ffc600461163a565b1015614e33575b61473b600361163a565b91613700565b9e8f9c8d809b8197828096614cc2565b6104aa818d61469d565b614cc2565b6104aa818a61469d565b6104aa818761469d565b809261469d565b6104aa818c61469d565b6104aa818961469d565b809461469d565b821190565b900390565b614e4690614e4085613700565b906128a8565b614dc4565b614e62614e6d91614e5c6004613700565b90614cc2565b91614e406002613700565b90614db0565b614e84614e8f91614e5c6008613700565b91614e406004613700565b90614d9e565b614ea6614eb191614e5c6010613700565b91614e406008613700565b90614d8b565b614ec8614ed391614e5c6020613700565b91614e406010613700565b90614d77565b614eea614ef591614e5c6040613700565b91614e406020613700565b90614d62565b50614f1d614f12614f0c6080613700565b8c614cc2565b91614e406040613700565b90614d4d565b5090565b93919092614f325f90565b505b80821015614f8c57614f46818361529a565b90614f5a5f6122eb84895f5260205f200190565b614f66611d0a87610c94565b1115614f755750915b91614f34565b929150614f8690613f23600161163a565b90614f6f565b925050915090565b6103ba6103ba6103ba9260ff1690565b90929190600191614fc16103ba614fbb600161163a565b87613830565b81118061508c575b90614fea614fdb613f99869594151590565b614fe45f61163a565b97613830565b935b614ffb575b5050505060019190565b909192946150068290565b8610156150865761503261502d6150208886602001015190565b6001600160f81b03191690565b6152da565b9061503d600f613700565b60ff8316116150745761506b916104aa61505e61506493613fa3601061163a565b91614f94565b9560010190565b92919082614fec565b505050505090505f906103ba5f61163a565b94614ff1565b50614fea614fdb613f996150a66140068987602001015190565b6150b761401561060f60f31b613f2f565b1492505050614fc9565b6150ce63ffffffff61271b565b81116150dd576103ba90613415565b6306dfcc6560e41b5f908152906116fa9060206004613716565b6103ba5f61510361309a565b01611e2e565b905f198183099102908180821091030391565b61473b83614a019361512b5f90565b501891151590565b909594926103a49461515d611b0d926151566080966131c060a088019c5f890152565b6040850152565b6060830152565b7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6151b86151906153ac565b615198615427565b9061257f6151a53061143f565b6040519586946020860194469286615133565b6151c3611a1a825190565b2090565b610a716103a494612e15606094989795612e0b608086019a5f870152565b90916151f084612551565b615212611ffc6fa2a8918ca85bafe22016d0b997e4df60600160ff1b0361163a565b1161528757906152336020945f949361522a60405190565b948594856151c7565b838052039060015afa15612c3e575f5161524c5f612043565b615255816104f2565b61525e836104f2565b14615274575061526d5f61163a565b90915f9190565b905061527f5f61163a565b909160019190565b5050506152935f612043565b9160039190565b613f236103ba926152a85f90565b5080831692186152b8600261163a565b9061469d565b611ac36103ba6103ba9260ff1690565b6103ba9060f81c6152be565b6152e3906152ce565b806152ee602f613700565b60ff83161180615397575b15615315576103ba915061530d6030613700565b900360ff1690565b61531f6060613700565b60ff83161180615382575b1561533e576103ba915061530d6057613700565b506153496040613700565b60ff8216118061536d575b15615367576103ba9061530d6037613700565b5060ff90565b506153786047613700565b60ff821610615354565b5061538d6067613700565b60ff83161061532a565b506153a2603a613700565b60ff8316106152f9565b6153b461315f565b6153bf6103ba613183565b906153c8825190565b6153d4611ffc5f61163a565b11156153e657506151c3611a1a825190565b6153f09150611ba0565b6153f95f61163a565b81146154025790565b507fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47090565b61542f61315f565b61543a6103ba613190565b90615443825190565b61544f611ffc5f61163a565b111561546157506151c3611a1a825190565b6153f09150600101611ba056fea2646970667358221220118f3b52cba92dce33bd61d31e2f09521127dee95dab3924fe430e92787dd18964736f6c634300081c0033
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 33 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.