Overview
ETH Balance
ETH Value
$0.00Latest 1 from a total of 1 transactions
| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
| Set Vetoer | 1293164 | 395 days ago | IN | 0 ETH | 0.00000044 |
View more zero value Internal Transactions in Advanced View mode
Cross-Chain Transactions
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.19;
import {IVotes} from "./governance/IVotes.sol";
import {IVotingEscrow} from "contracts/interfaces/IVotingEscrow.sol";
import {IVoter} from "contracts/interfaces/IVoter.sol";
import {IVetoGovernor} from "./governance/IVetoGovernor.sol";
import {VetoGovernor} from "./governance/VetoGovernor.sol";
import {VetoGovernorCountingSimple} from "./governance/VetoGovernorCountingSimple.sol";
import {VetoGovernorVotes} from "./governance/VetoGovernorVotes.sol";
import {VetoGovernorVotesQuorumFraction} from "./governance/VetoGovernorVotesQuorumFraction.sol";
import {VetoGovernorPreventLateQuorum} from "./governance/VetoGovernorPreventLateQuorum.sol";
/// @title ProtocolGovernor
/// @notice Protocol governance with timestamp-based voting power from VotingEscrow NFTs
/// Supports vetoing of proposals as mitigation for 51% attacks
/// Votes are cast and counted on a per tokenId basis
contract ProtocolGovernor is
VetoGovernor,
VetoGovernorCountingSimple,
VetoGovernorVotes,
VetoGovernorVotesQuorumFraction,
VetoGovernorPreventLateQuorum
{
IVoter public immutable voter;
address public team;
address public pendingTeam;
address public vetoer;
address public pendingVetoer;
uint256 public constant MAX_PROPOSAL_NUMERATOR = 500; // max 5%
uint256 public constant PROPOSAL_DENOMINATOR = 10_000;
uint256 public proposalNumerator = 100; // 1%
error CommentWeightingTooHigh();
error NotGovernor();
error NotPendingTeam();
error NotTeam();
error NotPendingVetoer();
error NotVetoer();
error ProposalNumeratorTooHigh();
error ZeroAddress();
event AcceptTeam(address indexed newTeam);
event AcceptVetoer(address indexed vetoer);
event RenounceVetoer();
event SetCommentWeighting(uint256 commentWeighting);
event SetProposalNumerator(uint256 indexed proposalNumerator);
constructor(
IVotes _ve,
IVoter _voter
)
VetoGovernor("Protocol Governor", IVotingEscrow(address(_ve)))
VetoGovernorVotes(_ve)
VetoGovernorVotesQuorumFraction(25)
VetoGovernorPreventLateQuorum(2 days)
{
vetoer = msg.sender;
team = msg.sender;
voter = _voter;
}
function votingDelay() public pure override(IVetoGovernor) returns (uint256) {
return (2 days);
}
function votingPeriod() public pure override(IVetoGovernor) returns (uint256) {
return (5 days);
}
function setProposalNumerator(uint256 numerator) external {
if (msg.sender != team) revert NotTeam();
if (numerator > MAX_PROPOSAL_NUMERATOR) revert ProposalNumeratorTooHigh();
proposalNumerator = numerator;
emit SetProposalNumerator(numerator);
}
function proposalThreshold() public view override(VetoGovernor) returns (uint256) {
return (token.getPastTotalSupply(block.timestamp - 1) * proposalNumerator) / PROPOSAL_DENOMINATOR;
}
function setTeam(address _pendingTeam) external {
if (_pendingTeam == address(0)) revert ZeroAddress();
if (msg.sender != team) revert NotTeam();
pendingTeam = _pendingTeam;
}
function acceptTeam() external {
if (msg.sender != pendingTeam) revert NotPendingTeam();
team = pendingTeam;
delete pendingTeam;
emit AcceptTeam(team);
}
/// @dev Vetoer can be removed once the risk of a 51% attack becomes unfeasible.
/// This can be done by transferring ownership of vetoer to a contract that is "bricked"
/// i.e. a non-zero address contract that is immutable with no ability to call this function.
function setVetoer(address _vetoer) external {
if (msg.sender != vetoer) revert NotVetoer();
if (_vetoer == address(0)) revert ZeroAddress();
pendingVetoer = _vetoer;
}
function acceptVetoer() external {
if (msg.sender != pendingVetoer) revert NotPendingVetoer();
vetoer = pendingVetoer;
delete pendingVetoer;
emit AcceptVetoer(vetoer);
}
/// @notice Support for vetoer to protect against 51% attacks
function veto(uint256 _proposalId) external {
if (msg.sender != vetoer) revert NotVetoer();
_veto(_proposalId);
}
function renounceVetoer() external {
if (msg.sender != vetoer) revert NotVetoer();
delete vetoer;
emit RenounceVetoer();
}
/// @notice Set minimum % of total supply required to comment
/// @dev Callable only by voter.governor() (i.e. this contract)
/// @param _commentWeighting Weighting required for comment (note the denominator value).
function setCommentWeighting(uint256 _commentWeighting) external {
if (_commentWeighting > COMMENT_DENOMINATOR) revert CommentWeightingTooHigh();
if (msg.sender != voter.governor()) revert NotGovernor();
commentWeighting = _commentWeighting;
emit SetCommentWeighting(_commentWeighting);
}
function proposalDeadline(
uint256 proposalId
) public view override(VetoGovernor, VetoGovernorPreventLateQuorum) returns (uint256) {
return super.proposalDeadline(proposalId);
}
function _castVote(
uint256 proposalId,
address account,
uint256 tokenId,
uint8 support,
string memory reason,
bytes memory params
) internal override(VetoGovernor, VetoGovernorPreventLateQuorum) returns (uint256) {
return super._castVote(proposalId, account, tokenId, support, reason, params);
}
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;
import {IERC165} from "@openzeppelin/contracts/utils/introspection/ERC165.sol";
import {IERC6372} from "@openzeppelin/contracts/interfaces/IERC6372.sol";
import {IVotingEscrow} from "contracts/interfaces/IVotingEscrow.sol";
/**
* @dev Taken from OpenZeppelin's IGovernor.
* Includes support for veto-ing as mitigation against a 51% attack.
*/
abstract contract IVetoGovernor is IERC165, IERC6372 {
enum ProposalState {
Pending,
Active,
Canceled,
Defeated,
Succeeded,
Expired,
Queued, // unused, required for backwards compatibility
Executed,
Vetoed
}
/**
* @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 canceled.
*/
event ProposalCanceled(uint256 proposalId);
/**
* @dev Emitted when a proposal is vetoed.
*/
event ProposalVetoed(uint256 proposalId);
/**
* @dev Emitted when a proposal is executed.
*/
event ProposalExecuted(uint256 proposalId);
/**
* @dev Emitted when a comment is cast on a certain proposal.
*/
event Comment(uint256 indexed proposalId, address indexed account, uint256 indexed tokenId, string comment);
/**
* @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 indexed tokenId,
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 interpepretation also depends on the voting module used.
*/
event VoteCastWithParams(
address indexed voter,
uint256 indexed tokenId,
uint256 proposalId,
uint8 support,
uint256 weight,
string reason,
bytes params
);
/**
* @notice module:core
* @dev Name of the governor instance (used in building the ERC712 domain separator).
*/
function name() public view virtual returns (string memory);
/**
* @notice module:core
* @dev Version of the governor instance (used in building the ERC712 domain separator). Default: "1"
*/
function version() public view virtual returns (string memory);
/**
* @notice module:core
* @dev See {IERC6372}
*/
function clock() public view virtual override returns (uint48);
/**
* @notice module:core
* @dev See EIP-6372.
*/
// solhint-disable-next-line func-name-mixedcase
function CLOCK_MODE() public view virtual override returns (string memory);
/// @notice Numerator used to calculate minimum voting power required to comment.
function commentWeighting() external view virtual returns (uint256);
/// @notice Denominator used to calculate minimum voting power required to comment.
function COMMENT_DENOMINATOR() external view virtual returns (uint256);
/// @notice Contract whose total supply / voting power is being used.
function escrow() external view virtual returns (IVotingEscrow);
/**
* @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() public view virtual returns (string memory);
/**
* @notice module:core
* @dev Hashing function used to (re)build the proposal id from the proposal details..
*/
function hashProposal(
address[] memory targets,
uint256[] memory values,
bytes[] memory calldatas,
bytes32 descriptionHash,
address proposer
) public pure virtual returns (uint256);
/**
* @notice module:core
* @dev Current state of a proposal, following Compound's convention
*/
function state(uint256 proposalId) public view virtual returns (ProposalState);
/**
* @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) public view virtual 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) public view virtual returns (uint256);
/**
* @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 EIP-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.
*/
function votingDelay() public view virtual returns (uint256);
/**
* @notice module:user-config
* @dev Delay, between the vote start and vote ends. The unit this duration is expressed in depends on the clock
* (see EIP-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.
*/
function votingPeriod() public view virtual 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) public view virtual returns (uint256);
/**
* @notice module:reputation
* @dev Voting power of an `tokenId` 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 tokenId, uint256 timepoint) public view virtual returns (uint256);
/**
* @notice module:reputation
* @dev Voting power of an `tokenId` at a specific `timepoint` given additional encoded parameters.
*/
function getVotesWithParams(
address account,
uint256 tokenId,
uint256 timepoint,
bytes memory params
) public view virtual returns (uint256);
/**
* @notice module:voting
* @dev Returns whether `tokenId` has cast a vote on `proposalId`.
*/
function hasVoted(uint256 proposalId, uint256 tokenId) public view virtual 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.
*/
function propose(
uint256 tokenId,
address[] memory targets,
uint256[] memory values,
bytes[] memory calldatas,
string memory description
) public virtual 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.
*
* Emits a {ProposalExecuted} event.
*
* Note: some module 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,
address proposer
) public payable virtual 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
) public virtual returns (uint256 proposalId);
/**
* @dev Add a comment to a proposal
*
* Emits a {Comment} event.
*/
function comment(uint256 proposalId, uint256 tokenId, string calldata message) external virtual;
/**
* @dev Cast a vote
*
* Emits a {VoteCast} event.
*/
function castVote(uint256 proposalId, uint256 tokenId, uint8 support) public virtual returns (uint256 balance);
/**
* @dev Cast a vote with a reason
*
* Emits a {VoteCast} event.
*/
function castVoteWithReason(
uint256 proposalId,
uint256 tokenId,
uint8 support,
string calldata reason
) public virtual 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,
uint256 tokenId,
uint8 support,
string calldata reason,
bytes memory params
) public virtual returns (uint256 balance);
/**
* @dev Cast a vote using the user's cryptographic signature.
*
* Emits a {VoteCast} event.
*/
function castVoteBySig(
uint256 proposalId,
uint256 tokenId,
uint8 support,
uint8 v,
bytes32 r,
bytes32 s
) public virtual returns (uint256 balance);
/**
* @dev Cast a vote with a reason and additional encoded parameters using the user's cryptographic signature.
*
* Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.
*/
function castVoteWithReasonAndParamsBySig(
uint256 proposalId,
uint256 tokenId,
uint8 support,
string calldata reason,
bytes memory params,
uint8 v,
bytes32 r,
bytes32 s
) public virtual returns (uint256 balance);
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;
/// Modified IVotes interface for tokenId based voting
interface IVotes {
/**
* @dev Emitted when an account changes their delegate.
*/
event DelegateChanged(address indexed delegator, uint256 indexed fromDelegate, uint256 indexed toDelegate);
/**
* @dev Emitted when a token transfer or delegate change results in changes to a delegate's number of votes.
*/
event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance);
/**
* @dev Returns the amount of votes that `tokenId` had at a specific moment in the past.
* If the account passed in is not the owner, returns 0.
*/
function getPastVotes(address account, uint256 tokenId, 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 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 `tokenId` has chosen. Can never be equal to the delegator's `tokenId`.
* Returns 0 if not delegated.
*/
function delegates(uint256 tokenId) external view returns (uint256);
/**
* @dev Delegates votes from the sender to `delegatee`.
*/
function delegate(uint256 delegator, uint256 delegatee) external;
/**
* @dev Delegates votes from `delegator` to `delegatee`. Signer must own `delegator`.
*/
function delegateBySig(
uint256 delegator,
uint256 delegatee,
uint256 nonce,
uint256 expiry,
uint8 v,
bytes32 r,
bytes32 s
) external;
}// SPDX-License-Identifier: BUSL-1.1
// OpenZeppelin Contracts (last updated v4.8.0) (governance/Governor.sol)
pragma solidity ^0.8.0;
import {IERC721Receiver} from "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol";
import {IERC1155Receiver} from "@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol";
import {ECDSA} from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
import {EIP712} from "@openzeppelin/contracts/utils/cryptography/EIP712.sol";
import {ERC165, IERC165} from "@openzeppelin/contracts/utils/introspection/ERC165.sol";
import {IERC6372} from "@openzeppelin/contracts/interfaces/IERC6372.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 {Context} from "@openzeppelin/contracts/utils/Context.sol";
import {IVetoGovernor} from "./IVetoGovernor.sol";
import {IVotingEscrow} from "contracts/interfaces/IVotingEscrow.sol";
/**
* @dev Modified lightly from OpenZeppelin's Governor contract to support vetoing.
*/
abstract contract VetoGovernor is Context, ERC165, EIP712, IVetoGovernor, IERC721Receiver, IERC1155Receiver {
using DoubleEndedQueue for DoubleEndedQueue.Bytes32Deque;
using SafeCast for uint256;
bytes32 public constant BALLOT_TYPEHASH = keccak256("Ballot(uint256 proposalId,uint8 support)");
bytes32 public constant EXTENDED_BALLOT_TYPEHASH =
keccak256("ExtendedBallot(uint256 proposalId,uint8 support,string reason,bytes params)");
// solhint-disable var-name-mixedcase
struct ProposalCore {
// --- start retyped from Timers.BlockNumber at offset 0x00 ---
uint64 voteStart;
address proposer;
bytes4 __gap_unused0;
// --- start retyped from Timers.BlockNumber at offset 0x20 ---
uint64 voteEnd;
bytes24 __gap_unused1;
// --- Remaining fields starting at offset 0x40 ---------------
bool executed;
bool canceled;
bool vetoed;
}
// solhint-enable var-name-mixedcase
string private _name;
uint256 public override commentWeighting = 4_000;
uint256 public constant override COMMENT_DENOMINATOR = 1_000_000_000;
IVotingEscrow public immutable override escrow;
/// @custom:oz-retyped-from mapping(uint256 => Governor.ProposalCore)
mapping(uint256 => ProposalCore) private _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 {_beforeExecute},
// consumed by the {onlyGovernance} modifier and eventually reset in {_afterExecute}. This ensures that the
// execution of {onlyGovernance} protected calls can only be achieved through successful proposals.
DoubleEndedQueue.Bytes32Deque private _governanceCall;
/**
* @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() {
require(_msgSender() == _executor(), "Governor: onlyGovernance");
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 Sets the value for {name} and {version}
*/
constructor(string memory name_, IVotingEscrow _ve) EIP712(name_, version()) {
_name = name_;
escrow = _ve;
}
/**
* @dev Function to receive ETH that will be handled by the governor (disabled if executor is a third party contract)
*/
receive() external payable virtual {
require(_executor() == address(this));
}
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC165) returns (bool) {
// In addition to the current interfaceId, also support previous version of the interfaceId that did not
// include the castVoteWithReasonAndParams() function as standard
return
interfaceId ==
(type(IVetoGovernor).interfaceId ^
type(IERC6372).interfaceId ^
this.cancel.selector ^
this.castVoteWithReasonAndParams.selector ^
this.castVoteWithReasonAndParamsBySig.selector ^
this.getVotesWithParams.selector) ||
// Previous interface for backwards compatibility
interfaceId == (type(IVetoGovernor).interfaceId ^ type(IERC6372).interfaceId ^ this.cancel.selector) ||
interfaceId == type(IERC1155Receiver).interfaceId ||
super.supportsInterface(interfaceId);
}
/**
* @dev See {IVetoGovernor-name}.
*/
function name() public view virtual override returns (string memory) {
return _name;
}
/**
* @dev See {IVetoGovernor-version}.
*/
function version() public view virtual override returns (string memory) {
return "1";
}
/**
* @dev See {IVetoGovernor-hashProposal}.
*
* The proposal id is produced by hashing the ABI encoded `targets` array, the `values` array, the `calldatas` array,
* the descriptionHash (bytes32 which itself is the keccak256 hash of the description string) and the `proposer` address.
* 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,
address proposer
) public pure virtual override returns (uint256) {
return uint256(keccak256(abi.encode(targets, values, calldatas, descriptionHash, proposer)));
}
/**
* @dev See {IVetoGovernor-state}.
*/
function state(uint256 proposalId) public view virtual override returns (ProposalState) {
ProposalCore storage proposal = _proposals[proposalId];
if (proposal.executed) {
return ProposalState.Executed;
}
if (proposal.canceled) {
return ProposalState.Canceled;
}
if (proposal.vetoed) {
return ProposalState.Vetoed;
}
uint256 snapshot = proposalSnapshot(proposalId);
if (snapshot == 0) {
revert("Governor: unknown proposal id");
}
uint256 currentTimepoint = clock();
if (snapshot >= currentTimepoint) {
return ProposalState.Pending;
}
uint256 deadline = proposalDeadline(proposalId);
if (deadline >= currentTimepoint) {
return ProposalState.Active;
}
if (_quorumReached(proposalId) && _voteSucceeded(proposalId)) {
return ProposalState.Succeeded;
} else {
return ProposalState.Defeated;
}
}
/**
* @dev Part of the Governor Bravo's interface: _"The number of votes required in order for a voter to become a proposer"_.
*/
function proposalThreshold() public view virtual returns (uint256) {
return 0;
}
/**
* @dev See {IVetoGovernor-proposalSnapshot}.
*/
function proposalSnapshot(uint256 proposalId) public view virtual override returns (uint256) {
return _proposals[proposalId].voteStart;
}
/**
* @dev See {IVetoGovernor-proposalDeadline}.
*/
function proposalDeadline(uint256 proposalId) public view virtual override returns (uint256) {
return _proposals[proposalId].voteEnd;
}
/**
* @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 `tokenId`, owned by `account` at a specific `timepoint`, for a vote as described by `params`.
*/
function _getVotes(
address account,
uint256 tokenId,
uint256 timepoint,
bytes memory params
) internal view virtual returns (uint256);
/**
* @dev Register a vote for `proposalId` by `tokenId` 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,
uint256 tokenId,
uint8 support,
uint256 weight,
bytes memory params
) 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 {IVetoGovernor-propose}.
*/
function propose(
uint256 tokenId,
address[] memory targets,
uint256[] memory values,
bytes[] memory calldatas,
string memory description
) public virtual override returns (uint256) {
address proposer = _msgSender();
uint256 currentTimepoint = clock();
require(
getVotes(proposer, tokenId, currentTimepoint - 1) >= proposalThreshold(),
"Governor: proposer votes below proposal threshold"
);
uint256 proposalId = hashProposal(targets, values, calldatas, keccak256(bytes(description)), proposer);
require(targets.length == values.length, "Governor: invalid proposal length");
require(targets.length == calldatas.length, "Governor: invalid proposal length");
require(targets.length > 0, "Governor: empty proposal");
require(_proposals[proposalId].proposer == address(0), "Governor: proposal already exists");
uint256 snapshot = currentTimepoint + votingDelay();
uint256 deadline = snapshot + votingPeriod();
_proposals[proposalId] = ProposalCore({
voteStart: snapshot.toUint64(),
proposer: proposer,
__gap_unused0: 0,
voteEnd: deadline.toUint64(),
__gap_unused1: 0,
executed: false,
canceled: false,
vetoed: false
});
emit ProposalCreated(
proposalId,
proposer,
targets,
values,
new string[](targets.length),
calldatas,
snapshot,
deadline,
description
);
return proposalId;
}
/**
* @dev See {IVetoGovernor-execute}.
*/
function execute(
address[] memory targets,
uint256[] memory values,
bytes[] memory calldatas,
bytes32 descriptionHash,
address proposer
) public payable virtual override returns (uint256) {
uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash, proposer);
ProposalState status = state(proposalId);
require(status == ProposalState.Succeeded, "Governor: proposal not successful");
_proposals[proposalId].executed = true;
emit ProposalExecuted(proposalId);
_beforeExecute(proposalId, targets, values, calldatas, descriptionHash);
_execute(proposalId, targets, values, calldatas, descriptionHash);
_afterExecute(proposalId, targets, values, calldatas, descriptionHash);
return proposalId;
}
/**
* @dev See {IVetoGovernor-cancel}.
*/
function cancel(
address[] memory targets,
uint256[] memory values,
bytes[] memory calldatas,
bytes32 descriptionHash
) public virtual override returns (uint256) {
address proposer = _msgSender();
uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash, proposer);
require(state(proposalId) == ProposalState.Pending, "Governor: too late to cancel");
require(proposer == _proposals[proposalId].proposer, "Governor: only proposer can cancel");
return _cancel(targets, values, calldatas, descriptionHash, proposer);
}
/**
* @dev Internal execution mechanism. Can be overridden to implement different execution mechanism
*/
function _execute(
uint256 /* proposalId */,
address[] memory targets,
uint256[] memory values,
bytes[] memory calldatas,
bytes32 /*descriptionHash*/
) internal virtual {
string memory errorMessage = "Governor: call reverted without message";
uint256 _length = targets.length;
for (uint256 i = 0; i < _length; ++i) {
(bool success, bytes memory returndata) = targets[i].call{value: values[i]}(calldatas[i]);
Address.verifyCallResult(success, returndata, errorMessage);
}
}
/**
* @dev Hook before execution is triggered.
*/
function _beforeExecute(
uint256 /* proposalId */,
address[] memory targets,
uint256[] memory /* values */,
bytes[] memory calldatas,
bytes32 /*descriptionHash*/
) internal virtual {
if (_executor() != address(this)) {
uint256 _length = targets.length;
for (uint256 i = 0; i < _length; ++i) {
if (targets[i] == address(this)) {
_governanceCall.pushBack(keccak256(calldatas[i]));
}
}
}
}
/**
* @dev Hook after execution is triggered.
*/
function _afterExecute(
uint256 /* proposalId */,
address[] memory /* targets */,
uint256[] memory /* values */,
bytes[] memory /* calldatas */,
bytes32 /*descriptionHash*/
) internal virtual {
if (_executor() != address(this)) {
if (!_governanceCall.empty()) {
_governanceCall.clear();
}
}
}
/**
* @dev Internal veto mechanism: locks up the proposal timer, preventing it from being re-submitted. Marks it as
* vetoed to allow distinguishing it from executed and canceled proposals.
*
* Emits a {IVetoGovernor-ProposalVetoed} event.
*/
function _veto(uint256 proposalId) internal returns (uint256) {
ProposalState status = state(proposalId);
require(
status != ProposalState.Vetoed &&
status != ProposalState.Canceled &&
status != ProposalState.Expired &&
status != ProposalState.Executed,
"Governor: proposal not active"
);
_proposals[proposalId].vetoed = true;
emit ProposalVetoed(proposalId);
return proposalId;
}
/**
* @dev Internal cancel mechanism: locks up the proposal timer, preventing it from being re-submitted. Marks it as
* canceled to allow distinguishing it from executed and canceled proposals.
*
* Emits a {IVetoGovernor-ProposalCanceled} event.
*/
function _cancel(
address[] memory targets,
uint256[] memory values,
bytes[] memory calldatas,
bytes32 descriptionHash,
address proposer
) internal virtual returns (uint256) {
uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash, proposer);
ProposalState status = state(proposalId);
require(
status != ProposalState.Vetoed &&
status != ProposalState.Canceled &&
status != ProposalState.Expired &&
status != ProposalState.Executed,
"Governor: proposal not active"
);
_proposals[proposalId].canceled = true;
emit ProposalCanceled(proposalId);
return proposalId;
}
/**
* @dev See {IVetoGovernor-getVotes}.
*/
function getVotes(
address account,
uint256 tokenId,
uint256 timepoint
) public view virtual override returns (uint256) {
return _getVotes(account, tokenId, timepoint, _defaultParams());
}
/**
* @dev See {IVetoGovernor-getVotesWithParams}.
*/
function getVotesWithParams(
address account,
uint256 tokenId,
uint256 timepoint,
bytes memory params
) public view virtual override returns (uint256) {
return _getVotes(account, tokenId, timepoint, params);
}
/**
* @dev See {IVetoGovernor-castVote}.
*/
function castVote(uint256 proposalId, uint256 tokenId, uint8 support) public virtual override returns (uint256) {
address voter = _msgSender();
return _castVote(proposalId, voter, tokenId, support, "");
}
/**
* @dev See {IVetoGovernor-castVoteWithReason}.
*/
function castVoteWithReason(
uint256 proposalId,
uint256 tokenId,
uint8 support,
string calldata reason
) public virtual override returns (uint256) {
address voter = _msgSender();
return _castVote(proposalId, voter, tokenId, support, reason);
}
/**
* @dev See {IVetoGovernor-castVoteWithReasonAndParams}.
*/
function castVoteWithReasonAndParams(
uint256 proposalId,
uint256 tokenId,
uint8 support,
string calldata reason,
bytes memory params
) public virtual override returns (uint256) {
address voter = _msgSender();
return _castVote(proposalId, voter, tokenId, support, reason, params);
}
/**
* @dev See {IVetoGovernor-castVoteBySig}.
*/
function castVoteBySig(
uint256 proposalId,
uint256 tokenId,
uint8 support,
uint8 v,
bytes32 r,
bytes32 s
) public virtual override returns (uint256) {
address voter = ECDSA.recover(
_hashTypedDataV4(keccak256(abi.encode(BALLOT_TYPEHASH, proposalId, support))),
v,
r,
s
);
return _castVote(proposalId, voter, tokenId, support, "");
}
/**
* @dev See {IVetoGovernor-castVoteWithReasonAndParamsBySig}.
*/
function castVoteWithReasonAndParamsBySig(
uint256 proposalId,
uint256 tokenId,
uint8 support,
string calldata reason,
bytes memory params,
uint8 v,
bytes32 r,
bytes32 s
) public virtual override returns (uint256) {
address voter = ECDSA.recover(
_hashTypedDataV4(
keccak256(
abi.encode(
EXTENDED_BALLOT_TYPEHASH,
proposalId,
support,
keccak256(bytes(reason)),
keccak256(params)
)
)
),
v,
r,
s
);
return _castVote(proposalId, voter, tokenId, support, reason, params);
}
/**
* @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve
* voting weight using {IVetoGovernor-getVotes} and call the {_countVote} internal function. Uses the _defaultParams().
*
* Emits a {IVetoGovernor-VoteCast} event.
*/
function _castVote(
uint256 proposalId,
address account,
uint256 tokenId,
uint8 support,
string memory reason
) internal virtual returns (uint256) {
return _castVote(proposalId, account, tokenId, 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 {IVetoGovernor-getVotes} and call the {_countVote} internal function.
*
* Emits a {IVetoGovernor-VoteCast} event.
*/
function _castVote(
uint256 proposalId,
address account,
uint256 tokenId,
uint8 support,
string memory reason,
bytes memory params
) internal virtual returns (uint256) {
ProposalCore storage proposal = _proposals[proposalId];
require(state(proposalId) == ProposalState.Active, "Governor: vote not currently active");
uint256 weight = _getVotes(account, tokenId, proposal.voteStart, params);
_countVote(proposalId, tokenId, support, weight, params);
if (params.length == 0) {
emit VoteCast(account, tokenId, proposalId, support, weight, reason);
} else {
emit VoteCastWithParams(account, tokenId, proposalId, support, weight, reason, params);
}
return weight;
}
/**
* @dev Comment mechanism for active or pending proposals. Requires a certain amount of votes. Emits a comment
* containing the message.
*
* Emits a {IVetoGovernor-Comment} event.
*/
function comment(uint256 proposalId, uint256 tokenId, string calldata message) external virtual override {
bytes memory params;
ProposalCore storage proposal = _proposals[proposalId];
ProposalState status = state(proposalId);
require(status == ProposalState.Active || status == ProposalState.Pending, "Governor: not active or pending");
uint256 startTime = proposal.voteStart;
address account = _msgSender();
uint256 weight = _getVotes(account, tokenId, startTime, params);
uint256 minimumWeight = (escrow.getPastTotalSupply(startTime) * commentWeighting) / COMMENT_DENOMINATOR;
require(weight > minimumWeight, "Governor: insufficient voting power");
emit Comment(proposalId, account, tokenId, message);
}
/**
* @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, "Governor: relay reverted without message");
}
/**
* @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}.
*/
function onERC721Received(address, address, uint256, bytes memory) public virtual override returns (bytes4) {
return this.onERC721Received.selector;
}
/**
* @dev See {IERC1155Receiver-onERC1155Received}.
*/
function onERC1155Received(
address,
address,
uint256,
uint256,
bytes memory
) public virtual override returns (bytes4) {
return this.onERC1155Received.selector;
}
/**
* @dev See {IERC1155Receiver-onERC1155BatchReceived}.
*/
function onERC1155BatchReceived(
address,
address,
uint256[] memory,
uint256[] memory,
bytes memory
) public virtual override returns (bytes4) {
return this.onERC1155BatchReceived.selector;
}
}// SPDX-License-Identifier: BUSL-1.1
// OpenZeppelin Contracts (last updated v4.8.0) (governance/extensions/GovernorCountingSimple.sol)
pragma solidity ^0.8.0;
import {VetoGovernor} from "./VetoGovernor.sol";
/**
* @dev OpenZeppelin's GovernorCountingSimple using VetoGovernor
*/
abstract contract VetoGovernorCountingSimple is VetoGovernor {
/**
* @dev Supported vote types. Matches Governor Bravo ordering.
*/
enum VoteType {
Against,
For,
Abstain
}
struct ProposalVote {
uint256 againstVotes;
uint256 forVotes;
uint256 abstainVotes;
mapping(uint256 => bool) hasVoted;
}
mapping(uint256 => ProposalVote) private _proposalVotes;
/**
* @dev See {IGovernor-COUNTING_MODE}.
*/
// solhint-disable-next-line func-name-mixedcase
function COUNTING_MODE() public pure virtual override returns (string memory) {
return "support=bravo&quorum=for,abstain";
}
/**
* @dev See {IGovernor-hasVoted}.
*/
function hasVoted(uint256 proposalId, uint256 tokenId) public view virtual override returns (bool) {
return _proposalVotes[proposalId].hasVoted[tokenId];
}
/**
* @dev Accessor to the internal vote counts.
*/
function proposalVotes(
uint256 proposalId
) public view virtual returns (uint256 againstVotes, uint256 forVotes, uint256 abstainVotes) {
ProposalVote storage proposalVote = _proposalVotes[proposalId];
return (proposalVote.againstVotes, proposalVote.forVotes, proposalVote.abstainVotes);
}
/**
* @dev See {Governor-_quorumReached}.
*/
function _quorumReached(uint256 proposalId) internal view virtual override returns (bool) {
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) {
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,
uint256 tokenId,
uint8 support,
uint256 weight,
bytes memory // params
) internal virtual override {
ProposalVote storage proposalVote = _proposalVotes[proposalId];
require(!proposalVote.hasVoted[tokenId], "GovernorVotingSimple: vote already cast");
require(weight > 0, "GovernorVotingSimple: zero voting weight");
proposalVote.hasVoted[tokenId] = true;
if (support == uint8(VoteType.Against)) {
proposalVote.againstVotes += weight;
} else if (support == uint8(VoteType.For)) {
proposalVote.forVotes += weight;
} else if (support == uint8(VoteType.Abstain)) {
proposalVote.abstainVotes += weight;
} else {
revert("GovernorVotingSimple: invalid value for enum VoteType");
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorPreventLateQuorum.sol)
pragma solidity ^0.8.0;
import {VetoGovernor} from "./VetoGovernor.sol";
import {SafeCast} from "@openzeppelin/contracts/utils/math/SafeCast.sol";
import {Math} from "@openzeppelin/contracts/utils/math/Math.sol";
/**
* @dev A module that ensures there is a minimum voting period after quorum is reached. This prevents a large voter from
* swaying a vote and triggering quorum at the last minute, by ensuring there is always time for other voters to react
* and try to oppose the decision.
*
* If a vote causes quorum to be reached, the proposal's voting period may be extended so that it does not end before at
* least a given number of blocks have passed (the "vote extension" parameter). This parameter can be set by the
* governance executor (e.g. through a governance proposal).
*
* _Available since v4.5._
*/
abstract contract VetoGovernorPreventLateQuorum is VetoGovernor {
using SafeCast for uint256;
uint64 private _voteExtension;
/// @custom:oz-retyped-from mapping(uint256 => Timers.BlockNumber)
mapping(uint256 => uint64) private _extendedDeadlines;
/// @dev Emitted when a proposal deadline is pushed back due to reaching quorum late in its voting period.
event ProposalExtended(uint256 indexed proposalId, uint64 extendedDeadline);
/// @dev Emitted when the {lateQuorumVoteExtension} parameter is changed.
event LateQuorumVoteExtensionSet(uint64 oldVoteExtension, uint64 newVoteExtension);
/**
* @dev Initializes the vote extension parameter: the number of blocks that are required to pass since a proposal
* reaches quorum until its voting period ends. If necessary the voting period will be extended beyond the one set
* at proposal creation.
*/
constructor(uint64 initialVoteExtension) {
_setLateQuorumVoteExtension(initialVoteExtension);
}
/**
* @dev Returns the proposal deadline, which may have been extended beyond that set at proposal creation, if the
* proposal reached quorum late in the voting period. See {Governor-proposalDeadline}.
*/
function proposalDeadline(uint256 proposalId) public view virtual override returns (uint256) {
return Math.max(super.proposalDeadline(proposalId), _extendedDeadlines[proposalId]);
}
/**
* @dev Casts a vote and detects if it caused quorum to be reached, potentially extending the voting period. See
* {Governor-_castVote}.
*
* May emit a {ProposalExtended} event.
*/
function _castVote(
uint256 proposalId,
address account,
uint256 tokenId,
uint8 support,
string memory reason,
bytes memory params
) internal virtual override returns (uint256) {
uint256 result = super._castVote(proposalId, account, tokenId, support, reason, params);
if (_extendedDeadlines[proposalId] == 0 && _quorumReached(proposalId)) {
uint64 extendedDeadline = clock() + lateQuorumVoteExtension();
if (extendedDeadline > proposalDeadline(proposalId)) {
emit ProposalExtended(proposalId, extendedDeadline);
}
_extendedDeadlines[proposalId] = extendedDeadline;
}
return result;
}
/**
* @dev Returns the current value of the vote extension parameter: the number of blocks that are required to pass
* from the time a proposal reaches quorum until its voting period ends.
*/
function lateQuorumVoteExtension() public view virtual returns (uint64) {
return _voteExtension;
}
/**
* @dev Changes the {lateQuorumVoteExtension}. This operation can only be performed by the governance executor,
* generally through a governance proposal.
*
* Emits a {LateQuorumVoteExtensionSet} event.
*/
function setLateQuorumVoteExtension(uint64 newVoteExtension) public virtual onlyGovernance {
_setLateQuorumVoteExtension(newVoteExtension);
}
/**
* @dev Changes the {lateQuorumVoteExtension}. This is an internal function that can be exposed in a public function
* like {setLateQuorumVoteExtension} if another access control mechanism is needed.
*
* Emits a {LateQuorumVoteExtensionSet} event.
*/
function _setLateQuorumVoteExtension(uint64 newVoteExtension) internal virtual {
emit LateQuorumVoteExtensionSet(_voteExtension, newVoteExtension);
_voteExtension = newVoteExtension;
}
}// SPDX-License-Identifier: BUSL-1.1
// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorVotes.sol)
pragma solidity ^0.8.0;
import {VetoGovernor} from "./VetoGovernor.sol";
import {IERC6372} from "@openzeppelin/contracts/interfaces/IERC6372.sol";
import {IVotes} from "./IVotes.sol";
import {SafeCast} from "@openzeppelin/contracts/utils/math/SafeCast.sol";
import {IVotingEscrow} from "contracts/interfaces/IVotingEscrow.sol";
import {DelegationHelperLibrary} from "contracts/libraries/DelegationHelperLibrary.sol";
/**
* @dev OpenZeppelin's GovernorVotes using VetoGovernor
*/
abstract contract VetoGovernorVotes is VetoGovernor {
using DelegationHelperLibrary for IVotingEscrow;
IVotes public immutable token;
IVotingEscrow public immutable ve;
constructor(IVotes votes) {
token = votes;
ve = IVotingEscrow(address(votes));
}
/**
* @dev Clock (as specified in EIP-6372) is set to match the token's clock. Fallback to block numbers if the token
* does not implement EIP-6372.
*/
function clock() public view virtual override returns (uint48) {
try IERC6372(address(token)).clock() returns (uint48 timepoint) {
return timepoint;
} catch {
return SafeCast.toUint48(block.number);
}
}
/**
* @dev Machine-readable description of the clock as specified in EIP-6372.
*/
// solhint-disable-next-line func-name-mixedcase
function CLOCK_MODE() public view virtual override returns (string memory) {
try IERC6372(address(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 tokenId,
uint256 timepoint,
bytes memory /*params*/
) internal view virtual override returns (uint256) {
IVotingEscrow.EscrowType escrowType = ve.escrowType(tokenId);
require(escrowType != IVotingEscrow.EscrowType.MANAGED, "Governor: managed nft cannot vote");
if (escrowType == IVotingEscrow.EscrowType.NORMAL) {
return token.getPastVotes(account, tokenId, timepoint);
}
// only allow locked veNFT voting if underlying nft not delegating at timepoint
uint256 mTokenId = ve.idToManaged(tokenId);
uint48 index = ve.getPastCheckpointIndex(mTokenId, timepoint);
uint256 delegatee = ve.checkpoints(mTokenId, index).delegatee;
if (delegatee == 0) {
// if mveNFT not delegating, voting balance = delegated balance +
// initial contribution to mveNFT + accrued locked rewards
uint256 delegatedBalance = token.getPastVotes(account, tokenId, timepoint);
uint256 weight = ve.weights(tokenId, mTokenId); // initial deposit weight
uint256 _earned = ve.earned(mTokenId, tokenId, timepoint); // accrued rewards
return weight + _earned + delegatedBalance;
}
// nft locked and underlying nft delegating
// balance will only be delegated balance
return token.getPastVotes(account, tokenId, timepoint);
}
function getVotes(uint256 tokenId, uint256 timepoint) external view returns (uint256) {
address account = ve.ownerOf(tokenId);
return _getVotes(account, tokenId, timepoint, "");
}
}// SPDX-License-Identifier: BUSL-1.1
// OpenZeppelin Contracts (last updated v4.8.0) (governance/extensions/GovernorVotesQuorumFraction.sol)
pragma solidity ^0.8.0;
import {VetoGovernorVotes} from "./VetoGovernorVotes.sol";
import {Checkpoints} from "@openzeppelin/contracts/utils/Checkpoints.sol";
import {SafeCast} from "@openzeppelin/contracts/utils/math/SafeCast.sol";
/**
* @dev OpenZeppelin's GovernorVotesQuorumFraction using VetoGovernor
*/
abstract contract VetoGovernorVotesQuorumFraction is VetoGovernorVotes {
using SafeCast for *;
using Checkpoints for Checkpoints.Trace224;
uint256 private _quorumNumerator; // DEPRECATED in favor of _quorumNumeratorHistory
/// @custom:oz-retyped-from Checkpoints.History
Checkpoints.Trace224 private _quorumNumeratorHistory;
event QuorumNumeratorUpdated(uint256 oldQuorumNumerator, uint256 newQuorumNumerator);
/**
* @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}.
*/
constructor(uint256 quorumNumeratorValue) {
_updateQuorumNumerator(quorumNumeratorValue);
}
/**
* @dev Returns the current quorum numerator. See {quorumDenominator}.
*/
function quorumNumerator() public view virtual returns (uint256) {
return _quorumNumeratorHistory._checkpoints.length == 0 ? _quorumNumerator : _quorumNumeratorHistory.latest();
}
/**
* @dev Returns the quorum numerator at a specific timepoint. See {quorumDenominator}.
*/
function quorumNumerator(uint256 timepoint) public view virtual returns (uint256) {
// If history is empty, fallback to old storage
uint256 length = _quorumNumeratorHistory._checkpoints.length;
if (length == 0) {
return _quorumNumerator;
}
// Optimistic search, check the latest checkpoint
Checkpoints.Checkpoint224 memory latest = _quorumNumeratorHistory._checkpoints[length - 1];
if (latest._key <= timepoint) {
return latest._value;
}
// Otherwise, do the binary search
return _quorumNumeratorHistory.upperLookupRecent(timepoint.toUint32());
}
/**
* @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 (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 {
require(
newQuorumNumerator <= quorumDenominator(),
"GovernorVotesQuorumFraction: quorumNumerator over quorumDenominator"
);
uint256 oldQuorumNumerator = quorumNumerator();
// Make sure we keep track of the original numerator in contracts upgraded from a version without checkpoints.
if (oldQuorumNumerator != 0 && _quorumNumeratorHistory._checkpoints.length == 0) {
_quorumNumeratorHistory._checkpoints.push(
Checkpoints.Checkpoint224({_key: 0, _value: oldQuorumNumerator.toUint224()})
);
}
// Set new quorum for future proposals
_quorumNumeratorHistory.push(clock().toUint32(), newQuorumNumerator.toUint224());
emit QuorumNumeratorUpdated(oldQuorumNumerator, newQuorumNumerator);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface IReward {
error InvalidReward();
error NotAuthorized();
error NotGauge();
error NotEscrowToken();
error NotSingleToken();
error NotVotingEscrow();
error NotWhitelisted();
error ZeroAmount();
event Deposit(address indexed from, uint256 indexed tokenId, uint256 amount);
event Withdraw(address indexed from, uint256 indexed tokenId, uint256 amount);
event NotifyReward(address indexed from, address indexed reward, uint256 indexed epoch, uint256 amount);
event ClaimRewards(address indexed from, address indexed reward, uint256 amount);
/// @notice A checkpoint for marking balance
struct Checkpoint {
uint256 timestamp;
uint256 balanceOf;
}
/// @notice A checkpoint for marking supply
struct SupplyCheckpoint {
uint256 timestamp;
uint256 supply;
}
/// @notice Epoch duration constant (7 days)
function DURATION() external view returns (uint256);
/// @notice Address of Voter.sol
function voter() external view returns (address);
/// @notice Address of VotingEscrow.sol
function ve() external view returns (address);
/// @dev Address which has permission to externally call _deposit() & _withdraw()
function authorized() external view returns (address);
/// @notice Total amount currently deposited via _deposit()
function totalSupply() external view returns (uint256);
/// @notice Current amount deposited by tokenId
function balanceOf(uint256 tokenId) external view returns (uint256);
/// @notice Amount of tokens to reward depositors for a given epoch
/// @param token Address of token to reward
/// @param epochStart Startime of rewards epoch
/// @return Amount of token
function tokenRewardsPerEpoch(address token, uint256 epochStart) external view returns (uint256);
/// @notice Most recent timestamp a veNFT has claimed their rewards
/// @param token Address of token rewarded
/// @param tokenId veNFT unique identifier
/// @return Timestamp
function lastEarn(address token, uint256 tokenId) external view returns (uint256);
/// @notice True if a token is or has been an active reward token, else false
function isReward(address token) external view returns (bool);
/// @notice The number of checkpoints for each tokenId deposited
function numCheckpoints(uint256 tokenId) external view returns (uint256);
/// @notice The total number of checkpoints
function supplyNumCheckpoints() external view returns (uint256);
/// @notice Deposit an amount into the rewards contract to earn future rewards associated to a veNFT
/// @dev Internal notation used as only callable internally by `authorized`.
/// @param amount Amount deposited for the veNFT
/// @param tokenId Unique identifier of the veNFT
function _deposit(uint256 amount, uint256 tokenId) external;
/// @notice Withdraw an amount from the rewards contract associated to a veNFT
/// @dev Internal notation used as only callable internally by `authorized`.
/// @param amount Amount deposited for the veNFT
/// @param tokenId Unique identifier of the veNFT
function _withdraw(uint256 amount, uint256 tokenId) external;
/// @notice Claim the rewards earned by a veNFT staker
/// @param tokenId Unique identifier of the veNFT
/// @param tokens Array of tokens to claim rewards of
function getReward(uint256 tokenId, address[] memory tokens) external;
/// @notice Add rewards for stakers to earn
/// @param token Address of token to reward
/// @param amount Amount of token to transfer to rewards
function notifyRewardAmount(address token, uint256 amount) external;
/// @notice Determine the prior balance for an account as of a block number
/// @dev Block number must be a finalized block or else this function will revert to prevent misinformation.
/// @param tokenId The token of the NFT to check
/// @param timestamp The timestamp to get the balance at
/// @return The balance the account had as of the given block
function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp) external view returns (uint256);
/// @notice Determine the prior index of supply staked by of a timestamp
/// @dev Timestamp must be <= current timestamp
/// @param timestamp The timestamp to get the index at
/// @return Index of supply checkpoint
function getPriorSupplyIndex(uint256 timestamp) external view returns (uint256);
/// @notice Get number of rewards tokens
function rewardsListLength() external view returns (uint256);
/// @notice Calculate how much in rewards are earned for a specific token and veNFT
/// @param token Address of token to fetch rewards of
/// @param tokenId Unique identifier of the veNFT
/// @return Amount of token earned in rewards
function earned(address token, uint256 tokenId) external view returns (uint256);
function checkpoints(uint256 tokenId, uint256 index) external view returns (uint256 timestamp, uint256 balanceOf);
function supplyCheckpoints(uint256 index) external view returns (uint256 timestamp, uint256 supply);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface IVoter {
error AlreadyVotedOrDeposited();
error DistributeWindow();
error FactoryPathNotApproved();
error GaugeAlreadyKilled();
error GaugeAlreadyRevived();
error GaugeExists();
error GaugeDoesNotExist(address _pool);
error GaugeNotAlive(address _gauge);
error InactiveManagedNFT();
error MaximumVotingNumberTooLow();
error NonZeroVotes();
error NotAPool();
error NotApprovedOrOwner();
error NotGovernor();
error NotEmergencyCouncil();
error NotMinter();
error NotWhitelistedNFT();
error NotWhitelistedToken();
error SameValue();
error SpecialVotingWindow();
error TooManyPools();
error UnequalLengths();
error ZeroBalance();
error ZeroAddress();
event GaugeCreated(
address indexed poolFactory,
address indexed votingRewardsFactory,
address indexed gaugeFactory,
address pool,
address bribeVotingReward,
address feeVotingReward,
address gauge,
address creator
);
event GaugeKilled(address indexed gauge);
event GaugeRevived(address indexed gauge);
event Voted(
address indexed voter,
address indexed pool,
uint256 indexed tokenId,
uint256 weight,
uint256 totalWeight,
uint256 timestamp
);
event Abstained(
address indexed voter,
address indexed pool,
uint256 indexed tokenId,
uint256 weight,
uint256 totalWeight,
uint256 timestamp
);
event NotifyReward(address indexed sender, address indexed reward, uint256 amount);
event DistributeReward(address indexed sender, address indexed gauge, uint256 amount);
event WhitelistToken(address indexed whitelister, address indexed token, bool indexed _bool);
event WhitelistNFT(address indexed whitelister, uint256 indexed tokenId, bool indexed _bool);
/// @notice Store trusted forwarder address to pass into factories
function forwarder() external view returns (address);
/// @notice The ve token that governs these contracts
function ve() external view returns (address);
/// @notice Factory registry for valid pool / gauge / rewards factories
function factoryRegistry() external view returns (address);
/// @notice Address of Minter.sol
function minter() external view returns (address);
/// @notice Standard OZ IGovernor using ve for vote weights.
function governor() external view returns (address);
/// @notice Custom Epoch Governor using ve for vote weights.
function epochGovernor() external view returns (address);
/// @notice credibly neutral party similar to Curve's Emergency DAO
function emergencyCouncil() external view returns (address);
/// @dev Total Voting Weights
function totalWeight() external view returns (uint256);
/// @dev Most number of pools one voter can vote for at once
function maxVotingNum() external view returns (uint256);
// mappings
/// @dev Pool => Gauge
function gauges(address pool) external view returns (address);
/// @dev Gauge => Pool
function poolForGauge(address gauge) external view returns (address);
/// @dev Gauge => Fees Voting Reward
function gaugeToFees(address gauge) external view returns (address);
/// @dev Gauge => Bribes Voting Reward
function gaugeToBribe(address gauge) external view returns (address);
/// @dev Pool => Weights
function weights(address pool) external view returns (uint256);
/// @dev NFT => Pool => Votes
function votes(uint256 tokenId, address pool) external view returns (uint256);
/// @dev NFT => Total voting weight of NFT
function usedWeights(uint256 tokenId) external view returns (uint256);
/// @dev Nft => Timestamp of last vote (ensures single vote per epoch)
function lastVoted(uint256 tokenId) external view returns (uint256);
/// @dev Address => Gauge
function isGauge(address) external view returns (bool);
/// @dev Token => Whitelisted status
function isWhitelistedToken(address token) external view returns (bool);
/// @dev TokenId => Whitelisted status
function isWhitelistedNFT(uint256 tokenId) external view returns (bool);
/// @dev Gauge => Liveness status
function isAlive(address gauge) external view returns (bool);
/// @dev Gauge => Amount claimable
function claimable(address gauge) external view returns (uint256);
/// @notice Number of pools with a Gauge
function length() external view returns (uint256);
/// @notice Called by Minter to distribute weekly emissions rewards for disbursement amongst gauges.
/// @dev Assumes totalWeight != 0 (Will never be zero as long as users are voting).
/// Throws if not called by minter.
/// @param _amount Amount of rewards to distribute.
function notifyRewardAmount(uint256 _amount) external;
/// @dev Utility to distribute to gauges of pools in range _start to _finish.
/// @param _start Starting index of gauges to distribute to.
/// @param _finish Ending index of gauges to distribute to.
function distribute(uint256 _start, uint256 _finish) external;
/// @dev Utility to distribute to gauges of pools in array.
/// @param _gauges Array of gauges to distribute to.
function distribute(address[] memory _gauges) external;
/// @notice Called by users to update voting balances in voting rewards contracts.
/// @param _tokenId Id of veNFT whose balance you wish to update.
function poke(uint256 _tokenId) external;
/// @notice Called by users to vote for pools. Votes distributed proportionally based on weights.
/// Can only vote or deposit into a managed NFT once per epoch.
/// Can only vote for gauges that have not been killed.
/// @dev Weights are distributed proportional to the sum of the weights in the array.
/// Throws if length of _poolVote and _weights do not match.
/// @param _tokenId Id of veNFT you are voting with.
/// @param _poolVote Array of pools you are voting for.
/// @param _weights Weights of pools.
function vote(uint256 _tokenId, address[] calldata _poolVote, uint256[] calldata _weights) external;
/// @notice Called by users to reset voting state. Required if you wish to make changes to
/// veNFT state (e.g. merge, split, deposit into managed etc).
/// Cannot reset in the same epoch that you voted in.
/// Can vote or deposit into a managed NFT again after reset.
/// @param _tokenId Id of veNFT you are reseting.
function reset(uint256 _tokenId) external;
/// @notice Called by users to deposit into a managed NFT.
/// Can only vote or deposit into a managed NFT once per epoch.
/// Note that NFTs deposited into a managed NFT will be re-locked
/// to the maximum lock time on withdrawal.
/// @dev Throws if not approved or owner.
/// Throws if managed NFT is inactive.
/// Throws if depositing within privileged window (one hour prior to epoch flip).
function depositManaged(uint256 _tokenId, uint256 _mTokenId) external;
/// @notice Called by users to withdraw from a managed NFT.
/// Cannot do it in the same epoch that you deposited into a managed NFT.
/// Can vote or deposit into a managed NFT again after withdrawing.
/// Note that the NFT withdrawn is re-locked to the maximum lock time.
function withdrawManaged(uint256 _tokenId) external;
/// @notice Claim emissions from gauges.
/// @param _gauges Array of gauges to collect emissions from.
function claimRewards(address[] memory _gauges) external;
/// @notice Claim bribes for a given NFT.
/// @dev Utility to help batch bribe claims.
/// @param _bribes Array of BribeVotingReward contracts to collect from.
/// @param _tokens Array of tokens that are used as bribes.
/// @param _tokenId Id of veNFT that you wish to claim bribes for.
function claimBribes(address[] memory _bribes, address[][] memory _tokens, uint256 _tokenId) external;
/// @notice Claim fees for a given NFT.
/// @dev Utility to help batch fee claims.
/// @param _fees Array of FeesVotingReward contracts to collect from.
/// @param _tokens Array of tokens that are used as fees.
/// @param _tokenId Id of veNFT that you wish to claim fees for.
function claimFees(address[] memory _fees, address[][] memory _tokens, uint256 _tokenId) external;
/// @notice Set new governor.
/// @dev Throws if not called by governor.
/// @param _governor .
function setGovernor(address _governor) external;
/// @notice Set new epoch based governor.
/// @dev Throws if not called by governor.
/// @param _epochGovernor .
function setEpochGovernor(address _epochGovernor) external;
/// @notice Set new emergency council.
/// @dev Throws if not called by emergency council.
/// @param _emergencyCouncil .
function setEmergencyCouncil(address _emergencyCouncil) external;
/// @notice Set maximum number of gauges that can be voted for.
/// @dev Throws if not called by governor.
/// Throws if _maxVotingNum is too low.
/// Throws if the values are the same.
/// @param _maxVotingNum .
function setMaxVotingNum(uint256 _maxVotingNum) external;
/// @notice Whitelist (or unwhitelist) token for use in bribes.
/// @dev Throws if not called by governor.
/// @param _token .
/// @param _bool .
function whitelistToken(address _token, bool _bool) external;
/// @notice Whitelist (or unwhitelist) token id for voting in last hour prior to epoch flip.
/// @dev Throws if not called by governor.
/// Throws if already whitelisted.
/// @param _tokenId .
/// @param _bool .
function whitelistNFT(uint256 _tokenId, bool _bool) external;
/// @notice Create a new gauge (unpermissioned).
/// @dev Governor can create a new gauge for a pool with any address.
/// @param _poolFactory .
/// @param _pool .
function createGauge(address _poolFactory, address _pool) external returns (address);
/// @notice Kills a gauge. The gauge will not receive any new emissions and cannot be deposited into.
/// Can still withdraw from gauge.
/// @dev Throws if not called by emergency council.
/// Throws if gauge already killed.
/// @param _gauge .
function killGauge(address _gauge) external;
/// @notice Revives a killed gauge. Gauge will can receive emissions and deposits again.
/// @dev Throws if not called by emergency council.
/// Throws if gauge is not killed.
/// @param _gauge .
function reviveGauge(address _gauge) external;
/// @dev Update claims to emissions for an array of gauges.
/// @param _gauges Array of gauges to update emissions for.
function updateFor(address[] memory _gauges) external;
/// @dev Update claims to emissions for gauges based on their pool id as stored in Voter.
/// @param _start Starting index of pools.
/// @param _end Ending index of pools.
function updateFor(uint256 _start, uint256 _end) external;
/// @dev Update claims to emissions for single gauge
/// @param _gauge .
function updateFor(address _gauge) external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {IERC165, IERC721, IERC721Metadata} from "@openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol";
import {IERC6372} from "@openzeppelin/contracts/interfaces/IERC6372.sol";
import {IERC4906} from "@openzeppelin/contracts/interfaces/IERC4906.sol";
import {IVotes} from "../governance/IVotes.sol";
interface IVotingEscrow is IVotes, IERC4906, IERC6372, IERC721Metadata {
struct LockedBalance {
int128 amount;
uint256 end;
bool isPermanent;
}
struct UserPoint {
int128 bias;
int128 slope; // # -dweight / dt
uint256 ts;
uint256 blk; // block
uint256 permanent;
}
struct GlobalPoint {
int128 bias;
int128 slope; // # -dweight / dt
uint256 ts;
uint256 blk; // block
uint256 permanentLockBalance;
}
/// @notice A checkpoint for recorded delegated voting weights at a certain timestamp
struct Checkpoint {
uint256 fromTimestamp;
address owner;
uint256 delegatedBalance;
uint256 delegatee;
}
enum DepositType {
DEPOSIT_FOR_TYPE,
CREATE_LOCK_TYPE,
INCREASE_LOCK_AMOUNT,
INCREASE_UNLOCK_TIME
}
/// @dev Different types of veNFTs:
/// NORMAL - typical veNFT
/// LOCKED - veNFT which is locked into a MANAGED veNFT
/// MANAGED - veNFT which can accept the deposit of NORMAL veNFTs
enum EscrowType {
NORMAL,
LOCKED,
MANAGED
}
error AlreadyVoted();
error AmountTooBig();
error ERC721ReceiverRejectedTokens();
error ERC721TransferToNonERC721ReceiverImplementer();
error InvalidNonce();
error InvalidSignature();
error InvalidSignatureS();
error InvalidManagedNFTId();
error LockDurationNotInFuture();
error LockDurationTooLong();
error LockExpired();
error LockNotExpired();
error NoLockFound();
error NonExistentToken();
error NotApprovedOrOwner();
error NotDistributor();
error NotEmergencyCouncilOrGovernor();
error NotGovernor();
error NotGovernorOrManager();
error NotManagedNFT();
error NotManagedOrNormalNFT();
error NotLockedNFT();
error NotNormalNFT();
error NotPermanentLock();
error NotOwner();
error NotTeam();
error NotVoter();
error OwnershipChange();
error PermanentLock();
error SameAddress();
error SameNFT();
error SameState();
error SplitNoOwner();
error SplitNotAllowed();
error SignatureExpired();
error TooManyTokenIDs();
error ZeroAddress();
error ZeroAmount();
error ZeroBalance();
event Deposit(
address indexed provider,
uint256 indexed tokenId,
DepositType indexed depositType,
uint256 value,
uint256 locktime,
uint256 ts
);
event Withdraw(address indexed provider, uint256 indexed tokenId, uint256 value, uint256 ts);
event LockPermanent(address indexed _owner, uint256 indexed _tokenId, uint256 amount, uint256 _ts);
event UnlockPermanent(address indexed _owner, uint256 indexed _tokenId, uint256 amount, uint256 _ts);
event Supply(uint256 prevSupply, uint256 supply);
event Merge(
address indexed _sender,
uint256 indexed _from,
uint256 indexed _to,
uint256 _amountFrom,
uint256 _amountTo,
uint256 _amountFinal,
uint256 _locktime,
uint256 _ts
);
event Split(
uint256 indexed _from,
uint256 indexed _tokenId1,
uint256 indexed _tokenId2,
address _sender,
uint256 _splitAmount1,
uint256 _splitAmount2,
uint256 _locktime,
uint256 _ts
);
event CreateManaged(
address indexed _to,
uint256 indexed _mTokenId,
address indexed _from,
address _lockedManagedReward,
address _freeManagedReward
);
event DepositManaged(
address indexed _owner,
uint256 indexed _tokenId,
uint256 indexed _mTokenId,
uint256 _weight,
uint256 _ts
);
event WithdrawManaged(
address indexed _owner,
uint256 indexed _tokenId,
uint256 indexed _mTokenId,
uint256 _weight,
uint256 _ts
);
event SetAllowedManager(address indexed _allowedManager);
// State variables
/// @notice Address of Meta-tx Forwarder
function forwarder() external view returns (address);
/// @notice Address of FactoryRegistry.sol
function factoryRegistry() external view returns (address);
/// @notice Address of token (NEP) used to create a veNFT
function token() external view returns (address);
/// @notice Address of RewardsDistributor.sol
function distributor() external view returns (address);
/// @notice Address of Voter.sol
function voter() external view returns (address);
/// @notice Address of Protocol Team multisig
function team() external view returns (address);
/// @notice Address of art proxy used for on-chain art generation
function artProxy() external view returns (address);
/// @dev address which can create managed NFTs
function allowedManager() external view returns (address);
/// @dev Current count of token
function tokenId() external view returns (uint256);
/*///////////////////////////////////////////////////////////////
MANAGED NFT STORAGE
//////////////////////////////////////////////////////////////*/
/// @dev Mapping of token id to escrow type
/// Takes advantage of the fact default value is EscrowType.NORMAL
function escrowType(uint256 tokenId) external view returns (EscrowType);
/// @dev Mapping of token id to managed id
function idToManaged(uint256 tokenId) external view returns (uint256 managedTokenId);
/// @dev Mapping of user token id to managed token id to weight of token id
function weights(uint256 tokenId, uint256 managedTokenId) external view returns (uint256 weight);
/// @dev Mapping of managed id to deactivated state
function deactivated(uint256 tokenId) external view returns (bool inactive);
/// @dev Mapping from managed nft id to locked managed rewards
/// `token` denominated rewards (rebases/rewards) stored in locked managed rewards contract
/// to prevent co-mingling of assets
function managedToLocked(uint256 tokenId) external view returns (address);
/// @dev Mapping from managed nft id to free managed rewards contract
/// these rewards can be freely withdrawn by users
function managedToFree(uint256 tokenId) external view returns (address);
/*///////////////////////////////////////////////////////////////
MANAGED NFT LOGIC
//////////////////////////////////////////////////////////////*/
/// @notice Create managed NFT (a permanent lock) for use within ecosystem.
/// @dev Throws if address already owns a managed NFT.
/// @return _mTokenId managed token id.
function createManagedLockFor(address _to) external returns (uint256 _mTokenId);
/// @notice Delegates balance to managed nft
/// Note that NFTs deposited into a managed NFT will be re-locked
/// to the maximum lock time on withdrawal.
/// Permanent locks that are deposited will automatically unlock.
/// @dev Managed nft will remain max-locked as long as there is at least one
/// deposit or withdrawal per week.
/// Throws if deposit nft is managed.
/// Throws if recipient nft is not managed.
/// Throws if deposit nft is already locked.
/// Throws if not called by voter.
/// @param _tokenId tokenId of NFT being deposited
/// @param _mTokenId tokenId of managed NFT that will receive the deposit
function depositManaged(uint256 _tokenId, uint256 _mTokenId) external;
/// @notice Retrieves locked rewards and withdraws balance from managed nft.
/// Note that the NFT withdrawn is re-locked to the maximum lock time.
/// @dev Throws if NFT not locked.
/// Throws if not called by voter.
/// @param _tokenId tokenId of NFT being deposited.
function withdrawManaged(uint256 _tokenId) external;
/// @notice Permit one address to call createManagedLockFor() that is not Voter.governor()
function setAllowedManager(address _allowedManager) external;
/// @notice Set Managed NFT state. Inactive NFTs cannot be deposited into.
/// @param _mTokenId managed nft state to set
/// @param _state true => inactive, false => active
function setManagedState(uint256 _mTokenId, bool _state) external;
/*///////////////////////////////////////////////////////////////
METADATA STORAGE
//////////////////////////////////////////////////////////////*/
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function version() external view returns (string memory);
function decimals() external view returns (uint8);
function setTeam(address _team) external;
function setArtProxy(address _proxy) external;
/// @inheritdoc IERC721Metadata
function tokenURI(uint256 tokenId) external view returns (string memory);
/*//////////////////////////////////////////////////////////////
ERC721 BALANCE/OWNER STORAGE
//////////////////////////////////////////////////////////////*/
/// @dev Mapping from owner address to mapping of index to tokenId
function ownerToNFTokenIdList(address _owner, uint256 _index) external view returns (uint256 _tokenId);
/// @inheritdoc IERC721
function ownerOf(uint256 tokenId) external view returns (address owner);
/// @inheritdoc IERC721
function balanceOf(address owner) external view returns (uint256 balance);
/*//////////////////////////////////////////////////////////////
ERC721 APPROVAL STORAGE
//////////////////////////////////////////////////////////////*/
/// @inheritdoc IERC721
function getApproved(uint256 _tokenId) external view returns (address operator);
/// @inheritdoc IERC721
function isApprovedForAll(address owner, address operator) external view returns (bool);
/// @notice Check whether spender is owner or an approved user for a given veNFT
/// @param _spender .
/// @param _tokenId .
function isApprovedOrOwner(address _spender, uint256 _tokenId) external returns (bool);
/*//////////////////////////////////////////////////////////////
ERC721 LOGIC
//////////////////////////////////////////////////////////////*/
/// @inheritdoc IERC721
function approve(address to, uint256 tokenId) external;
/// @inheritdoc IERC721
function setApprovalForAll(address operator, bool approved) external;
/// @inheritdoc IERC721
function transferFrom(address from, address to, uint256 tokenId) external;
/// @inheritdoc IERC721
function safeTransferFrom(address from, address to, uint256 tokenId) external;
/// @inheritdoc IERC721
function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;
/*//////////////////////////////////////////////////////////////
ERC165 LOGIC
//////////////////////////////////////////////////////////////*/
/// @inheritdoc IERC165
function supportsInterface(bytes4 _interfaceID) external view returns (bool);
/*//////////////////////////////////////////////////////////////
ESCROW STORAGE
//////////////////////////////////////////////////////////////*/
/// @notice Total count of epochs witnessed since contract creation
function epoch() external view returns (uint256);
/// @notice Total amount of token() deposited
function supply() external view returns (uint256);
/// @notice Aggregate permanent locked balances
function permanentLockBalance() external view returns (uint256);
function userPointEpoch(uint256 _tokenId) external view returns (uint256 _epoch);
/// @notice time -> signed slope change
function slopeChanges(uint256 _timestamp) external view returns (int128);
/// @notice account -> can split
function canSplit(address _account) external view returns (bool);
/// @notice Global point history at a given index
function pointHistory(uint256 _loc) external view returns (GlobalPoint memory);
/// @notice Get the LockedBalance (amount, end) of a _tokenId
/// @param _tokenId .
/// @return LockedBalance of _tokenId
function locked(uint256 _tokenId) external view returns (LockedBalance memory);
/// @notice User -> UserPoint[userEpoch]
function userPointHistory(uint256 _tokenId, uint256 _loc) external view returns (UserPoint memory);
/*//////////////////////////////////////////////////////////////
ESCROW LOGIC
//////////////////////////////////////////////////////////////*/
/// @notice Record global data to checkpoint
function checkpoint() external;
/// @notice Deposit `_value` tokens for `_tokenId` and add to the lock
/// @dev Anyone (even a smart contract) can deposit for someone else, but
/// cannot extend their locktime and deposit for a brand new user
/// @param _tokenId lock NFT
/// @param _value Amount to add to user's lock
function depositFor(uint256 _tokenId, uint256 _value) external;
/// @notice Deposit `_value` tokens for `msg.sender` and lock for `_lockDuration`
/// @param _value Amount to deposit
/// @param _lockDuration Number of seconds to lock tokens for (rounded down to nearest week)
/// @return TokenId of created veNFT
function createLock(uint256 _value, uint256 _lockDuration) external returns (uint256);
/// @notice Deposit `_value` tokens for `_to` and lock for `_lockDuration`
/// @param _value Amount to deposit
/// @param _lockDuration Number of seconds to lock tokens for (rounded down to nearest week)
/// @param _to Address to deposit
/// @return TokenId of created veNFT
function createLockFor(uint256 _value, uint256 _lockDuration, address _to) external returns (uint256);
/// @notice Deposit `_value` additional tokens for `_tokenId` without modifying the unlock time
/// @param _value Amount of tokens to deposit and add to the lock
function increaseAmount(uint256 _tokenId, uint256 _value) external;
/// @notice Extend the unlock time for `_tokenId`
/// Cannot extend lock time of permanent locks
/// @param _lockDuration New number of seconds until tokens unlock
function increaseUnlockTime(uint256 _tokenId, uint256 _lockDuration) external;
/// @notice Withdraw all tokens for `_tokenId`
/// @dev Only possible if the lock is both expired and not permanent
/// This will burn the veNFT. Any rebases or rewards that are unclaimed
/// will no longer be claimable. Claim all rebases and rewards prior to calling this.
function withdraw(uint256 _tokenId) external;
/// @notice Merges `_from` into `_to`.
/// @dev Cannot merge `_from` locks that are permanent or have already voted this epoch.
/// Cannot merge `_to` locks that have already expired.
/// This will burn the veNFT. Any rebases or rewards that are unclaimed
/// will no longer be claimable. Claim all rebases and rewards prior to calling this.
/// @param _from VeNFT to merge from.
/// @param _to VeNFT to merge into.
function merge(uint256 _from, uint256 _to) external;
/// @notice Splits veNFT into two new veNFTS - one with oldLocked.amount - `_amount`, and the second with `_amount`
/// @dev This burns the tokenId of the target veNFT
/// Callable by approved or owner
/// If this is called by approved, approved will not have permissions to manipulate the newly created veNFTs
/// Returns the two new split veNFTs to owner
/// If `from` is permanent, will automatically dedelegate.
/// This will burn the veNFT. Any rebases or rewards that are unclaimed
/// will no longer be claimable. Claim all rebases and rewards prior to calling this.
/// @param _from VeNFT to split.
/// @param _amount Amount to split from veNFT.
/// @return _tokenId1 Return tokenId of veNFT with oldLocked.amount - `_amount`.
/// @return _tokenId2 Return tokenId of veNFT with `_amount`.
function split(uint256 _from, uint256 _amount) external returns (uint256 _tokenId1, uint256 _tokenId2);
/// @notice Toggle split for a specific address.
/// @dev Toggle split for address(0) to enable or disable for all.
/// @param _account Address to toggle split permissions
/// @param _bool True to allow, false to disallow
function toggleSplit(address _account, bool _bool) external;
/// @notice Permanently lock a veNFT. Voting power will be equal to
/// `LockedBalance.amount` with no decay. Required to delegate.
/// @dev Only callable by unlocked normal veNFTs.
/// @param _tokenId tokenId to lock.
function lockPermanent(uint256 _tokenId) external;
/// @notice Unlock a permanently locked veNFT. Voting power will decay.
/// Will automatically dedelegate if delegated.
/// @dev Only callable by permanently locked veNFTs.
/// Cannot unlock if already voted this epoch.
/// @param _tokenId tokenId to unlock.
function unlockPermanent(uint256 _tokenId) external;
/*///////////////////////////////////////////////////////////////
GAUGE VOTING STORAGE
//////////////////////////////////////////////////////////////*/
/// @notice Get the voting power for _tokenId at the current timestamp
/// @dev Returns 0 if called in the same block as a transfer.
/// @param _tokenId .
/// @return Voting power
function balanceOfNFT(uint256 _tokenId) external view returns (uint256);
/// @notice Get the voting power for _tokenId at a given timestamp
/// @param _tokenId .
/// @param _t Timestamp to query voting power
/// @return Voting power
function balanceOfNFTAt(uint256 _tokenId, uint256 _t) external view returns (uint256);
/// @notice Calculate total voting power at current timestamp
/// @return Total voting power at current timestamp
function totalSupply() external view returns (uint256);
/// @notice Calculate total voting power at a given timestamp
/// @param _t Timestamp to query total voting power
/// @return Total voting power at given timestamp
function totalSupplyAt(uint256 _t) external view returns (uint256);
/*///////////////////////////////////////////////////////////////
GAUGE VOTING LOGIC
//////////////////////////////////////////////////////////////*/
/// @notice See if a queried _tokenId has actively voted
/// @param _tokenId .
/// @return True if voted, else false
function voted(uint256 _tokenId) external view returns (bool);
/// @notice Set the global state voter and distributor
/// @dev This is only called once, at setup
function setVoterAndDistributor(address _voter, address _distributor) external;
/// @notice Set `voted` for _tokenId to true or false
/// @dev Only callable by voter
/// @param _tokenId .
/// @param _voted .
function voting(uint256 _tokenId, bool _voted) external;
/*///////////////////////////////////////////////////////////////
DAO VOTING STORAGE
//////////////////////////////////////////////////////////////*/
/// @notice The number of checkpoints for each tokenId
function numCheckpoints(uint256 tokenId) external view returns (uint48);
/// @notice A record of states for signing / validating signatures
function nonces(address account) external view returns (uint256);
/// @inheritdoc IVotes
function delegates(uint256 delegator) external view returns (uint256);
/// @notice A record of delegated token checkpoints for each account, by index
/// @param tokenId .
/// @param index .
/// @return Checkpoint
function checkpoints(uint256 tokenId, uint48 index) external view returns (Checkpoint memory);
/// @inheritdoc IVotes
function getPastVotes(address account, uint256 tokenId, uint256 timestamp) external view returns (uint256);
/// @inheritdoc IVotes
function getPastTotalSupply(uint256 timestamp) external view returns (uint256);
/*///////////////////////////////////////////////////////////////
DAO VOTING LOGIC
//////////////////////////////////////////////////////////////*/
/// @inheritdoc IVotes
function delegate(uint256 delegator, uint256 delegatee) external;
/// @inheritdoc IVotes
function delegateBySig(
uint256 delegator,
uint256 delegatee,
uint256 nonce,
uint256 expiry,
uint8 v,
bytes32 r,
bytes32 s
) external;
/*//////////////////////////////////////////////////////////////
ERC6372 LOGIC
//////////////////////////////////////////////////////////////*/
/// @inheritdoc IERC6372
function clock() external view returns (uint48);
/// @inheritdoc IERC6372
function CLOCK_MODE() external view returns (string memory);
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.19;
import {IVotingEscrow} from "../interfaces/IVotingEscrow.sol";
import {IReward} from "contracts/interfaces/IReward.sol";
import {TimeLibrary} from "contracts/libraries/TimeLibrary.sol";
import {SafeCastLibrary} from "./SafeCastLibrary.sol";
import {Math} from "@openzeppelin/contracts/utils/math/Math.sol";
library DelegationHelperLibrary {
uint256 public constant DURATION = 7 days;
/// Helper function to fetch the checkpoint for the last voting checkpoint prior to a timepoint
/// Adapted from DelegationLogicLibrary.sol:getPastVotesIndex(uint256 tokenId, uint256 timestamp)
function getPastCheckpointIndex(
IVotingEscrow ve,
uint256 mTokenId,
uint256 timepoint
) internal view returns (uint48) {
uint48 nCheckpoints = ve.numCheckpoints(mTokenId);
if (nCheckpoints == 0) return 0;
// First check most recent balance
if (ve.checkpoints(mTokenId, nCheckpoints - 1).fromTimestamp <= timepoint) return (nCheckpoints - 1);
// Next check implicit zero balance
if (ve.checkpoints(mTokenId, 0).fromTimestamp > timepoint) return 0;
uint48 lower = 0;
uint48 upper = nCheckpoints - 1;
IVotingEscrow.Checkpoint memory cp;
while (upper > lower) {
uint48 center = upper - (upper - lower) / 2; // ceil, avoiding overflow
cp = ve.checkpoints(mTokenId, center);
if (cp.fromTimestamp == timepoint) {
return center;
} else if (cp.fromTimestamp < timepoint) {
lower = center;
} else {
upper = center - 1;
}
}
return lower;
}
/// Helper function to calculate the locked balance owed to a locked nft at a certain timepoint
/// It calculates the rewards until the end of the current epoch. As rewards are lagged by one epoch
/// This means it includes rewards that the user is projected to get in the following epoch.
/// These rewards are not immediately claimable, but the user can vote as if they claimed it.
/// Adapted from Reward.sol:earned(address token, uint256 tokenId)
function earned(
IVotingEscrow ve,
uint256 mTokenId,
uint256 tokenId,
uint256 timepoint
) internal view returns (uint256) {
IReward lmr = IReward(ve.managedToLocked(mTokenId));
if (lmr.numCheckpoints(tokenId) == 0) {
return 0;
}
address _rewardToken = ve.token();
uint256 reward = 0;
uint256 _supply = 1;
uint256 _currTs = TimeLibrary.epochStart(lmr.lastEarn(_rewardToken, tokenId)); // take epoch last claimed in as starting point
uint256 _index = lmr.getPriorBalanceIndex(tokenId, _currTs);
(uint256 _cpTs, uint256 _cpBalanceOf) = lmr.checkpoints(tokenId, _index);
// accounts for case where lastEarn is before first checkpoint
_currTs = Math.max(_currTs, TimeLibrary.epochStart(_cpTs));
// get epochs between end of the current epoch and first checkpoint in same epoch as last claim
uint256 numEpochs = (TimeLibrary.epochNext(timepoint) - _currTs) / DURATION;
uint256 _priorSupply;
if (numEpochs > 0) {
for (uint256 i = 0; i < numEpochs; i++) {
// get index of last checkpoint in this epoch
_index = lmr.getPriorBalanceIndex(tokenId, _currTs + DURATION - 1);
// get checkpoint in this epoch
(_cpTs, _cpBalanceOf) = lmr.checkpoints(tokenId, _index);
// get supply of last checkpoint in this epoch
(, _priorSupply) = lmr.supplyCheckpoints(lmr.getPriorSupplyIndex(_currTs + DURATION - 1));
_supply = Math.max(_priorSupply, 1);
reward += (_cpBalanceOf * lmr.tokenRewardsPerEpoch(_rewardToken, _currTs)) / _supply;
_currTs += DURATION;
}
}
return reward;
}
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.19;
/// @title SafeCast Library
/// @notice Safely convert unsigned and signed integers without overflow / underflow
library SafeCastLibrary {
error SafeCastOverflow();
error SafeCastUnderflow();
/// @dev Safely convert uint256 to int128
function toInt128(uint256 value) internal pure returns (int128) {
if (value > uint128(type(int128).max)) revert SafeCastOverflow();
return int128(uint128(value));
}
/// @dev Safely convert int128 to uint256
function toUint256(int128 value) internal pure returns (uint256) {
if (value < 0) revert SafeCastUnderflow();
return uint256(int256(value));
}
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.19;
library TimeLibrary {
uint256 internal constant WEEK = 7 days;
/// @dev Returns start of epoch based on current timestamp
function epochStart(uint256 timestamp) internal pure returns (uint256) {
unchecked {
return timestamp - (timestamp % WEEK);
}
}
/// @dev Returns start of next epoch / end of current epoch
function epochNext(uint256 timestamp) internal pure returns (uint256) {
unchecked {
return timestamp - (timestamp % WEEK) + WEEK;
}
}
/// @dev Returns start of voting window
function epochVoteStart(uint256 timestamp) internal pure returns (uint256) {
unchecked {
return timestamp - (timestamp % WEEK) + 1 hours;
}
}
/// @dev Returns end of voting window / beginning of unrestricted voting window
function epochVoteEnd(uint256 timestamp) internal pure returns (uint256) {
unchecked {
return timestamp - (timestamp % WEEK) + WEEK - 1 hours;
}
}
}// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (interfaces/IERC165.sol) pragma solidity ^0.8.0; import "../utils/introspection/IERC165.sol";
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./IERC165.sol";
import "./IERC721.sol";
/// @title EIP-721 Metadata Update Extension
interface IERC4906 is IERC165, IERC721 {
/// @dev This event emits when the metadata of a token is changed.
/// So that the third-party platforms such as NFT market could
/// timely update the images and related attributes of the NFT.
event MetadataUpdate(uint256 _tokenId);
/// @dev This event emits when the metadata of a range of tokens is changed.
/// So that the third-party platforms such as NFT market could
/// timely update the images and related attributes of the NFTs.
event BatchMetadataUpdate(uint256 _fromTokenId, uint256 _toTokenId);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
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 (interfaces/IERC6372.sol)
pragma solidity ^0.8.0;
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 v4.4.1 (interfaces/IERC721.sol) pragma solidity ^0.8.0; import "../token/ERC721/IERC721.sol";
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol)
pragma solidity ^0.8.0;
import "../../utils/introspection/IERC165.sol";
/**
* @dev _Available since v3.1._
*/
interface IERC1155Receiver is IERC165 {
/**
* @dev Handles the receipt of a single ERC1155 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 ERC1155 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 v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)
pragma solidity ^0.8.0;
import "../IERC721.sol";
/**
* @title ERC-721 Non-Fungible Token Standard, optional metadata extension
* @dev See https://eips.ethereum.org/EIPS/eip-721
*/
interface IERC721Metadata is IERC721 {
/**
* @dev Returns the token collection name.
*/
function name() external view returns (string memory);
/**
* @dev Returns the token collection symbol.
*/
function symbol() external view returns (string memory);
/**
* @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.
*/
function tokenURI(uint256 tokenId) external view returns (string memory);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/IERC721.sol)
pragma solidity ^0.8.0;
import "../../utils/introspection/IERC165.sol";
/**
* @dev Required interface of an ERC721 compliant contract.
*/
interface IERC721 is IERC165 {
/**
* @dev Emitted when `tokenId` token is transferred from `from` to `to`.
*/
event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
*/
event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.
*/
event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
/**
* @dev Returns the number of tokens in ``owner``'s account.
*/
function balanceOf(address owner) external view returns (uint256 balance);
/**
* @dev Returns the owner of the `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function ownerOf(uint256 tokenId) external view returns (address owner);
/**
* @dev Safely transfers `tokenId` token from `from` to `to`.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;
/**
* @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
* are aware of the ERC721 protocol to prevent tokens from being forever locked.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function safeTransferFrom(address from, address to, uint256 tokenId) external;
/**
* @dev Transfers `tokenId` token from `from` to `to`.
*
* WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721
* or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must
* understand this adds an external call which potentially creates a reentrancy vulnerability.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
*
* Emits a {Transfer} event.
*/
function transferFrom(address from, address to, uint256 tokenId) external;
/**
* @dev Gives permission to `to` to transfer `tokenId` token to another account.
* The approval is cleared when the token is transferred.
*
* Only a single account can be approved at a time, so approving the zero address clears previous approvals.
*
* Requirements:
*
* - The caller must own the token or be an approved operator.
* - `tokenId` must exist.
*
* Emits an {Approval} event.
*/
function approve(address to, uint256 tokenId) external;
/**
* @dev Approve or remove `operator` as an operator for the caller.
* Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.
*
* Requirements:
*
* - The `operator` cannot be the caller.
*
* Emits an {ApprovalForAll} event.
*/
function setApprovalForAll(address operator, bool approved) external;
/**
* @dev Returns the account approved for `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function getApproved(uint256 tokenId) external view returns (address operator);
/**
* @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
*
* See {setApprovalForAll}
*/
function isApprovedForAll(address owner, address operator) external view returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)
pragma solidity ^0.8.0;
/**
* @title ERC721 token receiver interface
* @dev Interface for any contract that wants to support safeTransfers
* from ERC721 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 v4.8.0) (utils/Address.sol)
pragma solidity ^0.8.1;
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
*
* Furthermore, `isContract` will also return true if the target contract within
* the same transaction is already scheduled for destruction by `SELFDESTRUCT`,
* which only has an effect at the end of a transaction.
* ====
*
* [IMPORTANT]
* ====
* You shouldn't rely on `isContract` to protect against flash loan attacks!
*
* Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
* like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
* constructor.
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize/address.code.length, which returns 0
// for contracts in construction, since the code is only stored at the end
// of the constructor execution.
return account.code.length > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
* the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
*
* _Available since v4.8._
*/
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata,
string memory errorMessage
) internal view returns (bytes memory) {
if (success) {
if (returndata.length == 0) {
// only check isContract if the call was successful and the return data is empty
// otherwise we already know that it was a contract
require(isContract(target), "Address: call to non-contract");
}
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
/**
* @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason or using the provided one.
*
* _Available since v4.3._
*/
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
function _revert(bytes memory returndata, string memory errorMessage) private pure {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
/// @solidity memory-safe-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/Checkpoints.sol)
// This file was procedurally generated from scripts/generate/templates/Checkpoints.js.
pragma solidity ^0.8.0;
import "./math/Math.sol";
import "./math/SafeCast.sol";
/**
* @dev This library defines the `History` 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.History` in your contract, and store a new
* checkpoint for the current transaction block using the {push} function.
*
* _Available since v4.5._
*/
library Checkpoints {
struct History {
Checkpoint[] _checkpoints;
}
struct Checkpoint {
uint32 _blockNumber;
uint224 _value;
}
/**
* @dev Returns the value at a given block number. If a checkpoint is not available at that block, the closest one
* before it is returned, or zero otherwise. Because the number returned corresponds to that at the end of the
* block, the requested block number must be in the past, excluding the current block.
*/
function getAtBlock(History storage self, uint256 blockNumber) internal view returns (uint256) {
require(blockNumber < block.number, "Checkpoints: block not yet mined");
uint32 key = SafeCast.toUint32(blockNumber);
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 at a given block number. If a checkpoint is not available at that block, the closest one
* before it is returned, or zero otherwise. Similar to {upperLookup} but optimized for the case when the searched
* checkpoint is probably "recent", defined as being among the last sqrt(N) checkpoints where N is the number of
* checkpoints.
*/
function getAtProbablyRecentBlock(History storage self, uint256 blockNumber) internal view returns (uint256) {
require(blockNumber < block.number, "Checkpoints: block not yet mined");
uint32 key = SafeCast.toUint32(blockNumber);
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)._blockNumber) {
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 Pushes a value onto a History so that it is stored as the checkpoint for the current block.
*
* Returns previous value and new value.
*/
function push(History storage self, uint256 value) internal returns (uint256, uint256) {
return _insert(self._checkpoints, SafeCast.toUint32(block.number), SafeCast.toUint224(value));
}
/**
* @dev Pushes a value onto a History, by updating the latest value using binary operation `op`. The new value will
* be set to `op(latest, delta)`.
*
* Returns previous value and new value.
*/
function push(
History storage self,
function(uint256, uint256) view returns (uint256) op,
uint256 delta
) internal returns (uint256, uint256) {
return push(self, op(latest(self), delta));
}
/**
* @dev Returns the value in the most recent checkpoint, or zero if there are no checkpoints.
*/
function latest(History 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(
History storage self
) internal view returns (bool exists, uint32 _blockNumber, uint224 _value) {
uint256 pos = self._checkpoints.length;
if (pos == 0) {
return (false, 0, 0);
} else {
Checkpoint memory ckpt = _unsafeAccess(self._checkpoints, pos - 1);
return (true, ckpt._blockNumber, ckpt._value);
}
}
/**
* @dev Returns the number of checkpoint.
*/
function length(History storage self) internal view returns (uint256) {
return self._checkpoints.length;
}
/**
* @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(Checkpoint[] storage self, uint32 key, uint224 value) private returns (uint224, uint224) {
uint256 pos = self.length;
if (pos > 0) {
// Copying to memory is important here.
Checkpoint memory last = _unsafeAccess(self, pos - 1);
// Checkpoint keys must be non-decreasing.
require(last._blockNumber <= key, "Checkpoint: decreasing keys");
// Update or push new checkpoint
if (last._blockNumber == key) {
_unsafeAccess(self, pos - 1)._value = value;
} else {
self.push(Checkpoint({_blockNumber: key, _value: value}));
}
return (last._value, value);
} else {
self.push(Checkpoint({_blockNumber: key, _value: value}));
return (0, value);
}
}
/**
* @dev Return the index of the oldest checkpoint whose key is greater 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(
Checkpoint[] 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)._blockNumber > key) {
high = mid;
} else {
low = mid + 1;
}
}
return high;
}
/**
* @dev Return the index of the oldest checkpoint whose key is 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(
Checkpoint[] 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)._blockNumber < 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(Checkpoint[] storage self, uint256 pos) private pure returns (Checkpoint storage result) {
assembly {
mstore(0, self.slot)
result.slot := add(keccak256(0, 0x20), pos)
}
}
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.
*/
function push(Trace224 storage self, uint32 key, uint224 value) internal returns (uint224, uint224) {
return _insert(self._checkpoints, key, value);
}
/**
* @dev Returns the value in the 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 most recent checkpoint with key lower or equal than the search key.
*/
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 most recent checkpoint with key lower or equal than the search key.
*
* NOTE: This is a variant of {upperLookup} that is optimised 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 memory ckpt = _unsafeAccess(self._checkpoints, pos - 1);
return (true, ckpt._key, ckpt._value);
}
}
/**
* @dev Returns the number of checkpoint.
*/
function length(Trace224 storage self) internal view returns (uint256) {
return self._checkpoints.length;
}
/**
* @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, uint224) {
uint256 pos = self.length;
if (pos > 0) {
// Copying to memory is important here.
Checkpoint224 memory last = _unsafeAccess(self, pos - 1);
// Checkpoint keys must be non-decreasing.
require(last._key <= key, "Checkpoint: decreasing keys");
// Update or push new checkpoint
if (last._key == key) {
_unsafeAccess(self, pos - 1)._value = value;
} else {
self.push(Checkpoint224({_key: key, _value: value}));
}
return (last._value, value);
} else {
self.push(Checkpoint224({_key: key, _value: value}));
return (0, value);
}
}
/**
* @dev Return the index of the oldest checkpoint whose key is greater 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 oldest checkpoint whose key is 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 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.
*/
function push(Trace160 storage self, uint96 key, uint160 value) internal returns (uint160, uint160) {
return _insert(self._checkpoints, key, value);
}
/**
* @dev Returns the value in the 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 most recent checkpoint with key lower or equal than the search key.
*/
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 most recent checkpoint with key lower or equal than the search key.
*
* NOTE: This is a variant of {upperLookup} that is optimised 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 memory ckpt = _unsafeAccess(self._checkpoints, pos - 1);
return (true, ckpt._key, ckpt._value);
}
}
/**
* @dev Returns the number of checkpoint.
*/
function length(Trace160 storage self) internal view returns (uint256) {
return self._checkpoints.length;
}
/**
* @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, uint160) {
uint256 pos = self.length;
if (pos > 0) {
// Copying to memory is important here.
Checkpoint160 memory last = _unsafeAccess(self, pos - 1);
// Checkpoint keys must be non-decreasing.
require(last._key <= key, "Checkpoint: decreasing keys");
// Update or push new checkpoint
if (last._key == key) {
_unsafeAccess(self, pos - 1)._value = value;
} else {
self.push(Checkpoint160({_key: key, _value: value}));
}
return (last._value, value);
} else {
self.push(Checkpoint160({_key: key, _value: value}));
return (0, value);
}
}
/**
* @dev Return the index of the oldest checkpoint whose key is greater 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 oldest checkpoint whose key is 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 v4.4.1 (utils/Context.sol)
pragma solidity ^0.8.0;
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/ECDSA.sol)
pragma solidity ^0.8.0;
import "../Strings.sol";
/**
* @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.
*
* These functions can be used to verify that a message was signed by the holder
* of the private keys of a given address.
*/
library ECDSA {
enum RecoverError {
NoError,
InvalidSignature,
InvalidSignatureLength,
InvalidSignatureS,
InvalidSignatureV // Deprecated in v4.8
}
function _throwError(RecoverError error) private pure {
if (error == RecoverError.NoError) {
return; // no error: do nothing
} else if (error == RecoverError.InvalidSignature) {
revert("ECDSA: invalid signature");
} else if (error == RecoverError.InvalidSignatureLength) {
revert("ECDSA: invalid signature length");
} else if (error == RecoverError.InvalidSignatureS) {
revert("ECDSA: invalid signature 's' value");
}
}
/**
* @dev Returns the address that signed a hashed message (`hash`) with
* `signature` or error string. This address can then be used for verification purposes.
*
* The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
* this function rejects them by requiring the `s` value to be in the lower
* half order, and the `v` value to be either 27 or 28.
*
* IMPORTANT: `hash` _must_ be the result of a hash operation for the
* verification to be secure: it is possible to craft signatures that
* recover to arbitrary addresses for non-hashed data. A safe way to ensure
* this is by receiving a hash of the original message (which may otherwise
* be too long), and then calling {toEthSignedMessageHash} on it.
*
* Documentation for signature generation:
* - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]
* - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]
*
* _Available since v4.3._
*/
function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {
if (signature.length == 65) {
bytes32 r;
bytes32 s;
uint8 v;
// ecrecover takes the signature parameters, and the only way to get them
// currently is to use assembly.
/// @solidity memory-safe-assembly
assembly {
r := mload(add(signature, 0x20))
s := mload(add(signature, 0x40))
v := byte(0, mload(add(signature, 0x60)))
}
return tryRecover(hash, v, r, s);
} else {
return (address(0), RecoverError.InvalidSignatureLength);
}
}
/**
* @dev Returns the address that signed a hashed message (`hash`) with
* `signature`. This address can then be used for verification purposes.
*
* The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
* this function rejects them by requiring the `s` value to be in the lower
* half order, and the `v` value to be either 27 or 28.
*
* IMPORTANT: `hash` _must_ be the result of a hash operation for the
* verification to be secure: it is possible to craft signatures that
* recover to arbitrary addresses for non-hashed data. A safe way to ensure
* this is by receiving a hash of the original message (which may otherwise
* be too long), and then calling {toEthSignedMessageHash} on it.
*/
function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {
(address recovered, RecoverError error) = tryRecover(hash, signature);
_throwError(error);
return recovered;
}
/**
* @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.
*
* See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]
*
* _Available since v4.3._
*/
function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {
bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);
uint8 v = uint8((uint256(vs) >> 255) + 27);
return tryRecover(hash, v, r, s);
}
/**
* @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.
*
* _Available since v4.2._
*/
function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {
(address recovered, RecoverError error) = tryRecover(hash, r, vs);
_throwError(error);
return recovered;
}
/**
* @dev Overload of {ECDSA-tryRecover} that receives the `v`,
* `r` and `s` signature fields separately.
*
* _Available since v4.3._
*/
function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {
// EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature
// unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines
// the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most
// signatures from current libraries generate a unique signature with an s-value in the lower half order.
//
// If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value
// with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or
// vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept
// these malleable signatures as well.
if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {
return (address(0), RecoverError.InvalidSignatureS);
}
// If the signature is valid (and not malleable), return the signer address
address signer = ecrecover(hash, v, r, s);
if (signer == address(0)) {
return (address(0), RecoverError.InvalidSignature);
}
return (signer, RecoverError.NoError);
}
/**
* @dev Overload of {ECDSA-recover} that receives the `v`,
* `r` and `s` signature fields separately.
*/
function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {
(address recovered, RecoverError error) = tryRecover(hash, v, r, s);
_throwError(error);
return recovered;
}
/**
* @dev Returns an Ethereum Signed Message, created from a `hash`. This
* produces hash corresponding to the one signed with the
* https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]
* JSON-RPC method as part of EIP-191.
*
* See {recover}.
*/
function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32 message) {
// 32 is the length in bytes of hash,
// enforced by the type signature above
/// @solidity memory-safe-assembly
assembly {
mstore(0x00, "\x19Ethereum Signed Message:\n32")
mstore(0x1c, hash)
message := keccak256(0x00, 0x3c)
}
}
/**
* @dev Returns an Ethereum Signed Message, created from `s`. This
* produces hash corresponding to the one signed with the
* https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]
* JSON-RPC method as part of EIP-191.
*
* See {recover}.
*/
function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {
return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n", Strings.toString(s.length), s));
}
/**
* @dev Returns an Ethereum Signed Typed Data, created from a
* `domainSeparator` and a `structHash`. This produces hash corresponding
* to the one signed with the
* https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]
* JSON-RPC method as part of EIP-712.
*
* See {recover}.
*/
function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 data) {
/// @solidity memory-safe-assembly
assembly {
let ptr := mload(0x40)
mstore(ptr, "\x19\x01")
mstore(add(ptr, 0x02), domainSeparator)
mstore(add(ptr, 0x22), structHash)
data := keccak256(ptr, 0x42)
}
}
/**
* @dev Returns an Ethereum Signed Data with intended validator, created from a
* `validator` and `data` according to the version 0 of EIP-191.
*
* See {recover}.
*/
function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) {
return keccak256(abi.encodePacked("\x19\x00", validator, data));
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/EIP712.sol)
pragma solidity ^0.8.8;
import "./ECDSA.sol";
import "../ShortStrings.sol";
import "../../interfaces/IERC5267.sol";
/**
* @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.
*
* The encoding specified in the EIP is very generic, and such a generic 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 their contracts 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: In the upgradeable version of this contract, the cached values will correspond to the address, and the domain
* separator of the implementation contract. This will cause the `_domainSeparatorV4` function to always rebuild the
* separator from the immutable values, which is cheaper than accessing a cached version in cold storage.
*
* _Available since v3.4._
*
* @custom:oz-upgrades-unsafe-allow state-variable-immutable state-variable-assignment
*/
abstract contract EIP712 is IERC5267 {
using ShortStrings for *;
bytes32 private constant _TYPE_HASH =
keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)");
/* solhint-disable var-name-mixedcase */
// Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to
// invalidate the cached domain separator if the chain id changes.
bytes32 private immutable _cachedDomainSeparator;
uint256 private immutable _cachedChainId;
address private immutable _cachedThis;
ShortString private immutable _name;
ShortString private immutable _version;
string private _nameFallback;
string private _versionFallback;
bytes32 private immutable _hashedName;
bytes32 private immutable _hashedVersion;
/* solhint-enable var-name-mixedcase */
/**
* @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].
*/
constructor(string memory name, string memory version) {
_name = name.toShortStringWithFallback(_nameFallback);
_version = version.toShortStringWithFallback(_versionFallback);
_hashedName = keccak256(bytes(name));
_hashedVersion = keccak256(bytes(version));
_cachedChainId = block.chainid;
_cachedDomainSeparator = _buildDomainSeparator();
_cachedThis = address(this);
}
/**
* @dev Returns the domain separator for the current chain.
*/
function _domainSeparatorV4() internal view returns (bytes32) {
if (address(this) == _cachedThis && block.chainid == _cachedChainId) {
return _cachedDomainSeparator;
} else {
return _buildDomainSeparator();
}
}
function _buildDomainSeparator() private view returns (bytes32) {
return keccak256(abi.encode(_TYPE_HASH, _hashedName, _hashedVersion, 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 ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash);
}
/**
* @dev See {EIP-5267}.
*/
function eip712Domain()
public
view
virtual
override
returns (
bytes1 fields,
string memory name,
string memory version,
uint256 chainId,
address verifyingContract,
bytes32 salt,
uint256[] memory extensions
)
{
return (
hex"0f", // 01111
_name.toStringWithFallback(_nameFallback),
_version.toStringWithFallback(_versionFallback),
block.chainid,
address(this),
bytes32(0),
new uint256[](0)
);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)
pragma solidity ^0.8.0;
import "./IERC165.sol";
/**
* @dev Implementation of the {IERC165} interface.
*
* Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check
* for the additional interface id that will be supported. For example:
*
* ```solidity
* function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
* return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
* }
* ```
*
* Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.
*/
abstract contract ERC165 is IERC165 {
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IERC165).interfaceId;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[EIP].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/
interface IERC165 {
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)
pragma solidity ^0.8.0;
/**
* @dev Standard math utilities missing in the Solidity language.
*/
library Math {
enum Rounding {
Down, // Toward negative infinity
Up, // Toward infinity
Zero // Toward zero
}
/**
* @dev Returns the largest of two numbers.
*/
function max(uint256 a, uint256 b) internal pure returns (uint256) {
return a > b ? a : b;
}
/**
* @dev Returns the smallest of two numbers.
*/
function min(uint256 a, uint256 b) internal pure returns (uint256) {
return a < b ? a : b;
}
/**
* @dev Returns the average of two numbers. The result is rounded towards
* zero.
*/
function average(uint256 a, uint256 b) internal pure returns (uint256) {
// (a + b) / 2 can overflow.
return (a & b) + (a ^ b) / 2;
}
/**
* @dev Returns the ceiling of the division of two numbers.
*
* This differs from standard division with `/` in that it rounds up instead
* of rounding down.
*/
function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
// (a + b - 1) / b can overflow on addition, so we distribute.
return a == 0 ? 0 : (a - 1) / b + 1;
}
/**
* @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
* @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)
* with further edits by Uniswap Labs also under MIT license.
*/
function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {
unchecked {
// 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use
// use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
// variables such that product = prod1 * 2^256 + prod0.
uint256 prod0; // Least significant 256 bits of the product
uint256 prod1; // Most significant 256 bits of the product
assembly {
let mm := mulmod(x, y, not(0))
prod0 := mul(x, y)
prod1 := sub(sub(mm, prod0), lt(mm, prod0))
}
// Handle non-overflow cases, 256 by 256 division.
if (prod1 == 0) {
return prod0 / denominator;
}
// Make sure the result is less than 2^256. Also prevents denominator == 0.
require(denominator > prod1, "Math: mulDiv overflow");
///////////////////////////////////////////////
// 512 by 256 division.
///////////////////////////////////////////////
// Make division exact by subtracting the remainder from [prod1 prod0].
uint256 remainder;
assembly {
// Compute remainder using mulmod.
remainder := mulmod(x, y, denominator)
// Subtract 256 bit number from 512 bit number.
prod1 := sub(prod1, gt(remainder, prod0))
prod0 := sub(prod0, remainder)
}
// Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.
// See https://cs.stackexchange.com/q/138556/92363.
// Does not overflow because the denominator cannot be zero at this stage in the function.
uint256 twos = denominator & (~denominator + 1);
assembly {
// Divide denominator by twos.
denominator := div(denominator, twos)
// Divide [prod1 prod0] by twos.
prod0 := div(prod0, twos)
// Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.
twos := add(div(sub(0, twos), twos), 1)
}
// Shift in bits from prod1 into prod0.
prod0 |= prod1 * twos;
// Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such
// that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for
// four bits. That is, denominator * inv = 1 mod 2^4.
uint256 inverse = (3 * denominator) ^ 2;
// Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works
// in modular arithmetic, doubling the correct bits in each step.
inverse *= 2 - denominator * inverse; // inverse mod 2^8
inverse *= 2 - denominator * inverse; // inverse mod 2^16
inverse *= 2 - denominator * inverse; // inverse mod 2^32
inverse *= 2 - denominator * inverse; // inverse mod 2^64
inverse *= 2 - denominator * inverse; // inverse mod 2^128
inverse *= 2 - denominator * inverse; // inverse mod 2^256
// Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
// This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is
// less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1
// is no longer required.
result = prod0 * inverse;
return result;
}
}
/**
* @notice Calculates x * y / denominator with full precision, following the selected rounding direction.
*/
function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {
uint256 result = mulDiv(x, y, denominator);
if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {
result += 1;
}
return result;
}
/**
* @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.
*
* Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11).
*/
function sqrt(uint256 a) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
// For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.
//
// We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have
// `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.
//
// This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`
// → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`
// → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`
//
// Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.
uint256 result = 1 << (log2(a) >> 1);
// At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,
// since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at
// every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision
// into the expected uint128 result.
unchecked {
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
return min(result, a / result);
}
}
/**
* @notice Calculates sqrt(a), following the selected rounding direction.
*/
function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = sqrt(a);
return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);
}
}
/**
* @dev Return the log in base 2, rounded down, of a positive value.
* Returns 0 if given 0.
*/
function log2(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 128;
}
if (value >> 64 > 0) {
value >>= 64;
result += 64;
}
if (value >> 32 > 0) {
value >>= 32;
result += 32;
}
if (value >> 16 > 0) {
value >>= 16;
result += 16;
}
if (value >> 8 > 0) {
value >>= 8;
result += 8;
}
if (value >> 4 > 0) {
value >>= 4;
result += 4;
}
if (value >> 2 > 0) {
value >>= 2;
result += 2;
}
if (value >> 1 > 0) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 2, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log2(value);
return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 10, rounded down, of a positive value.
* Returns 0 if given 0.
*/
function log10(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >= 10 ** 64) {
value /= 10 ** 64;
result += 64;
}
if (value >= 10 ** 32) {
value /= 10 ** 32;
result += 32;
}
if (value >= 10 ** 16) {
value /= 10 ** 16;
result += 16;
}
if (value >= 10 ** 8) {
value /= 10 ** 8;
result += 8;
}
if (value >= 10 ** 4) {
value /= 10 ** 4;
result += 4;
}
if (value >= 10 ** 2) {
value /= 10 ** 2;
result += 2;
}
if (value >= 10 ** 1) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 10, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log10(value);
return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 256, rounded down, of a positive value.
* Returns 0 if given 0.
*
* Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
*/
function log256(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 16;
}
if (value >> 64 > 0) {
value >>= 64;
result += 8;
}
if (value >> 32 > 0) {
value >>= 32;
result += 4;
}
if (value >> 16 > 0) {
value >>= 16;
result += 2;
}
if (value >> 8 > 0) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 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 + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)
// This file was procedurally generated from scripts/generate/templates/SafeCast.js.
pragma solidity ^0.8.0;
/**
* @dev Wrappers over Solidity's uintXX/intXX 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.
*
* Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing
* all math on `uint256` and `int256` and then downcasting.
*/
library SafeCast {
/**
* @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
*
* _Available since v4.7._
*/
function toUint248(uint256 value) internal pure returns (uint248) {
require(value <= type(uint248).max, "SafeCast: value doesn't fit in 248 bits");
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
*
* _Available since v4.7._
*/
function toUint240(uint256 value) internal pure returns (uint240) {
require(value <= type(uint240).max, "SafeCast: value doesn't fit in 240 bits");
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
*
* _Available since v4.7._
*/
function toUint232(uint256 value) internal pure returns (uint232) {
require(value <= type(uint232).max, "SafeCast: value doesn't fit in 232 bits");
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
*
* _Available since v4.2._
*/
function toUint224(uint256 value) internal pure returns (uint224) {
require(value <= type(uint224).max, "SafeCast: value doesn't fit in 224 bits");
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
*
* _Available since v4.7._
*/
function toUint216(uint256 value) internal pure returns (uint216) {
require(value <= type(uint216).max, "SafeCast: value doesn't fit in 216 bits");
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
*
* _Available since v4.7._
*/
function toUint208(uint256 value) internal pure returns (uint208) {
require(value <= type(uint208).max, "SafeCast: value doesn't fit in 208 bits");
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
*
* _Available since v4.7._
*/
function toUint200(uint256 value) internal pure returns (uint200) {
require(value <= type(uint200).max, "SafeCast: value doesn't fit in 200 bits");
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
*
* _Available since v4.7._
*/
function toUint192(uint256 value) internal pure returns (uint192) {
require(value <= type(uint192).max, "SafeCast: value doesn't fit in 192 bits");
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
*
* _Available since v4.7._
*/
function toUint184(uint256 value) internal pure returns (uint184) {
require(value <= type(uint184).max, "SafeCast: value doesn't fit in 184 bits");
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
*
* _Available since v4.7._
*/
function toUint176(uint256 value) internal pure returns (uint176) {
require(value <= type(uint176).max, "SafeCast: value doesn't fit in 176 bits");
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
*
* _Available since v4.7._
*/
function toUint168(uint256 value) internal pure returns (uint168) {
require(value <= type(uint168).max, "SafeCast: value doesn't fit in 168 bits");
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
*
* _Available since v4.7._
*/
function toUint160(uint256 value) internal pure returns (uint160) {
require(value <= type(uint160).max, "SafeCast: value doesn't fit in 160 bits");
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
*
* _Available since v4.7._
*/
function toUint152(uint256 value) internal pure returns (uint152) {
require(value <= type(uint152).max, "SafeCast: value doesn't fit in 152 bits");
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
*
* _Available since v4.7._
*/
function toUint144(uint256 value) internal pure returns (uint144) {
require(value <= type(uint144).max, "SafeCast: value doesn't fit in 144 bits");
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
*
* _Available since v4.7._
*/
function toUint136(uint256 value) internal pure returns (uint136) {
require(value <= type(uint136).max, "SafeCast: value doesn't fit in 136 bits");
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
*
* _Available since v2.5._
*/
function toUint128(uint256 value) internal pure returns (uint128) {
require(value <= type(uint128).max, "SafeCast: value doesn't fit in 128 bits");
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
*
* _Available since v4.7._
*/
function toUint120(uint256 value) internal pure returns (uint120) {
require(value <= type(uint120).max, "SafeCast: value doesn't fit in 120 bits");
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
*
* _Available since v4.7._
*/
function toUint112(uint256 value) internal pure returns (uint112) {
require(value <= type(uint112).max, "SafeCast: value doesn't fit in 112 bits");
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
*
* _Available since v4.7._
*/
function toUint104(uint256 value) internal pure returns (uint104) {
require(value <= type(uint104).max, "SafeCast: value doesn't fit in 104 bits");
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
*
* _Available since v4.2._
*/
function toUint96(uint256 value) internal pure returns (uint96) {
require(value <= type(uint96).max, "SafeCast: value doesn't fit in 96 bits");
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
*
* _Available since v4.7._
*/
function toUint88(uint256 value) internal pure returns (uint88) {
require(value <= type(uint88).max, "SafeCast: value doesn't fit in 88 bits");
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
*
* _Available since v4.7._
*/
function toUint80(uint256 value) internal pure returns (uint80) {
require(value <= type(uint80).max, "SafeCast: value doesn't fit in 80 bits");
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
*
* _Available since v4.7._
*/
function toUint72(uint256 value) internal pure returns (uint72) {
require(value <= type(uint72).max, "SafeCast: value doesn't fit in 72 bits");
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
*
* _Available since v2.5._
*/
function toUint64(uint256 value) internal pure returns (uint64) {
require(value <= type(uint64).max, "SafeCast: value doesn't fit in 64 bits");
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
*
* _Available since v4.7._
*/
function toUint56(uint256 value) internal pure returns (uint56) {
require(value <= type(uint56).max, "SafeCast: value doesn't fit in 56 bits");
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
*
* _Available since v4.7._
*/
function toUint48(uint256 value) internal pure returns (uint48) {
require(value <= type(uint48).max, "SafeCast: value doesn't fit in 48 bits");
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
*
* _Available since v4.7._
*/
function toUint40(uint256 value) internal pure returns (uint40) {
require(value <= type(uint40).max, "SafeCast: value doesn't fit in 40 bits");
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
*
* _Available since v2.5._
*/
function toUint32(uint256 value) internal pure returns (uint32) {
require(value <= type(uint32).max, "SafeCast: value doesn't fit in 32 bits");
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
*
* _Available since v4.7._
*/
function toUint24(uint256 value) internal pure returns (uint24) {
require(value <= type(uint24).max, "SafeCast: value doesn't fit in 24 bits");
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
*
* _Available since v2.5._
*/
function toUint16(uint256 value) internal pure returns (uint16) {
require(value <= type(uint16).max, "SafeCast: value doesn't fit in 16 bits");
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
*
* _Available since v2.5._
*/
function toUint8(uint256 value) internal pure returns (uint8) {
require(value <= type(uint8).max, "SafeCast: value doesn't fit in 8 bits");
return uint8(value);
}
/**
* @dev Converts a signed int256 into an unsigned uint256.
*
* Requirements:
*
* - input must be greater than or equal to 0.
*
* _Available since v3.0._
*/
function toUint256(int256 value) internal pure returns (uint256) {
require(value >= 0, "SafeCast: value must be positive");
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
*
* _Available since v4.7._
*/
function toInt248(int256 value) internal pure returns (int248 downcasted) {
downcasted = int248(value);
require(downcasted == value, "SafeCast: value doesn't fit in 248 bits");
}
/**
* @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
*
* _Available since v4.7._
*/
function toInt240(int256 value) internal pure returns (int240 downcasted) {
downcasted = int240(value);
require(downcasted == value, "SafeCast: value doesn't fit in 240 bits");
}
/**
* @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
*
* _Available since v4.7._
*/
function toInt232(int256 value) internal pure returns (int232 downcasted) {
downcasted = int232(value);
require(downcasted == value, "SafeCast: value doesn't fit in 232 bits");
}
/**
* @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
*
* _Available since v4.7._
*/
function toInt224(int256 value) internal pure returns (int224 downcasted) {
downcasted = int224(value);
require(downcasted == value, "SafeCast: value doesn't fit in 224 bits");
}
/**
* @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
*
* _Available since v4.7._
*/
function toInt216(int256 value) internal pure returns (int216 downcasted) {
downcasted = int216(value);
require(downcasted == value, "SafeCast: value doesn't fit in 216 bits");
}
/**
* @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
*
* _Available since v4.7._
*/
function toInt208(int256 value) internal pure returns (int208 downcasted) {
downcasted = int208(value);
require(downcasted == value, "SafeCast: value doesn't fit in 208 bits");
}
/**
* @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
*
* _Available since v4.7._
*/
function toInt200(int256 value) internal pure returns (int200 downcasted) {
downcasted = int200(value);
require(downcasted == value, "SafeCast: value doesn't fit in 200 bits");
}
/**
* @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
*
* _Available since v4.7._
*/
function toInt192(int256 value) internal pure returns (int192 downcasted) {
downcasted = int192(value);
require(downcasted == value, "SafeCast: value doesn't fit in 192 bits");
}
/**
* @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
*
* _Available since v4.7._
*/
function toInt184(int256 value) internal pure returns (int184 downcasted) {
downcasted = int184(value);
require(downcasted == value, "SafeCast: value doesn't fit in 184 bits");
}
/**
* @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
*
* _Available since v4.7._
*/
function toInt176(int256 value) internal pure returns (int176 downcasted) {
downcasted = int176(value);
require(downcasted == value, "SafeCast: value doesn't fit in 176 bits");
}
/**
* @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
*
* _Available since v4.7._
*/
function toInt168(int256 value) internal pure returns (int168 downcasted) {
downcasted = int168(value);
require(downcasted == value, "SafeCast: value doesn't fit in 168 bits");
}
/**
* @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
*
* _Available since v4.7._
*/
function toInt160(int256 value) internal pure returns (int160 downcasted) {
downcasted = int160(value);
require(downcasted == value, "SafeCast: value doesn't fit in 160 bits");
}
/**
* @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
*
* _Available since v4.7._
*/
function toInt152(int256 value) internal pure returns (int152 downcasted) {
downcasted = int152(value);
require(downcasted == value, "SafeCast: value doesn't fit in 152 bits");
}
/**
* @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
*
* _Available since v4.7._
*/
function toInt144(int256 value) internal pure returns (int144 downcasted) {
downcasted = int144(value);
require(downcasted == value, "SafeCast: value doesn't fit in 144 bits");
}
/**
* @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
*
* _Available since v4.7._
*/
function toInt136(int256 value) internal pure returns (int136 downcasted) {
downcasted = int136(value);
require(downcasted == value, "SafeCast: value doesn't fit in 136 bits");
}
/**
* @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
*
* _Available since v3.1._
*/
function toInt128(int256 value) internal pure returns (int128 downcasted) {
downcasted = int128(value);
require(downcasted == value, "SafeCast: value doesn't fit in 128 bits");
}
/**
* @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
*
* _Available since v4.7._
*/
function toInt120(int256 value) internal pure returns (int120 downcasted) {
downcasted = int120(value);
require(downcasted == value, "SafeCast: value doesn't fit in 120 bits");
}
/**
* @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
*
* _Available since v4.7._
*/
function toInt112(int256 value) internal pure returns (int112 downcasted) {
downcasted = int112(value);
require(downcasted == value, "SafeCast: value doesn't fit in 112 bits");
}
/**
* @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
*
* _Available since v4.7._
*/
function toInt104(int256 value) internal pure returns (int104 downcasted) {
downcasted = int104(value);
require(downcasted == value, "SafeCast: value doesn't fit in 104 bits");
}
/**
* @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
*
* _Available since v4.7._
*/
function toInt96(int256 value) internal pure returns (int96 downcasted) {
downcasted = int96(value);
require(downcasted == value, "SafeCast: value doesn't fit in 96 bits");
}
/**
* @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
*
* _Available since v4.7._
*/
function toInt88(int256 value) internal pure returns (int88 downcasted) {
downcasted = int88(value);
require(downcasted == value, "SafeCast: value doesn't fit in 88 bits");
}
/**
* @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
*
* _Available since v4.7._
*/
function toInt80(int256 value) internal pure returns (int80 downcasted) {
downcasted = int80(value);
require(downcasted == value, "SafeCast: value doesn't fit in 80 bits");
}
/**
* @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
*
* _Available since v4.7._
*/
function toInt72(int256 value) internal pure returns (int72 downcasted) {
downcasted = int72(value);
require(downcasted == value, "SafeCast: value doesn't fit in 72 bits");
}
/**
* @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
*
* _Available since v3.1._
*/
function toInt64(int256 value) internal pure returns (int64 downcasted) {
downcasted = int64(value);
require(downcasted == value, "SafeCast: value doesn't fit in 64 bits");
}
/**
* @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
*
* _Available since v4.7._
*/
function toInt56(int256 value) internal pure returns (int56 downcasted) {
downcasted = int56(value);
require(downcasted == value, "SafeCast: value doesn't fit in 56 bits");
}
/**
* @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
*
* _Available since v4.7._
*/
function toInt48(int256 value) internal pure returns (int48 downcasted) {
downcasted = int48(value);
require(downcasted == value, "SafeCast: value doesn't fit in 48 bits");
}
/**
* @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
*
* _Available since v4.7._
*/
function toInt40(int256 value) internal pure returns (int40 downcasted) {
downcasted = int40(value);
require(downcasted == value, "SafeCast: value doesn't fit in 40 bits");
}
/**
* @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
*
* _Available since v3.1._
*/
function toInt32(int256 value) internal pure returns (int32 downcasted) {
downcasted = int32(value);
require(downcasted == value, "SafeCast: value doesn't fit in 32 bits");
}
/**
* @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
*
* _Available since v4.7._
*/
function toInt24(int256 value) internal pure returns (int24 downcasted) {
downcasted = int24(value);
require(downcasted == value, "SafeCast: value doesn't fit in 24 bits");
}
/**
* @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
*
* _Available since v3.1._
*/
function toInt16(int256 value) internal pure returns (int16 downcasted) {
downcasted = int16(value);
require(downcasted == value, "SafeCast: value doesn't fit in 16 bits");
}
/**
* @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
*
* _Available since v3.1._
*/
function toInt8(int256 value) internal pure returns (int8 downcasted) {
downcasted = int8(value);
require(downcasted == value, "SafeCast: value doesn't fit in 8 bits");
}
/**
* @dev Converts an unsigned uint256 into a signed int256.
*
* Requirements:
*
* - input must be less than or equal to maxInt256.
*
* _Available since v3.0._
*/
function toInt256(uint256 value) internal pure returns (int256) {
// Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive
require(value <= uint256(type(int256).max), "SafeCast: value doesn't fit in an int256");
return int256(value);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)
pragma solidity ^0.8.0;
/**
* @dev Standard signed math utilities missing in the Solidity language.
*/
library SignedMath {
/**
* @dev Returns the largest of two signed numbers.
*/
function max(int256 a, int256 b) internal pure returns (int256) {
return a > b ? a : b;
}
/**
* @dev Returns the smallest of two signed numbers.
*/
function min(int256 a, int256 b) internal pure returns (int256) {
return 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 {
// must be unchecked in order to support `n = type(int256).min`
return uint256(n >= 0 ? n : -n);
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.8;
import "./StorageSlot.sol";
type ShortString is bytes32;
/**
* @dev This library provides functions to convert short memory strings
* into a `ShortString` type that can be used as an immutable variable.
* Strings of arbitrary length can be optimized if they are short enough by
* the addition of a storage variable used as fallback.
*
* Usage example:
*
* ```solidity
* contract Named {
* using ShortStrings for *;
*
* ShortString private immutable _name;
* string private _nameFallback;
*
* constructor(string memory contractName) {
* _name = contractName.toShortStringWithFallback(_nameFallback);
* }
*
* function name() external view returns (string memory) {
* return _name.toStringWithFallback(_nameFallback);
* }
* }
* ```
*/
library ShortStrings {
error StringTooLong(string str);
/**
* @dev Encode a string of at most 31 chars into a `ShortString`.
*
* This will trigger a `StringTooLong` error is the input string is too long.
*/
function toShortString(string memory str) internal pure returns (ShortString) {
bytes memory bstr = bytes(str);
if (bstr.length > 31) {
revert StringTooLong(str);
}
return ShortString.wrap(bytes32(uint256(bytes32(bstr)) | bstr.length));
}
/**
* @dev Decode a `ShortString` back to a "normal" string.
*/
function toString(ShortString sstr) internal pure returns (string memory) {
uint256 len = length(sstr);
// using `new string(len)` would work locally but is not memory safe.
string memory str = new string(32);
/// @solidity memory-safe-assembly
assembly {
mstore(str, len)
mstore(add(str, 0x20), sstr)
}
return str;
}
/**
* @dev Return the length of a `ShortString`.
*/
function length(ShortString sstr) internal pure returns (uint256) {
return uint256(ShortString.unwrap(sstr)) & 0xFF;
}
/**
* @dev Encode a string into a `ShortString`, or write it to storage if it is too long.
*/
function toShortStringWithFallback(string memory value, string storage store) internal returns (ShortString) {
if (bytes(value).length < 32) {
return toShortString(value);
} else {
StorageSlot.getStringSlot(store).value = value;
return ShortString.wrap(0);
}
}
/**
* @dev Decode a string that was encoded to `ShortString` or written to storage using {setWithFallback}.
*/
function toStringWithFallback(ShortString value, string storage store) internal pure returns (string memory) {
if (length(value) > 0) {
return toString(value);
} else {
return store;
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (utils/StorageSlot.sol)
// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.
pragma solidity ^0.8.0;
/**
* @dev Library for reading and writing primitive types to specific storage slots.
*
* Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.
* This library helps with reading and writing to such slots without the need for inline assembly.
*
* The functions in this library return Slot structs that contain a `value` member that can be used to read or write.
*
* Example usage to set ERC1967 implementation slot:
* ```solidity
* contract ERC1967 {
* bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
*
* function _getImplementation() internal view returns (address) {
* return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;
* }
*
* function _setImplementation(address newImplementation) internal {
* require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract");
* StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
* }
* }
* ```
*
* _Available since v4.1 for `address`, `bool`, `bytes32`, `uint256`._
* _Available since v4.9 for `string`, `bytes`._
*/
library StorageSlot {
struct AddressSlot {
address value;
}
struct BooleanSlot {
bool value;
}
struct Bytes32Slot {
bytes32 value;
}
struct Uint256Slot {
uint256 value;
}
struct StringSlot {
string value;
}
struct BytesSlot {
bytes value;
}
/**
* @dev Returns an `AddressSlot` with member `value` located at `slot`.
*/
function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `BooleanSlot` with member `value` located at `slot`.
*/
function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `Bytes32Slot` with member `value` located at `slot`.
*/
function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `Uint256Slot` with member `value` located at `slot`.
*/
function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `StringSlot` with member `value` located at `slot`.
*/
function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `StringSlot` representation of the string storage pointer `store`.
*/
function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := store.slot
}
}
/**
* @dev Returns an `BytesSlot` with member `value` located at `slot`.
*/
function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.
*/
function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := store.slot
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)
pragma solidity ^0.8.0;
import "./math/Math.sol";
import "./math/SignedMath.sol";
/**
* @dev String operations.
*/
library Strings {
bytes16 private constant _SYMBOLS = "0123456789abcdef";
uint8 private constant _ADDRESS_LENGTH = 20;
/**
* @dev Converts a `uint256` to its ASCII `string` decimal representation.
*/
function toString(uint256 value) internal pure returns (string memory) {
unchecked {
uint256 length = Math.log10(value) + 1;
string memory buffer = new string(length);
uint256 ptr;
/// @solidity memory-safe-assembly
assembly {
ptr := add(buffer, add(32, length))
}
while (true) {
ptr--;
/// @solidity memory-safe-assembly
assembly {
mstore8(ptr, byte(mod(value, 10), _SYMBOLS))
}
value /= 10;
if (value == 0) break;
}
return buffer;
}
}
/**
* @dev Converts a `int256` to its ASCII `string` decimal representation.
*/
function toString(int256 value) internal pure returns (string memory) {
return string(abi.encodePacked(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) {
bytes memory buffer = new bytes(2 * length + 2);
buffer[0] = "0";
buffer[1] = "x";
for (uint256 i = 2 * length + 1; i > 1; --i) {
buffer[i] = _SYMBOLS[value & 0xf];
value >>= 4;
}
require(value == 0, "Strings: hex length insufficient");
return string(buffer);
}
/**
* @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.
*/
function toHexString(address addr) internal pure returns (string memory) {
return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);
}
/**
* @dev Returns true if the two strings are equal.
*/
function equal(string memory a, string memory b) internal pure returns (bool) {
return keccak256(bytes(a)) == keccak256(bytes(b));
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (utils/structs/DoubleEndedQueue.sol)
pragma solidity ^0.8.4;
import "../math/SafeCast.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;
* ```
*
* _Available since v4.6._
*/
library DoubleEndedQueue {
/**
* @dev An operation (e.g. {front}) couldn't be completed due to the queue being empty.
*/
error Empty();
/**
* @dev An operation (e.g. {at}) couldn't be completed due to an index being out of bounds.
*/
error OutOfBounds();
/**
* @dev Indices are signed integers because the queue can grow in any direction. They are 128 bits so begin and end
* are packed in a single storage slot for efficient access. Since the items are added one at a time we can safely
* assume that these 128-bit indices will not overflow, and use unchecked arithmetic.
*
* 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.
*
* Indices are in the range [begin, end) which means the first item is at data[begin] and the last item is at
* data[end - 1].
*/
struct Bytes32Deque {
int128 _begin;
int128 _end;
mapping(int128 => bytes32) _data;
}
/**
* @dev Inserts an item at the end of the queue.
*/
function pushBack(Bytes32Deque storage deque, bytes32 value) internal {
int128 backIndex = deque._end;
deque._data[backIndex] = value;
unchecked {
deque._end = backIndex + 1;
}
}
/**
* @dev Removes the item at the end of the queue and returns it.
*
* Reverts with `Empty` if the queue is empty.
*/
function popBack(Bytes32Deque storage deque) internal returns (bytes32 value) {
if (empty(deque)) revert Empty();
int128 backIndex;
unchecked {
backIndex = deque._end - 1;
}
value = deque._data[backIndex];
delete deque._data[backIndex];
deque._end = backIndex;
}
/**
* @dev Inserts an item at the beginning of the queue.
*/
function pushFront(Bytes32Deque storage deque, bytes32 value) internal {
int128 frontIndex;
unchecked {
frontIndex = deque._begin - 1;
}
deque._data[frontIndex] = value;
deque._begin = frontIndex;
}
/**
* @dev Removes the item at the beginning of the queue and returns it.
*
* Reverts with `Empty` if the queue is empty.
*/
function popFront(Bytes32Deque storage deque) internal returns (bytes32 value) {
if (empty(deque)) revert Empty();
int128 frontIndex = deque._begin;
value = deque._data[frontIndex];
delete deque._data[frontIndex];
unchecked {
deque._begin = frontIndex + 1;
}
}
/**
* @dev Returns the item at the beginning of the queue.
*
* Reverts with `Empty` if the queue is empty.
*/
function front(Bytes32Deque storage deque) internal view returns (bytes32 value) {
if (empty(deque)) revert Empty();
int128 frontIndex = deque._begin;
return deque._data[frontIndex];
}
/**
* @dev Returns the item at the end of the queue.
*
* Reverts with `Empty` if the queue is empty.
*/
function back(Bytes32Deque storage deque) internal view returns (bytes32 value) {
if (empty(deque)) revert Empty();
int128 backIndex;
unchecked {
backIndex = deque._end - 1;
}
return deque._data[backIndex];
}
/**
* @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 `OutOfBounds` if the index is out of bounds.
*/
function at(Bytes32Deque storage deque, uint256 index) internal view returns (bytes32 value) {
// int256(deque._begin) is a safe upcast
int128 idx = SafeCast.toInt128(int256(deque._begin) + SafeCast.toInt256(index));
if (idx >= deque._end) revert OutOfBounds();
return deque._data[idx];
}
/**
* @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) {
// The interface preserves the invariant that begin <= end so we assume this will not overflow.
// We also assume there are at most int256.max items in the queue.
unchecked {
return uint256(int256(deque._end) - int256(deque._begin));
}
}
/**
* @dev Returns true if the queue is empty.
*/
function empty(Bytes32Deque storage deque) internal view returns (bool) {
return deque._end <= deque._begin;
}
}{
"optimizer": {
"enabled": true,
"runs": 200
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"metadata": {
"useLiteralContent": true
},
"remappings": [
"@opengsn/=lib/gsn/packages/",
"@openzeppelin/=lib/openzeppelin-contracts/",
"@uniswap/v3-core/=lib/v3-core/",
"ds-test/=lib/ds-test/src/",
"erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/",
"forge-std/=lib/forge-std/src/",
"gsn/=lib/gsn/",
"openzeppelin-contracts/=lib/openzeppelin-contracts/",
"solady/=lib/solady/src/",
"utils/=test/utils/"
],
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"contract IVotes","name":"_ve","type":"address"},{"internalType":"contract IVoter","name":"_voter","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"CommentWeightingTooHigh","type":"error"},{"inputs":[],"name":"Empty","type":"error"},{"inputs":[],"name":"NotGovernor","type":"error"},{"inputs":[],"name":"NotPendingTeam","type":"error"},{"inputs":[],"name":"NotPendingVetoer","type":"error"},{"inputs":[],"name":"NotTeam","type":"error"},{"inputs":[],"name":"NotVetoer","type":"error"},{"inputs":[],"name":"ProposalNumeratorTooHigh","type":"error"},{"inputs":[{"internalType":"string","name":"str","type":"string"}],"name":"StringTooLong","type":"error"},{"inputs":[],"name":"ZeroAddress","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"newTeam","type":"address"}],"name":"AcceptTeam","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"vetoer","type":"address"}],"name":"AcceptVetoer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"proposalId","type":"uint256"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"string","name":"comment","type":"string"}],"name":"Comment","type":"event"},{"anonymous":false,"inputs":[],"name":"EIP712DomainChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"oldVoteExtension","type":"uint64"},{"indexed":false,"internalType":"uint64","name":"newVoteExtension","type":"uint64"}],"name":"LateQuorumVoteExtensionSet","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":true,"internalType":"uint256","name":"proposalId","type":"uint256"},{"indexed":false,"internalType":"uint64","name":"extendedDeadline","type":"uint64"}],"name":"ProposalExtended","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"proposalId","type":"uint256"}],"name":"ProposalVetoed","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":[],"name":"RenounceVetoer","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"commentWeighting","type":"uint256"}],"name":"SetCommentWeighting","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"proposalNumerator","type":"uint256"}],"name":"SetProposalNumerator","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"voter","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"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":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"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"},{"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":"view","type":"function"},{"inputs":[],"name":"COMMENT_DENOMINATOR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","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":[],"name":"MAX_PROPOSAL_NUMERATOR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PROPOSAL_DENOMINATOR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"acceptTeam","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"acceptVetoer","outputs":[],"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":"cancel","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"},{"internalType":"uint256","name":"tokenId","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":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint8","name":"support","type":"uint8"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"castVoteBySig","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"},{"internalType":"uint256","name":"tokenId","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":"uint256","name":"tokenId","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":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint8","name":"support","type":"uint8"},{"internalType":"string","name":"reason","type":"string"},{"internalType":"bytes","name":"params","type":"bytes"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"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":[{"internalType":"uint256","name":"proposalId","type":"uint256"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"string","name":"message","type":"string"}],"name":"comment","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"commentWeighting","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","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":[],"name":"escrow","outputs":[{"internalType":"contract IVotingEscrow","name":"","type":"address"}],"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"},{"internalType":"address","name":"proposer","type":"address"}],"name":"execute","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"timepoint","type":"uint256"}],"name":"getVotes","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"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":"tokenId","type":"uint256"},{"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":"uint256","name":"tokenId","type":"uint256"}],"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"},{"internalType":"address","name":"proposer","type":"address"}],"name":"hashProposal","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"lateQuorumVoteExtension","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"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":[],"name":"pendingTeam","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingVetoer","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"}],"name":"proposalDeadline","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"proposalNumerator","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"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":"uint256","name":"tokenId","type":"uint256"},{"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":"uint256","name":"timepoint","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":[],"name":"renounceVetoer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_commentWeighting","type":"uint256"}],"name":"setCommentWeighting","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"newVoteExtension","type":"uint64"}],"name":"setLateQuorumVoteExtension","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"numerator","type":"uint256"}],"name":"setProposalNumerator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_pendingTeam","type":"address"}],"name":"setTeam","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_vetoer","type":"address"}],"name":"setVetoer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"}],"name":"state","outputs":[{"internalType":"enum IVetoGovernor.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":"team","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"token","outputs":[{"internalType":"contract IVotes","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"newQuorumNumerator","type":"uint256"}],"name":"updateQuorumNumerator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"ve","outputs":[{"internalType":"contract IVotingEscrow","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_proposalId","type":"uint256"}],"name":"veto","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"vetoer","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"voter","outputs":[{"internalType":"contract IVoter","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"votingDelay","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"votingPeriod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"stateMutability":"payable","type":"receive"}]Contract Creation Code
6101e0604052610fa060035560646010553480156200001d57600080fd5b506040516200658738038062006587833981016040819052620000409162000850565b6202a30060198360405180604001604052806011815260200170283937ba37b1b7b61023b7bb32b93737b960791b815250858162000083620001b460201b60201c565b62000090826000620001cf565b60e052620000a0816001620001cf565b61010052815160208084019190912061012052815190820120610140524660a052620001306101205161014051604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60208201529081019290925260608201524660808201523060a082015260009060c00160405160208183030381529060405280519060200120905090565b60805250503060c052600262000147838262000934565b506001600160a01b0390811661016052919091166101808190526101a05250620001718162000208565b506200017d816200038b565b50600e8054336001600160a01b03199182168117909255600c805490911690911790556001600160a01b03166101c0525062000ac1565b6040805180820190915260018152603160f81b602082015290565b6000602083511015620001ef57620001e783620003f4565b905062000202565b81620001fc848262000934565b50600090505b92915050565b6064811115620002915760405162461bcd60e51b815260206004820152604360248201527f476f7665726e6f72566f74657351756f72756d4672616374696f6e3a2071756f60448201527f72756d4e756d657261746f72206f7665722071756f72756d44656e6f6d696e616064820152623a37b960e91b608482015260a4015b60405180910390fd5b60006200029d62000437565b90508015801590620002af5750600954155b156200031757604080518082019091526000815260099060208101620002d58462000466565b6001600160e01b0390811690915282546001810184556000938452602093849020835194909301519091166401000000000263ffffffff909316929092179101555b6200034c6200033762000329620004d5565b65ffffffffffff166200054c565b620003428462000466565b60099190620005b3565b505060408051828152602081018490527f0553476bf02ef2726e8ce5ced78d63e26e602e4a2257b1f559418e24b4633997910160405180910390a15050565b600a54604080516001600160401b03928316815291831660208301527f7ca4ac117ed3cdce75c1161d8207c440389b1a15d69d096831664657c07dafc2910160405180910390a1600a80546001600160401b0319166001600160401b0392909216919091179055565b600080829050601f8151111562000422578260405163305a27a960e01b815260040162000288919062000a00565b80516200042f8262000a50565b179392505050565b600954600090156200045d576200044f6009620005d0565b6001600160e01b0316905090565b6008545b905090565b60006001600160e01b03821115620004d15760405162461bcd60e51b815260206004820152602760248201527f53616665436173743a2076616c756520646f65736e27742066697420696e20326044820152663234206269747360c81b606482015260840162000288565b5090565b6000610180516001600160a01b03166391ddadf46040518163ffffffff1660e01b8152600401602060405180830381865afa92505050801562000537575060408051601f3d908101601f19168201909252620005349181019062000a75565b60015b620005475762000461436200061e565b919050565b600063ffffffff821115620004d15760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203360448201526532206269747360d01b606482015260840162000288565b600080620005c385858562000687565b915091505b935093915050565b805460009080156200061457620005fc83620005ee60018462000a9f565b600091825260209091200190565b5464010000000090046001600160e01b031662000617565b60005b9392505050565b600065ffffffffffff821115620004d15760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203460448201526538206269747360d01b606482015260840162000288565b825460009081908015620007dc576000620006a987620005ee60018562000a9f565b60408051808201909152905463ffffffff8082168084526401000000009092046001600160e01b0316602084015291925090871610156200072d5760405162461bcd60e51b815260206004820152601b60248201527f436865636b706f696e743a2064656372656173696e67206b6579730000000000604482015260640162000288565b805163ffffffff8088169116036200077b57846200075288620005ee60018662000a9f565b80546001600160e01b03929092166401000000000263ffffffff909216919091179055620007cb565b6040805180820190915263ffffffff80881682526001600160e01b0380881660208085019182528b54600181018d5560008d81529190912094519151909216640100000000029216919091179101555b602001519250839150620005c89050565b50506040805180820190915263ffffffff80851682526001600160e01b0380851660208085019182528854600181018a5560008a815291822095519251909316640100000000029190931617920191909155905081620005c8565b6001600160a01b03811681146200084d57600080fd5b50565b600080604083850312156200086457600080fd5b8251620008718162000837565b6020840151909250620008848162000837565b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b600181811c90821680620008ba57607f821691505b602082108103620008db57634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200092f57600081815260208120601f850160051c810160208610156200090a5750805b601f850160051c820191505b818110156200092b5782815560010162000916565b5050505b505050565b81516001600160401b038111156200095057620009506200088f565b6200096881620009618454620008a5565b84620008e1565b602080601f831160018114620009a05760008415620009875750858301515b600019600386901b1c1916600185901b1785556200092b565b600085815260208120601f198616915b82811015620009d157888601518255948401946001909101908401620009b0565b5085821015620009f05787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b600060208083528351808285015260005b8181101562000a2f5785810183015185820160400152820162000a11565b506000604082860101526040601f19601f8301168501019250505092915050565b80516020808301519190811015620008db5760001960209190910360031b1b16919050565b60006020828403121562000a8857600080fd5b815165ffffffffffff811681146200061757600080fd5b818103818111156200020257634e487b7160e01b600052601160045260246000fd5b60805160a05160c05160e05161010051610120516101405161016051610180516101a0516101c0516159cf62000bb86000396000818161069a01526116e301526000818161052101528181611c7401528181612600015281816127aa0152818161282e01528181612887015281816129c80152612a44015260008181610c56015281816117d301528181611bc701528181611dec015281816121990152818161271e015281816129300152612abe015260008181610b96015261130f0152600061405c0152600061403401526000611b7301526000611b4901526000613f8f01526000613fb901526000613fe301526159cf6000f3fe6080604052600436106103b15760003560e01c806367e2e078116101e7578063c01f9e371161010d578063dea112a6116100a0578063f8ce560a1161006f578063f8ce560a14610be4578063f945970a14610c04578063fa25f37714610c24578063fc0c546a14610c4457600080fd5b8063dea112a614610b30578063deaaa7cc14610b50578063e2fdcc1714610b84578063f23a6e6114610bb857600080fd5b8063d07f91e9116100dc578063d07f91e914610a8a578063d152a32e14610aaa578063d8bff44014610aca578063dd4e2ba514610aea57600080fd5b8063c01f9e3714610a17578063c28bc2fa14610a37578063c2e863e414610a4a578063cf781d4514610a6a57600080fd5b80639f8b339211610185578063b58131b011610154578063b58131b0146109a1578063b5cc143a146109b6578063bc197c81146109cb578063be443ad0146109f757600080fd5b80639f8b339214610936578063a67d06351461094c578063a7713a701461096c578063aedbfe331461098157600080fd5b806391ddadf4116101c157806391ddadf4146108c157806391f36633146108ed57806395b6d6bd1461090d57806397c3d3341461092257600080fd5b806367e2e0781461086357806384b0196e1461087957806385f2aef2146108a157600080fd5b80633932abb1116102d7578063544ffc9c1161026a57806360c4247f1161023957806360c4247f146107dc57806360e69a7b146107fc578063638663ac1461080f57806364390ff11461082457600080fd5b8063544ffc9c1461071d57806354fd4d5014610772578063592a84941461079c57806359d46ffc146107bc57600080fd5b806349758df2116102a657806349758df2146106bc5780634bf5d7e9146106dc578063501fa8bd146106f1578063525f9c3e1461070757600080fd5b80633932abb1146106255780633e4f49e61461063b578063452115d61461066857806346c96aac1461068857600080fd5b8063150b7a021161034f5780632d63f6931161031e5780632d63f693146105735780632fe3e261146105a957806332b8113e146105dd578063380a243a1461060557600080fd5b8063150b7a02146104b65780631d28dec7146104ef5780631f8507161461050f57806322b36ac61461055b57600080fd5b806306fdde031161038b57806306fdde0314610434578063095cf5c6146104565780630f8a88361461047657806311fd26f41461049657600080fd5b806301ffc9a7146103bf57806302a251a3146103f457806306f3f9e61461041457600080fd5b366103ba57005b005b600080fd5b3480156103cb57600080fd5b506103df6103da366004614842565b610c78565b60405190151581526020015b60405180910390f35b34801561040057600080fd5b50620697805b6040519081526020016103eb565b34801561042057600080fd5b506103b861042f36600461486c565b610ce5565b34801561044057600080fd5b50610449610d30565b6040516103eb91906148d5565b34801561046257600080fd5b506103b86104713660046148fd565b610dc2565b34801561048257600080fd5b50610406610491366004614b46565b610e36565b3480156104a257600080fd5b506104066104b1366004614c10565b6111d9565b3480156104c257600080fd5b506104d66104d1366004614c45565b611205565b6040516001600160e01b031990911681526020016103eb565b3480156104fb57600080fd5b506103b861050a36600461486c565b611216565b34801561051b57600080fd5b506105437f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016103eb565b34801561056757600080fd5b50610406633b9aca0081565b34801561057f57600080fd5b5061040661058e36600461486c565b6000908152600460205260409020546001600160401b031690565b3480156105b557600080fd5b506104067fb3b3f3b703cd84ce352197dcff232b1b5d3cfb2025ce47cf04742d0651f1af8881565b3480156105e957600080fd5b50600a546040516001600160401b0390911681526020016103eb565b34801561061157600080fd5b506103b8610620366004614cf8565b61124e565b34801561063157600080fd5b506202a300610406565b34801561064757600080fd5b5061065b61065636600461486c565b61145f565b6040516103eb9190614d60565b34801561067457600080fd5b50610406610683366004614d88565b6115ad565b34801561069457600080fd5b506105437f000000000000000000000000000000000000000000000000000000000000000081565b3480156106c857600080fd5b506103b86106d736600461486c565b6116bc565b3480156106e857600080fd5b506104496117cf565b3480156106fd57600080fd5b506104066101f481565b34801561071357600080fd5b5061040660035481565b34801561072957600080fd5b5061075761073836600461486c565b6000908152600760205260409020805460018201546002909201549092565b604080519384526020840192909252908201526060016103eb565b34801561077e57600080fd5b506040805180820190915260018152603160f81b6020820152610449565b3480156107a857600080fd5b506103b86107b736600461486c565b611891565b3480156107c857600080fd5b50600d54610543906001600160a01b031681565b3480156107e857600080fd5b506104066107f736600461486c565b611912565b61040661080a366004614e17565b6119c3565b34801561081b57600080fd5b506103b8611ad5565b34801561083057600080fd5b506103df61083f366004614ebd565b60009182526007602090815260408084209284526003909201905290205460ff1690565b34801561086f57600080fd5b5061040661271081565b34801561088557600080fd5b5061088e611b3b565b6040516103eb9796959493929190614f1a565b3480156108ad57600080fd5b50600c54610543906001600160a01b031681565b3480156108cd57600080fd5b506108d6611bc3565b60405165ffffffffffff90911681526020016103eb565b3480156108f957600080fd5b50610406610908366004614ebd565b611c51565b34801561091957600080fd5b506103b8611cfc565b34801561092e57600080fd5b506064610406565b34801561094257600080fd5b5061040660105481565b34801561095857600080fd5b50600f54610543906001600160a01b031681565b34801561097857600080fd5b50610406611d7b565b34801561098d57600080fd5b5061040661099c366004614e17565b611da5565b3480156109ad57600080fd5b50610406611de2565b3480156109c257600080fd5b506103b8611e99565b3480156109d757600080fd5b506104d66109e6366004614f8a565b63bc197c8160e01b95945050505050565b348015610a0357600080fd5b50610406610a1236600461503b565b611f18565b348015610a2357600080fd5b50610406610a3236600461486c565b611f6f565b6103b8610a453660046150c6565b611f7a565b348015610a5657600080fd5b50610406610a65366004615109565b612041565b348015610a7657600080fd5b50610406610a85366004615170565b61208a565b348015610a9657600080fd5b506103b8610aa53660046151ba565b6120a1565b348015610ab657600080fd5b506103b8610ac53660046148fd565b6120e0565b348015610ad657600080fd5b50600e54610543906001600160a01b031681565b348015610af657600080fd5b506040805180820190915260208082527f737570706f72743d627261766f2671756f72756d3d666f722c6162737461696e90820152610449565b348015610b3c57600080fd5b50610406610b4b3660046151e3565b612154565b348015610b5c57600080fd5b506104067f150214d74d59b7d1e90c73fc22ef3d991dd0a76b046543d4d80ab92d2a50328f81565b348015610b9057600080fd5b506105437f000000000000000000000000000000000000000000000000000000000000000081565b348015610bc457600080fd5b506104d6610bd3366004615218565b63f23a6e6160e01b95945050505050565b348015610bf057600080fd5b50610406610bff36600461486c565b612176565b348015610c1057600080fd5b50610406610c1f366004615280565b612220565b348015610c3057600080fd5b50610406610c3f366004615330565b61231a565b348015610c5057600080fd5b506105437f000000000000000000000000000000000000000000000000000000000000000081565b60006001600160e01b031982166367276c3760e01b1480610ca957506001600160e01b03198216631debdb9560e31b145b80610cc457506001600160e01b03198216630271189760e51b145b80610cdf57506301ffc9a760e01b6001600160e01b03198316145b92915050565b333014610d0d5760405162461bcd60e51b8152600401610d0490615388565b60405180910390fd5b610d24565b80610d1d6005612386565b03610d1257505b610d2d81612405565b50565b606060028054610d3f906153cf565b80601f0160208091040260200160405190810160405280929190818152602001828054610d6b906153cf565b8015610db85780601f10610d8d57610100808354040283529160200191610db8565b820191906000526020600020905b815481529060010190602001808311610d9b57829003601f168201915b5050505050905090565b6001600160a01b038116610de95760405163d92e233d60e01b815260040160405180910390fd5b600c546001600160a01b03163314610e1457604051633a7cfa5d60e21b815260040160405180910390fd5b600d80546001600160a01b0319166001600160a01b0392909216919091179055565b60003381610e42611bc3565b65ffffffffffff169050610e54611de2565b610e64838a6104b160018661541f565b1015610ecc5760405162461bcd60e51b815260206004820152603160248201527f476f7665726e6f723a2070726f706f73657220766f7465732062656c6f7720706044820152701c9bdc1bdcd85b081d1a1c995cda1bdb19607a1b6064820152608401610d04565b6000610ee2888888888051906020012087611da5565b90508651885114610f055760405162461bcd60e51b8152600401610d0490615432565b8551885114610f265760405162461bcd60e51b8152600401610d0490615432565b6000885111610f775760405162461bcd60e51b815260206004820152601860248201527f476f7665726e6f723a20656d7074792070726f706f73616c00000000000000006044820152606401610d04565b600081815260046020526040902054600160401b90046001600160a01b031615610fed5760405162461bcd60e51b815260206004820152602160248201527f476f7665726e6f723a2070726f706f73616c20616c72656164792065786973746044820152607360f81b6064820152608401610d04565b6000610ffc6202a30084615473565b9050600061100d6206978083615473565b905060405180610100016040528061102484612573565b6001600160401b031681526001600160a01b03871660208201526000604082015260600161105183612573565b6001600160401b0390811682526000602080840182905260408085018390526060808601849052608095860184905289845260048352928190208651815493880151888401519187166001600160e01b031990951694909417600160401b6001600160a01b039095168502176001600160e01b0316600160e01b60e092831c0217825593870151958701519585169590911c90910293909317600184015560a08401516002909301805460c0860151929095015161ffff1990951693151561ff00191693909317610100911515919091021762ff0000191662010000931515939093029290921790558a517f7d84a6263ae0d98d3329bd7b46bb4e8d6f98cd35a7adb45c274c8b7fd5ebd5e091859188918e918e918111156111755761117561491a565b6040519080825280602002602001820160405280156111a857816020015b60608152602001906001900390816111935790505b508d88888f6040516111c299989796959493929190615514565b60405180910390a150909998505050505050505050565b60006111fb8484846111f660408051602081019091526000815290565b6125df565b90505b9392505050565b630a85bd0160e11b5b949350505050565b600e546001600160a01b0316331461124157604051636184ba1160e01b815260040160405180910390fd5b61124a81612b36565b5050565b60008481526004602052604081206060916112688761145f565b9050600181600881111561127e5761127e614d4a565b148061129b5750600081600881111561129957611299614d4a565b145b6112e75760405162461bcd60e51b815260206004820152601f60248201527f476f7665726e6f723a206e6f7420616374697665206f722070656e64696e67006044820152606401610d04565b81546001600160401b0316336000611301828a85896125df565b90506000633b9aca006003547f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316638e539e8c876040518263ffffffff1660e01b815260040161135b91815260200190565b602060405180830381865afa158015611378573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061139c91906155eb565b6113a69190615604565b6113b09190615631565b905080821161140d5760405162461bcd60e51b815260206004820152602360248201527f476f7665726e6f723a20696e73756666696369656e7420766f74696e6720706f6044820152623bb2b960e91b6064820152608401610d04565b89836001600160a01b03168c7fdb700dee4c69422ecdfd4ad68ffe25aa39c6ddffef4657f727571e095b642cc58c8c60405161144a929190615645565b60405180910390a45050505050505050505050565b6000818152600460205260408120600281015460ff16156114835750600792915050565b6002810154610100900460ff161561149e5750600292915050565b600281015462010000900460ff16156114ba5750600892915050565b6000838152600460205260408120546001600160401b0316908190036115225760405162461bcd60e51b815260206004820152601d60248201527f476f7665726e6f723a20756e6b6e6f776e2070726f706f73616c2069640000006044820152606401610d04565b600061152c611bc3565b65ffffffffffff16905080821061154857506000949350505050565b600061155386611f6f565b90508181106115685750600195945050505050565b61157186612c61565b8015611590575060008681526007602052604090208054600190910154115b156115a15750600495945050505050565b50600395945050505050565b600033816115be8787878786611da5565b905060006115cb8261145f565b60088111156115dc576115dc614d4a565b146116295760405162461bcd60e51b815260206004820152601c60248201527f476f7665726e6f723a20746f6f206c61746520746f2063616e63656c000000006044820152606401610d04565b6000818152600460205260409020546001600160a01b03838116600160401b90920416146116a45760405162461bcd60e51b815260206004820152602260248201527f476f7665726e6f723a206f6e6c792070726f706f7365722063616e2063616e63604482015261195b60f21b6064820152608401610d04565b6116b18787878786612cad565b979650505050505050565b633b9aca008111156116e157604051634fa0e5e360e01b815260040160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316630c340a246040518163ffffffff1660e01b8152600401602060405180830381865afa15801561173f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117639190615674565b6001600160a01b0316336001600160a01b03161461179457604051633b8d9d7560e21b815260040160405180910390fd5b60038190556040518181527f5abd4079db52a376d0f48814132d5f1f10624699a317971509682d7ec6db0a4f9060200160405180910390a150565b60607f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634bf5d7e96040518163ffffffff1660e01b8152600401600060405180830381865afa92505050801561185057506040513d6000823e601f3d908101601f1916820160405261184d9190810190615691565b60015b61188c575060408051808201909152601d81527f6d6f64653d626c6f636b6e756d6265722666726f6d3d64656661756c74000000602082015290565b919050565b600c546001600160a01b031633146118bc57604051633a7cfa5d60e21b815260040160405180910390fd5b6101f48111156118df576040516314263b7360e11b815260040160405180910390fd5b601081905560405181907f586fc658003980a786f5709cd2ad386034e0424082c948c863d3116f8f66566990600090a250565b600954600090808203611929575050600854919050565b6000600961193860018461541f565b81548110611948576119486156fe565b60009182526020918290206040805180820190915291015463ffffffff8116808352600160201b9091046001600160e01b0316928201929092529150841061199e57602001516001600160e01b03169392505050565b6119b26119aa85612deb565b600990612e50565b6001600160e01b0316949350505050565b6000806119d38787878787611da5565b905060006119e08261145f565b905060048160088111156119f6576119f6614d4a565b14611a4d5760405162461bcd60e51b815260206004820152602160248201527f476f7665726e6f723a2070726f706f73616c206e6f74207375636365737366756044820152601b60fa1b6064820152608401610d04565b60008281526004602052604090819020600201805460ff19166001179055517f712ae1383f79ac853f8d882153778e0260ef8f03b504e2866e0593e04d2b291f90611a9b9084815260200190565b60405180910390a1611ab08289898989612f03565b611abd8289898989612f8d565b611aca8289898989612f03565b509695505050505050565b600e546001600160a01b03163314611b0057604051636184ba1160e01b815260040160405180910390fd5b600e80546001600160a01b03191690556040517f62acb1bd035e6b0070db32c18d981d7ef3d5921d59efd75de499c7632df8dd7990600090a1565b600060608082808083611b6e7f00000000000000000000000000000000000000000000000000000000000000008361308f565b611b997f0000000000000000000000000000000000000000000000000000000000000000600161308f565b60408051600080825260208201909252600f60f81b9b939a50919850469750309650945092509050565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166391ddadf46040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015611c3f575060408051601f3d908101601f19168201909252611c3c91810190615714565b60015b61188c57611c4c4361313b565b905090565b6040516331a9108f60e11b81526004810183905260009081906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636352211e90602401602060405180830381865afa158015611cbb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cdf9190615674565b905061120e818585604051806020016040528060008152506125df565b600f546001600160a01b03163314611d275760405163f37fda0760e01b815260040160405180910390fd5b600f8054600e80546001600160a01b0383166001600160a01b031991821681179092559091169091556040517f03ae59c1e4263c9049c7aab44b77283fa0484d5d0f714e102cd9857f8fc5274d90600090a2565b60095460009015611d9e57611d9060096131a2565b6001600160e01b0316905090565b5060085490565b60008585858585604051602001611dc095949392919061573c565b60408051601f1981840301815291905280516020909101209695505050505050565b60006127106010547f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316638e539e8c600142611e26919061541f565b6040518263ffffffff1660e01b8152600401611e4491815260200190565b602060405180830381865afa158015611e61573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e8591906155eb565b611e8f9190615604565b611c4c9190615631565b600d546001600160a01b03163314611ec45760405163071110c760e51b815260040160405180910390fd5b600d8054600c80546001600160a01b0383166001600160a01b031991821681179092559091169091556040517fe25466fe8250322bee73bc230e10775fe0da57be723ebdabfdc8b62b4ba0d10c90600090a2565b600080339050611f638882898989898080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508b92506131db915050565b98975050505050505050565b6000610cdf826131eb565b333014611f995760405162461bcd60e51b8152600401610d0490615388565b611fb0565b80611fa96005612386565b03611f9e57505b600080856001600160a01b0316858585604051611fce9291906153bf565b60006040518083038185875af1925050503d806000811461200b576040519150601f19603f3d011682016040523d82523d6000602084013e612010565b606091505b5091509150612038828260405180606001604052806028815260200161594b60289139613227565b50505050505050565b6000803390506116b18782888888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061324092505050565b6000612098858585856125df565b95945050505050565b3330146120c05760405162461bcd60e51b8152600401610d0490615388565b6120d7565b806120d06005612386565b036120c557505b610d2d8161326e565b600e546001600160a01b0316331461210b57604051636184ba1160e01b815260040160405180910390fd5b6001600160a01b0381166121325760405163d92e233d60e01b815260040160405180910390fd5b600f80546001600160a01b0319166001600160a01b0392909216919091179055565b6000803390506120988582868660405180602001604052806000815250613240565b6000606461218383611912565b604051632394e7a360e21b8152600481018590527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690638e539e8c90602401602060405180830381865afa1580156121e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061220c91906155eb565b6122169190615604565b610cdf9190615631565b6000806122c46122bc7fb3b3f3b703cd84ce352197dcff232b1b5d3cfb2025ce47cf04742d0651f1af888d8c8c8c60405161225c9291906153bf565b60405180910390208b805190602001206040516020016122a1959493929190948552602085019390935260ff9190911660408401526060830152608082015260a00190565b604051602081830303815290604052805190602001206132d8565b868686613305565b905061230b8b828c8c8c8c8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508e92506131db915050565b9b9a5050505050505050505050565b604080517f150214d74d59b7d1e90c73fc22ef3d991dd0a76b046543d4d80ab92d2a50328f602082015290810187905260ff851660608201526000908190612368906122bc906080016122a1565b9050611f638882898960405180602001604052806000815250613240565b60006123a18254600f81810b600160801b909204900b131590565b156123bf57604051631ed9509560e11b815260040160405180910390fd5b508054600f0b6000818152600180840160205260408220805492905583546fffffffffffffffffffffffffffffffff191692016001600160801b03169190911790915590565b60648111156124885760405162461bcd60e51b815260206004820152604360248201527f476f7665726e6f72566f74657351756f72756d4672616374696f6e3a2071756f60448201527f72756d4e756d657261746f72206f7665722071756f72756d44656e6f6d696e616064820152623a37b960e91b608482015260a401610d04565b6000612492611d7b565b905080158015906124a35750600954155b15612507576040805180820190915260008152600990602081016124c68461332d565b6001600160e01b039081169091528254600181018455600093845260209384902083519490930151909116600160201b0263ffffffff909316929092179101555b612534612522612515611bc3565b65ffffffffffff16612deb565b61252b8461332d565b60099190613396565b505060408051828152602081018490527f0553476bf02ef2726e8ce5ced78d63e26e602e4a2257b1f559418e24b4633997910160405180910390a15050565b60006001600160401b038211156125db5760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203660448201526534206269747360d01b6064820152608401610d04565b5090565b60405161f8e560ef1b81526004810184905260009081906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690637c72800090602401602060405180830381865afa158015612647573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061266b9190615798565b9050600281600281111561268157612681614d4a565b036126d85760405162461bcd60e51b815260206004820152602160248201527f476f7665726e6f723a206d616e61676564206e66742063616e6e6f7420766f746044820152606560f81b6064820152608401610d04565b60008160028111156126ec576126ec614d4a565b0361279157604051634d6fb77560e01b81526001600160a01b03878116600483015260248201879052604482018690527f00000000000000000000000000000000000000000000000000000000000000001690634d6fb77590606401602060405180830381865afa158015612765573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061278991906155eb565b91505061120e565b6040516319a0a9d560e01b8152600481018690526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906319a0a9d590602401602060405180830381865afa1580156127f9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061281d91906155eb565b905060006128556001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001683886133b1565b604051631e09967560e31b81526004810184905265ffffffffffff821660248201529091506000906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063f04cb3a890604401608060405180830381865afa1580156128ce573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128f291906157b9565b60600151905080600003612a9157604051634d6fb77560e01b81526001600160a01b038a81166004830152602482018a9052604482018990526000917f000000000000000000000000000000000000000000000000000000000000000090911690634d6fb77590606401602060405180830381865afa158015612979573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061299d91906155eb565b60405163145615f560e21b8152600481018b9052602481018690529091506000906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063515857d490604401602060405180830381865afa158015612a0f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a3391906155eb565b90506000612a6c6001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016878d8d6136a2565b905082612a798284615473565b612a839190615473565b97505050505050505061120e565b604051634d6fb77560e01b81526001600160a01b038a81166004830152602482018a9052604482018990527f00000000000000000000000000000000000000000000000000000000000000001690634d6fb77590606401602060405180830381865afa158015612b05573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b2991906155eb565b9998505050505050505050565b600080612b428361145f565b90506008816008811115612b5857612b58614d4a565b14158015612b7857506002816008811115612b7557612b75614d4a565b14155b8015612b9657506005816008811115612b9357612b93614d4a565b14155b8015612bb457506007816008811115612bb157612bb1614d4a565b14155b612c005760405162461bcd60e51b815260206004820152601d60248201527f476f7665726e6f723a2070726f706f73616c206e6f74206163746976650000006044820152606401610d04565b60008381526004602052604090819020600201805462ff0000191662010000179055517fde0cea2a3a0097cc3d981d40c375407760e85bc9c5e69aea449ac3885f8615c690612c529085815260200190565b60405180910390a15090919050565b600081815260076020526040812060028101546001820154612c839190615473565b600084815260046020526040902054612ca4906001600160401b0316612176565b11159392505050565b600080612cbd8787878787611da5565b90506000612cca8261145f565b90506008816008811115612ce057612ce0614d4a565b14158015612d0057506002816008811115612cfd57612cfd614d4a565b14155b8015612d1e57506005816008811115612d1b57612d1b614d4a565b14155b8015612d3c57506007816008811115612d3957612d39614d4a565b14155b612d885760405162461bcd60e51b815260206004820152601d60248201527f476f7665726e6f723a2070726f706f73616c206e6f74206163746976650000006044820152606401610d04565b60008281526004602052604090819020600201805461ff001916610100179055517f789cf55be980739dad1d0699b93b58e806b51c9d96619bfa8fe0a28abaa7b30c90612dd89084815260200190565b60405180910390a1509695505050505050565b600063ffffffff8211156125db5760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203360448201526532206269747360d01b6064820152608401610d04565b815460009081816005811115612ead576000612e6b84613c89565b612e75908561541f565b60008881526020902090915081015463ffffffff9081169087161015612e9d57809150612eab565b612ea8816001615473565b92505b505b6000612ebb87878585613d71565b90508015612ef657612ee087612ed260018461541f565b600091825260209091200190565b54600160201b90046001600160e01b03166116b1565b6000979650505050505050565b612f86565b8181101561203857306001600160a01b0316868281518110612f2c57612f2c6156fe565b60200260200101516001600160a01b031603612f7657612f76848281518110612f5757612f576156fe565b6020026020010151805190602001206005613dcf90919063ffffffff16565b612f7f81615824565b9050612f08565b5050505050565b600060405180606001604052806027815260200161597360279139855190915060005b8181101561308557600080888381518110612fcd57612fcd6156fe565b60200260200101516001600160a01b0316888481518110612ff057612ff06156fe565b602002602001015188858151811061300a5761300a6156fe565b602002602001015160405161301f919061583d565b60006040518083038185875af1925050503d806000811461305c576040519150601f19603f3d011682016040523d82523d6000602084013e613061565b606091505b5091509150613071828287613227565b5050508061307e90615824565b9050612fb0565b5050505050505050565b606060ff8316156130aa576130a383613e0b565b9050610cdf565b8180546130b6906153cf565b80601f01602080910402602001604051908101604052809291908181526020018280546130e2906153cf565b801561312f5780601f106131045761010080835404028352916020019161312f565b820191906000526020600020905b81548152906001019060200180831161311257829003601f168201915b50505050509050610cdf565b600065ffffffffffff8211156125db5760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203460448201526538206269747360d01b6064820152608401610d04565b805460009080156131d2576131bc83612ed260018461541f565b54600160201b90046001600160e01b03166111fe565b60009392505050565b60006116b1878787878787613e40565b600081815260046020526040812060010154610cdf906001600160401b03166000848152600b60205260409020546001600160401b0316613f42565b606083156132365750816111fe565b6111fe8383613f58565b6000613264868686868661325f60408051602081019091526000815290565b6131db565b9695505050505050565b600a54604080516001600160401b03928316815291831660208301527f7ca4ac117ed3cdce75c1161d8207c440389b1a15d69d096831664657c07dafc2910160405180910390a1600a805467ffffffffffffffff19166001600160401b0392909216919091179055565b6000610cdf6132e5613f82565b8360405161190160f01b8152600281019290925260228201526042902090565b6000806000613316878787876140ad565b9150915061332381614171565b5095945050505050565b60006001600160e01b038211156125db5760405162461bcd60e51b815260206004820152602760248201527f53616665436173743a2076616c756520646f65736e27742066697420696e20326044820152663234206269747360c81b6064820152608401610d04565b6000806133a48585856142bb565b915091505b935093915050565b604051635058979360e01b81526004810183905260009081906001600160a01b03861690635058979390602401602060405180830381865afa1580156133fb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061341f9190615714565b90508065ffffffffffff1660000361343b5760009150506111fe565b826001600160a01b03861663f04cb3a886613457600186615859565b6040516001600160e01b031960e085901b168152600481019290925265ffffffffffff166024820152604401608060405180830381865afa1580156134a0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134c491906157b9565b51116134dd576134d5600182615859565b9150506111fe565b604051631e09967560e31b8152600481018590526000602482015283906001600160a01b0387169063f04cb3a890604401608060405180830381865afa15801561352b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061354f91906157b9565b5111156135605760009150506111fe565b60008061356e600184615859565b90506135a460405180608001604052806000815260200160006001600160a01b0316815260200160008152602001600081525090565b8265ffffffffffff168265ffffffffffff16111561369657600060026135ca8585615859565b6135d4919061587f565b6135de9084615859565b604051631e09967560e31b8152600481018a905265ffffffffffff821660248201529091506001600160a01b038a169063f04cb3a890604401608060405180830381865afa158015613634573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061365891906157b9565b9150868260000151036136715794506111fe9350505050565b815187111561368257809350613690565b61368d600182615859565b92505b506135a4565b50909695505050505050565b60405163539c6d4160e11b81526004810184905260009081906001600160a01b0387169063a738da8290602401602060405180830381865afa1580156136ec573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137109190615674565b604051635058979360e01b8152600481018690529091506001600160a01b03821690635058979390602401602060405180830381865afa158015613758573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061377c91906155eb565b60000361378d57600091505061120e565b6000866001600160a01b031663fc0c546a6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156137cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137f19190615674565b60405163f25e55a560e01b81526001600160a01b03808316600483015260248201889052919250600091600191839161387d919087169063f25e55a590604401602060405180830381865afa15801561384e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061387291906155eb565b62093a808106900390565b6040516328a3532760e21b8152600481018a9052602481018290529091506000906001600160a01b0387169063a28d4c9c90604401602060405180830381865afa1580156138cf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138f391906155eb565b604051631277308160e21b8152600481018b90526024810182905290915060009081906001600160a01b038916906349dcc204906044016040805180830381865afa158015613946573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061396a91906158a4565b90925090506139808462093a8084068403613f42565b9350600062093a8061399886828e068e03830161541f565b6139a29190615631565b905060008115613c765760005b82811015613c74576001600160a01b038b1663a28d4c9c8f60016139d662093a808c615473565b6139e0919061541f565b6040516001600160e01b031960e085901b16815260048101929092526024820152604401602060405180830381865afa158015613a21573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613a4591906155eb565b95508a6001600160a01b03166349dcc2048f886040518363ffffffff1660e01b8152600401613a7e929190918252602082015260400190565b6040805180830381865afa158015613a9a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613abe91906158a4565b90955093506001600160a01b038b1663f7412baf816376f4be366001613ae762093a808d615473565b613af1919061541f565b6040518263ffffffff1660e01b8152600401613b0f91815260200190565b602060405180830381865afa158015613b2c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b5091906155eb565b6040518263ffffffff1660e01b8152600401613b6e91815260200190565b6040805180830381865afa158015613b8a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613bae91906158a4565b9250613bbd9050826001613f42565b6040516392777b2960e01b81526001600160a01b038c81166004830152602482018a905291995089918d16906392777b2990604401602060405180830381865afa158015613c0f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613c3391906155eb565b613c3d9086615604565b613c479190615631565b613c51908a615473565b9850613c6062093a8088615473565b965080613c6c81615824565b9150506139af565b505b50959d9c50505050505050505050505050565b600081600003613c9b57506000919050565b60006001613ca88461445a565b901c6001901b90506001818481613cc157613cc161561b565b048201901c90506001818481613cd957613cd961561b565b048201901c90506001818481613cf157613cf161561b565b048201901c90506001818481613d0957613d0961561b565b048201901c90506001818481613d2157613d2161561b565b048201901c90506001818481613d3957613d3961561b565b048201901c90506001818481613d5157613d5161561b565b048201901c90506111fe81828581613d6b57613d6b61561b565b046144ee565b60005b81831015613dc7576000613d8884846144fd565b60008781526020902090915063ffffffff86169082015463ffffffff161115613db357809250613dc1565b613dbe816001615473565b93505b50613d74565b509392505050565b8154600160801b90819004600f0b6000818152600180860160205260409091209390935583546001600160801b03908116939091011602179055565b60408051602080825281830190925260609160ff84169160009180820181803683375050509182525060208101929092525090565b600080613e51888888888888614518565b6000898152600b60205260409020549091506001600160401b0316158015613e7d5750613e7d88612c61565b156116b1576000613e96600a546001600160401b031690565b613e9e611bc3565b65ffffffffffff16613eb091906158c8565b9050613ebb89611f6f565b816001600160401b03161115613f0a576040516001600160401b038216815289907f541f725fb9f7c98a30cc9c0ff32fbb14358cd7159c847a3aa20a2bdc442ba5119060200160405180910390a25b6000898152600b60205260409020805467ffffffffffffffff19166001600160401b0392909216919091179055979650505050505050565b6000818311613f5157816111fe565b5090919050565b815115613f685781518083602001fd5b8060405162461bcd60e51b8152600401610d0491906148d5565b6000306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016148015613fdb57507f000000000000000000000000000000000000000000000000000000000000000046145b1561400557507f000000000000000000000000000000000000000000000000000000000000000090565b611c4c604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60208201527f0000000000000000000000000000000000000000000000000000000000000000918101919091527f000000000000000000000000000000000000000000000000000000000000000060608201524660808201523060a082015260009060c00160405160208183030381529060405280519060200120905090565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08311156140e45750600090506003614168565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015614138573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811661416157600060019250925050614168565b9150600090505b94509492505050565b600081600481111561418557614185614d4a565b0361418d5750565b60018160048111156141a1576141a1614d4a565b036141ee5760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e617475726500000000000000006044820152606401610d04565b600281600481111561420257614202614d4a565b0361424f5760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152606401610d04565b600381600481111561426357614263614d4a565b03610d2d5760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b6064820152608401610d04565b8254600090819080156144015760006142d987612ed260018561541f565b60408051808201909152905463ffffffff808216808452600160201b9092046001600160e01b03166020840152919250908716101561435a5760405162461bcd60e51b815260206004820152601b60248201527f436865636b706f696e743a2064656372656173696e67206b65797300000000006044820152606401610d04565b805163ffffffff8088169116036143a2578461437b88612ed260018661541f565b80546001600160e01b0392909216600160201b0263ffffffff9092169190911790556143f1565b6040805180820190915263ffffffff80881682526001600160e01b0380881660208085019182528b54600181018d5560008d81529190912094519151909216600160201b029216919091179101555b6020015192508391506133a99050565b50506040805180820190915263ffffffff80851682526001600160e01b0380851660208085019182528854600181018a5560008a815291822095519251909316600160201b0291909316179201919091559050816133a9565b600080608083901c1561446f57608092831c92015b604083901c1561448157604092831c92015b602083901c1561449357602092831c92015b601083901c156144a557601092831c92015b600883901c156144b757600892831c92015b600483901c156144c957600492831c92015b600283901c156144db57600292831c92015b600183901c15610cdf5760010192915050565b6000818310613f5157816111fe565b600061450c6002848418615631565b6111fe90848416615473565b600086815260046020526040812060016145318961145f565b600881111561454257614542614d4a565b1461459b5760405162461bcd60e51b815260206004820152602360248201527f476f7665726e6f723a20766f7465206e6f742063757272656e746c792061637460448201526269766560e81b6064820152608401610d04565b80546000906145b790899089906001600160401b0316876125df565b90506145c68988888488614672565b835160000361461c5786886001600160a01b03167f02ecdb7f59712b7ae7cb6851cce1c64e98f94e5b51ec63809112c054622b25548b89858a60405161460f94939291906158e8565b60405180910390a3611f63565b86886001600160a01b03167f7dcdc52e34b09364e599a32b0e3ccb5b730a7b952ddbdf4f237ea785da228ce78b89858a8a60405161465e959493929190615910565b60405180910390a398975050505050505050565b6000858152600760209081526040808320878452600381019092529091205460ff16156146f15760405162461bcd60e51b815260206004820152602760248201527f476f7665726e6f72566f74696e6753696d706c653a20766f746520616c726561604482015266191e4818d85cdd60ca1b6064820152608401610d04565b600083116147525760405162461bcd60e51b815260206004820152602860248201527f476f7665726e6f72566f74696e6753696d706c653a207a65726f20766f74696e60448201526719c81dd95a59da1d60c21b6064820152608401610d04565b60008581526003820160205260409020805460ff1916600117905560ff841661479457828160000160008282546147899190615473565b9091555061483a9050565b60001960ff8516016147b457828160010160008282546147899190615473565b60011960ff8516016147d457828160020160008282546147899190615473565b60405162461bcd60e51b815260206004820152603560248201527f476f7665726e6f72566f74696e6753696d706c653a20696e76616c69642076616044820152746c756520666f7220656e756d20566f74655479706560581b6064820152608401610d04565b505050505050565b60006020828403121561485457600080fd5b81356001600160e01b0319811681146111fe57600080fd5b60006020828403121561487e57600080fd5b5035919050565b60005b838110156148a0578181015183820152602001614888565b50506000910152565b600081518084526148c1816020860160208601614885565b601f01601f19169290920160200192915050565b6020815260006111fe60208301846148a9565b6001600160a01b0381168114610d2d57600080fd5b60006020828403121561490f57600080fd5b81356111fe816148e8565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b03811182821017156149585761495861491a565b604052919050565b60006001600160401b038211156149795761497961491a565b5060051b60200190565b600082601f83011261499457600080fd5b813560206149a96149a483614960565b614930565b82815260059290921b840181019181810190868411156149c857600080fd5b8286015b84811015611aca5780356149df816148e8565b83529183019183016149cc565b600082601f8301126149fd57600080fd5b81356020614a0d6149a483614960565b82815260059290921b84018101918181019086841115614a2c57600080fd5b8286015b84811015611aca5780358352918301918301614a30565b60006001600160401b03821115614a6057614a6061491a565b50601f01601f191660200190565b6000614a7c6149a484614a47565b9050828152838383011115614a9057600080fd5b828260208301376000602084830101529392505050565b600082601f830112614ab857600080fd5b6111fe83833560208501614a6e565b600082601f830112614ad857600080fd5b81356020614ae86149a483614960565b82815260059290921b84018101918181019086841115614b0757600080fd5b8286015b84811015611aca5780356001600160401b03811115614b2a5760008081fd5b614b388986838b0101614aa7565b845250918301918301614b0b565b600080600080600060a08688031215614b5e57600080fd5b8535945060208601356001600160401b0380821115614b7c57600080fd5b614b8889838a01614983565b95506040880135915080821115614b9e57600080fd5b614baa89838a016149ec565b94506060880135915080821115614bc057600080fd5b614bcc89838a01614ac7565b93506080880135915080821115614be257600080fd5b508601601f81018813614bf457600080fd5b614c0388823560208401614a6e565b9150509295509295909350565b600080600060608486031215614c2557600080fd5b8335614c30816148e8565b95602085013595506040909401359392505050565b60008060008060808587031215614c5b57600080fd5b8435614c66816148e8565b93506020850135614c76816148e8565b92506040850135915060608501356001600160401b03811115614c9857600080fd5b614ca487828801614aa7565b91505092959194509250565b60008083601f840112614cc257600080fd5b5081356001600160401b03811115614cd957600080fd5b602083019150836020828501011115614cf157600080fd5b9250929050565b60008060008060608587031215614d0e57600080fd5b843593506020850135925060408501356001600160401b03811115614d3257600080fd5b614d3e87828801614cb0565b95989497509550505050565b634e487b7160e01b600052602160045260246000fd5b6020810160098310614d8257634e487b7160e01b600052602160045260246000fd5b91905290565b60008060008060808587031215614d9e57600080fd5b84356001600160401b0380821115614db557600080fd5b614dc188838901614983565b95506020870135915080821115614dd757600080fd5b614de3888389016149ec565b94506040870135915080821115614df957600080fd5b50614e0687828801614ac7565b949793965093946060013593505050565b600080600080600060a08688031215614e2f57600080fd5b85356001600160401b0380821115614e4657600080fd5b614e5289838a01614983565b96506020880135915080821115614e6857600080fd5b614e7489838a016149ec565b95506040880135915080821115614e8a57600080fd5b50614e9788828901614ac7565b935050606086013591506080860135614eaf816148e8565b809150509295509295909350565b60008060408385031215614ed057600080fd5b50508035926020909101359150565b600081518084526020808501945080840160005b83811015614f0f57815187529582019590820190600101614ef3565b509495945050505050565b60ff60f81b8816815260e060208201526000614f3960e08301896148a9565b8281036040840152614f4b81896148a9565b606084018890526001600160a01b038716608085015260a0840186905283810360c08501529050614f7c8185614edf565b9a9950505050505050505050565b600080600080600060a08688031215614fa257600080fd5b8535614fad816148e8565b94506020860135614fbd816148e8565b935060408601356001600160401b0380821115614fd957600080fd5b614fe589838a016149ec565b94506060880135915080821115614ffb57600080fd5b61500789838a016149ec565b9350608088013591508082111561501d57600080fd5b50614c0388828901614aa7565b803560ff8116811461188c57600080fd5b60008060008060008060a0878903121561505457600080fd5b863595506020870135945061506b6040880161502a565b935060608701356001600160401b038082111561508757600080fd5b6150938a838b01614cb0565b909550935060808901359150808211156150ac57600080fd5b506150b989828a01614aa7565b9150509295509295509295565b600080600080606085870312156150dc57600080fd5b84356150e7816148e8565b93506020850135925060408501356001600160401b03811115614d3257600080fd5b60008060008060006080868803121561512157600080fd5b85359450602086013593506151386040870161502a565b925060608601356001600160401b0381111561515357600080fd5b61515f88828901614cb0565b969995985093965092949392505050565b6000806000806080858703121561518657600080fd5b8435615191816148e8565b9350602085013592506040850135915060608501356001600160401b03811115614c9857600080fd5b6000602082840312156151cc57600080fd5b81356001600160401b03811681146111fe57600080fd5b6000806000606084860312156151f857600080fd5b833592506020840135915061520f6040850161502a565b90509250925092565b600080600080600060a0868803121561523057600080fd5b853561523b816148e8565b9450602086013561524b816148e8565b9350604086013592506060860135915060808601356001600160401b0381111561527457600080fd5b614c0388828901614aa7565b60008060008060008060008060006101008a8c03121561529f57600080fd5b8935985060208a013597506152b660408b0161502a565b965060608a01356001600160401b03808211156152d257600080fd5b6152de8d838e01614cb0565b909850965060808c01359150808211156152f757600080fd5b506153048c828d01614aa7565b94505061531360a08b0161502a565b925060c08a0135915060e08a013590509295985092959850929598565b60008060008060008060c0878903121561534957600080fd5b86359550602087013594506153606040880161502a565b935061536e6060880161502a565b92506080870135915060a087013590509295509295509295565b60208082526018908201527f476f7665726e6f723a206f6e6c79476f7665726e616e63650000000000000000604082015260600190565b8183823760009101908152919050565b600181811c908216806153e357607f821691505b60208210810361540357634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b81810381811115610cdf57610cdf615409565b60208082526021908201527f476f7665726e6f723a20696e76616c69642070726f706f73616c206c656e67746040820152600d60fb1b606082015260800190565b80820180821115610cdf57610cdf615409565b600081518084526020808501945080840160005b83811015614f0f5781516001600160a01b03168752958201959082019060010161549a565b600081518084526020808501808196508360051b8101915082860160005b858110156155075782840389526154f58483516148a9565b988501989350908401906001016154dd565b5091979650505050505050565b60006101208b8352602060018060a01b038c168185015281604085015261553d8285018c615486565b91508382036060850152615551828b614edf565b915083820360808501528189518084528284019150828160051b850101838c0160005b838110156155a257601f198784030185526155908383516148a9565b94860194925090850190600101615574565b505086810360a08801526155b6818c6154bf565b9450505050508560c08401528460e08401528281036101008401526155db81856148a9565b9c9b505050505050505050505050565b6000602082840312156155fd57600080fd5b5051919050565b8082028115828204841417610cdf57610cdf615409565b634e487b7160e01b600052601260045260246000fd5b6000826156405761564061561b565b500490565b60208152816020820152818360408301376000818301604090810191909152601f909201601f19160101919050565b60006020828403121561568657600080fd5b81516111fe816148e8565b6000602082840312156156a357600080fd5b81516001600160401b038111156156b957600080fd5b8201601f810184136156ca57600080fd5b80516156d86149a482614a47565b8181528560208385010111156156ed57600080fd5b612098826020830160208601614885565b634e487b7160e01b600052603260045260246000fd5b60006020828403121561572657600080fd5b815165ffffffffffff811681146111fe57600080fd5b60a08152600061574f60a0830188615486565b82810360208401526157618188614edf565b9050828103604084015261577581876154bf565b606084019590955250506001600160a01b03919091166080909101529392505050565b6000602082840312156157aa57600080fd5b8151600381106111fe57600080fd5b6000608082840312156157cb57600080fd5b604051608081018181106001600160401b03821117156157ed576157ed61491a565b604052825181526020830151615802816148e8565b6020820152604083810151908201526060928301519281019290925250919050565b60006001820161583657615836615409565b5060010190565b6000825161584f818460208701614885565b9190910192915050565b65ffffffffffff82811682821603908082111561587857615878615409565b5092915050565b600065ffffffffffff808416806158985761589861561b565b92169190910492915050565b600080604083850312156158b757600080fd5b505080516020909101519092909150565b6001600160401b0381811683821601908082111561587857615878615409565b84815260ff8416602082015282604082015260806060820152600061326460808301846148a9565b85815260ff8516602082015283604082015260a06060820152600061593860a08301856148a9565b8281036080840152611f6381856148a956fe476f7665726e6f723a2072656c617920726576657274656420776974686f7574206d657373616765476f7665726e6f723a2063616c6c20726576657274656420776974686f7574206d657373616765a2646970667358221220ff5084ec0901c5f666a0f87da4e27382ca272edf4b32c142c7bd9cf6228504e764736f6c63430008130033000000000000000000000000c4e6a85630ca1d9b754518f653cb43c3f768215b000000000000000000000000612c5dc0256b8da00bfd6b2b8f711e24b0509044
Deployed Bytecode
0x6080604052600436106103b15760003560e01c806367e2e078116101e7578063c01f9e371161010d578063dea112a6116100a0578063f8ce560a1161006f578063f8ce560a14610be4578063f945970a14610c04578063fa25f37714610c24578063fc0c546a14610c4457600080fd5b8063dea112a614610b30578063deaaa7cc14610b50578063e2fdcc1714610b84578063f23a6e6114610bb857600080fd5b8063d07f91e9116100dc578063d07f91e914610a8a578063d152a32e14610aaa578063d8bff44014610aca578063dd4e2ba514610aea57600080fd5b8063c01f9e3714610a17578063c28bc2fa14610a37578063c2e863e414610a4a578063cf781d4514610a6a57600080fd5b80639f8b339211610185578063b58131b011610154578063b58131b0146109a1578063b5cc143a146109b6578063bc197c81146109cb578063be443ad0146109f757600080fd5b80639f8b339214610936578063a67d06351461094c578063a7713a701461096c578063aedbfe331461098157600080fd5b806391ddadf4116101c157806391ddadf4146108c157806391f36633146108ed57806395b6d6bd1461090d57806397c3d3341461092257600080fd5b806367e2e0781461086357806384b0196e1461087957806385f2aef2146108a157600080fd5b80633932abb1116102d7578063544ffc9c1161026a57806360c4247f1161023957806360c4247f146107dc57806360e69a7b146107fc578063638663ac1461080f57806364390ff11461082457600080fd5b8063544ffc9c1461071d57806354fd4d5014610772578063592a84941461079c57806359d46ffc146107bc57600080fd5b806349758df2116102a657806349758df2146106bc5780634bf5d7e9146106dc578063501fa8bd146106f1578063525f9c3e1461070757600080fd5b80633932abb1146106255780633e4f49e61461063b578063452115d61461066857806346c96aac1461068857600080fd5b8063150b7a021161034f5780632d63f6931161031e5780632d63f693146105735780632fe3e261146105a957806332b8113e146105dd578063380a243a1461060557600080fd5b8063150b7a02146104b65780631d28dec7146104ef5780631f8507161461050f57806322b36ac61461055b57600080fd5b806306fdde031161038b57806306fdde0314610434578063095cf5c6146104565780630f8a88361461047657806311fd26f41461049657600080fd5b806301ffc9a7146103bf57806302a251a3146103f457806306f3f9e61461041457600080fd5b366103ba57005b005b600080fd5b3480156103cb57600080fd5b506103df6103da366004614842565b610c78565b60405190151581526020015b60405180910390f35b34801561040057600080fd5b50620697805b6040519081526020016103eb565b34801561042057600080fd5b506103b861042f36600461486c565b610ce5565b34801561044057600080fd5b50610449610d30565b6040516103eb91906148d5565b34801561046257600080fd5b506103b86104713660046148fd565b610dc2565b34801561048257600080fd5b50610406610491366004614b46565b610e36565b3480156104a257600080fd5b506104066104b1366004614c10565b6111d9565b3480156104c257600080fd5b506104d66104d1366004614c45565b611205565b6040516001600160e01b031990911681526020016103eb565b3480156104fb57600080fd5b506103b861050a36600461486c565b611216565b34801561051b57600080fd5b506105437f000000000000000000000000c4e6a85630ca1d9b754518f653cb43c3f768215b81565b6040516001600160a01b0390911681526020016103eb565b34801561056757600080fd5b50610406633b9aca0081565b34801561057f57600080fd5b5061040661058e36600461486c565b6000908152600460205260409020546001600160401b031690565b3480156105b557600080fd5b506104067fb3b3f3b703cd84ce352197dcff232b1b5d3cfb2025ce47cf04742d0651f1af8881565b3480156105e957600080fd5b50600a546040516001600160401b0390911681526020016103eb565b34801561061157600080fd5b506103b8610620366004614cf8565b61124e565b34801561063157600080fd5b506202a300610406565b34801561064757600080fd5b5061065b61065636600461486c565b61145f565b6040516103eb9190614d60565b34801561067457600080fd5b50610406610683366004614d88565b6115ad565b34801561069457600080fd5b506105437f000000000000000000000000612c5dc0256b8da00bfd6b2b8f711e24b050904481565b3480156106c857600080fd5b506103b86106d736600461486c565b6116bc565b3480156106e857600080fd5b506104496117cf565b3480156106fd57600080fd5b506104066101f481565b34801561071357600080fd5b5061040660035481565b34801561072957600080fd5b5061075761073836600461486c565b6000908152600760205260409020805460018201546002909201549092565b604080519384526020840192909252908201526060016103eb565b34801561077e57600080fd5b506040805180820190915260018152603160f81b6020820152610449565b3480156107a857600080fd5b506103b86107b736600461486c565b611891565b3480156107c857600080fd5b50600d54610543906001600160a01b031681565b3480156107e857600080fd5b506104066107f736600461486c565b611912565b61040661080a366004614e17565b6119c3565b34801561081b57600080fd5b506103b8611ad5565b34801561083057600080fd5b506103df61083f366004614ebd565b60009182526007602090815260408084209284526003909201905290205460ff1690565b34801561086f57600080fd5b5061040661271081565b34801561088557600080fd5b5061088e611b3b565b6040516103eb9796959493929190614f1a565b3480156108ad57600080fd5b50600c54610543906001600160a01b031681565b3480156108cd57600080fd5b506108d6611bc3565b60405165ffffffffffff90911681526020016103eb565b3480156108f957600080fd5b50610406610908366004614ebd565b611c51565b34801561091957600080fd5b506103b8611cfc565b34801561092e57600080fd5b506064610406565b34801561094257600080fd5b5061040660105481565b34801561095857600080fd5b50600f54610543906001600160a01b031681565b34801561097857600080fd5b50610406611d7b565b34801561098d57600080fd5b5061040661099c366004614e17565b611da5565b3480156109ad57600080fd5b50610406611de2565b3480156109c257600080fd5b506103b8611e99565b3480156109d757600080fd5b506104d66109e6366004614f8a565b63bc197c8160e01b95945050505050565b348015610a0357600080fd5b50610406610a1236600461503b565b611f18565b348015610a2357600080fd5b50610406610a3236600461486c565b611f6f565b6103b8610a453660046150c6565b611f7a565b348015610a5657600080fd5b50610406610a65366004615109565b612041565b348015610a7657600080fd5b50610406610a85366004615170565b61208a565b348015610a9657600080fd5b506103b8610aa53660046151ba565b6120a1565b348015610ab657600080fd5b506103b8610ac53660046148fd565b6120e0565b348015610ad657600080fd5b50600e54610543906001600160a01b031681565b348015610af657600080fd5b506040805180820190915260208082527f737570706f72743d627261766f2671756f72756d3d666f722c6162737461696e90820152610449565b348015610b3c57600080fd5b50610406610b4b3660046151e3565b612154565b348015610b5c57600080fd5b506104067f150214d74d59b7d1e90c73fc22ef3d991dd0a76b046543d4d80ab92d2a50328f81565b348015610b9057600080fd5b506105437f000000000000000000000000c4e6a85630ca1d9b754518f653cb43c3f768215b81565b348015610bc457600080fd5b506104d6610bd3366004615218565b63f23a6e6160e01b95945050505050565b348015610bf057600080fd5b50610406610bff36600461486c565b612176565b348015610c1057600080fd5b50610406610c1f366004615280565b612220565b348015610c3057600080fd5b50610406610c3f366004615330565b61231a565b348015610c5057600080fd5b506105437f000000000000000000000000c4e6a85630ca1d9b754518f653cb43c3f768215b81565b60006001600160e01b031982166367276c3760e01b1480610ca957506001600160e01b03198216631debdb9560e31b145b80610cc457506001600160e01b03198216630271189760e51b145b80610cdf57506301ffc9a760e01b6001600160e01b03198316145b92915050565b333014610d0d5760405162461bcd60e51b8152600401610d0490615388565b60405180910390fd5b610d24565b80610d1d6005612386565b03610d1257505b610d2d81612405565b50565b606060028054610d3f906153cf565b80601f0160208091040260200160405190810160405280929190818152602001828054610d6b906153cf565b8015610db85780601f10610d8d57610100808354040283529160200191610db8565b820191906000526020600020905b815481529060010190602001808311610d9b57829003601f168201915b5050505050905090565b6001600160a01b038116610de95760405163d92e233d60e01b815260040160405180910390fd5b600c546001600160a01b03163314610e1457604051633a7cfa5d60e21b815260040160405180910390fd5b600d80546001600160a01b0319166001600160a01b0392909216919091179055565b60003381610e42611bc3565b65ffffffffffff169050610e54611de2565b610e64838a6104b160018661541f565b1015610ecc5760405162461bcd60e51b815260206004820152603160248201527f476f7665726e6f723a2070726f706f73657220766f7465732062656c6f7720706044820152701c9bdc1bdcd85b081d1a1c995cda1bdb19607a1b6064820152608401610d04565b6000610ee2888888888051906020012087611da5565b90508651885114610f055760405162461bcd60e51b8152600401610d0490615432565b8551885114610f265760405162461bcd60e51b8152600401610d0490615432565b6000885111610f775760405162461bcd60e51b815260206004820152601860248201527f476f7665726e6f723a20656d7074792070726f706f73616c00000000000000006044820152606401610d04565b600081815260046020526040902054600160401b90046001600160a01b031615610fed5760405162461bcd60e51b815260206004820152602160248201527f476f7665726e6f723a2070726f706f73616c20616c72656164792065786973746044820152607360f81b6064820152608401610d04565b6000610ffc6202a30084615473565b9050600061100d6206978083615473565b905060405180610100016040528061102484612573565b6001600160401b031681526001600160a01b03871660208201526000604082015260600161105183612573565b6001600160401b0390811682526000602080840182905260408085018390526060808601849052608095860184905289845260048352928190208651815493880151888401519187166001600160e01b031990951694909417600160401b6001600160a01b039095168502176001600160e01b0316600160e01b60e092831c0217825593870151958701519585169590911c90910293909317600184015560a08401516002909301805460c0860151929095015161ffff1990951693151561ff00191693909317610100911515919091021762ff0000191662010000931515939093029290921790558a517f7d84a6263ae0d98d3329bd7b46bb4e8d6f98cd35a7adb45c274c8b7fd5ebd5e091859188918e918e918111156111755761117561491a565b6040519080825280602002602001820160405280156111a857816020015b60608152602001906001900390816111935790505b508d88888f6040516111c299989796959493929190615514565b60405180910390a150909998505050505050505050565b60006111fb8484846111f660408051602081019091526000815290565b6125df565b90505b9392505050565b630a85bd0160e11b5b949350505050565b600e546001600160a01b0316331461124157604051636184ba1160e01b815260040160405180910390fd5b61124a81612b36565b5050565b60008481526004602052604081206060916112688761145f565b9050600181600881111561127e5761127e614d4a565b148061129b5750600081600881111561129957611299614d4a565b145b6112e75760405162461bcd60e51b815260206004820152601f60248201527f476f7665726e6f723a206e6f7420616374697665206f722070656e64696e67006044820152606401610d04565b81546001600160401b0316336000611301828a85896125df565b90506000633b9aca006003547f000000000000000000000000c4e6a85630ca1d9b754518f653cb43c3f768215b6001600160a01b0316638e539e8c876040518263ffffffff1660e01b815260040161135b91815260200190565b602060405180830381865afa158015611378573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061139c91906155eb565b6113a69190615604565b6113b09190615631565b905080821161140d5760405162461bcd60e51b815260206004820152602360248201527f476f7665726e6f723a20696e73756666696369656e7420766f74696e6720706f6044820152623bb2b960e91b6064820152608401610d04565b89836001600160a01b03168c7fdb700dee4c69422ecdfd4ad68ffe25aa39c6ddffef4657f727571e095b642cc58c8c60405161144a929190615645565b60405180910390a45050505050505050505050565b6000818152600460205260408120600281015460ff16156114835750600792915050565b6002810154610100900460ff161561149e5750600292915050565b600281015462010000900460ff16156114ba5750600892915050565b6000838152600460205260408120546001600160401b0316908190036115225760405162461bcd60e51b815260206004820152601d60248201527f476f7665726e6f723a20756e6b6e6f776e2070726f706f73616c2069640000006044820152606401610d04565b600061152c611bc3565b65ffffffffffff16905080821061154857506000949350505050565b600061155386611f6f565b90508181106115685750600195945050505050565b61157186612c61565b8015611590575060008681526007602052604090208054600190910154115b156115a15750600495945050505050565b50600395945050505050565b600033816115be8787878786611da5565b905060006115cb8261145f565b60088111156115dc576115dc614d4a565b146116295760405162461bcd60e51b815260206004820152601c60248201527f476f7665726e6f723a20746f6f206c61746520746f2063616e63656c000000006044820152606401610d04565b6000818152600460205260409020546001600160a01b03838116600160401b90920416146116a45760405162461bcd60e51b815260206004820152602260248201527f476f7665726e6f723a206f6e6c792070726f706f7365722063616e2063616e63604482015261195b60f21b6064820152608401610d04565b6116b18787878786612cad565b979650505050505050565b633b9aca008111156116e157604051634fa0e5e360e01b815260040160405180910390fd5b7f000000000000000000000000612c5dc0256b8da00bfd6b2b8f711e24b05090446001600160a01b0316630c340a246040518163ffffffff1660e01b8152600401602060405180830381865afa15801561173f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117639190615674565b6001600160a01b0316336001600160a01b03161461179457604051633b8d9d7560e21b815260040160405180910390fd5b60038190556040518181527f5abd4079db52a376d0f48814132d5f1f10624699a317971509682d7ec6db0a4f9060200160405180910390a150565b60607f000000000000000000000000c4e6a85630ca1d9b754518f653cb43c3f768215b6001600160a01b0316634bf5d7e96040518163ffffffff1660e01b8152600401600060405180830381865afa92505050801561185057506040513d6000823e601f3d908101601f1916820160405261184d9190810190615691565b60015b61188c575060408051808201909152601d81527f6d6f64653d626c6f636b6e756d6265722666726f6d3d64656661756c74000000602082015290565b919050565b600c546001600160a01b031633146118bc57604051633a7cfa5d60e21b815260040160405180910390fd5b6101f48111156118df576040516314263b7360e11b815260040160405180910390fd5b601081905560405181907f586fc658003980a786f5709cd2ad386034e0424082c948c863d3116f8f66566990600090a250565b600954600090808203611929575050600854919050565b6000600961193860018461541f565b81548110611948576119486156fe565b60009182526020918290206040805180820190915291015463ffffffff8116808352600160201b9091046001600160e01b0316928201929092529150841061199e57602001516001600160e01b03169392505050565b6119b26119aa85612deb565b600990612e50565b6001600160e01b0316949350505050565b6000806119d38787878787611da5565b905060006119e08261145f565b905060048160088111156119f6576119f6614d4a565b14611a4d5760405162461bcd60e51b815260206004820152602160248201527f476f7665726e6f723a2070726f706f73616c206e6f74207375636365737366756044820152601b60fa1b6064820152608401610d04565b60008281526004602052604090819020600201805460ff19166001179055517f712ae1383f79ac853f8d882153778e0260ef8f03b504e2866e0593e04d2b291f90611a9b9084815260200190565b60405180910390a1611ab08289898989612f03565b611abd8289898989612f8d565b611aca8289898989612f03565b509695505050505050565b600e546001600160a01b03163314611b0057604051636184ba1160e01b815260040160405180910390fd5b600e80546001600160a01b03191690556040517f62acb1bd035e6b0070db32c18d981d7ef3d5921d59efd75de499c7632df8dd7990600090a1565b600060608082808083611b6e7f50726f746f636f6c20476f7665726e6f720000000000000000000000000000118361308f565b611b997f3100000000000000000000000000000000000000000000000000000000000001600161308f565b60408051600080825260208201909252600f60f81b9b939a50919850469750309650945092509050565b60007f000000000000000000000000c4e6a85630ca1d9b754518f653cb43c3f768215b6001600160a01b03166391ddadf46040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015611c3f575060408051601f3d908101601f19168201909252611c3c91810190615714565b60015b61188c57611c4c4361313b565b905090565b6040516331a9108f60e11b81526004810183905260009081906001600160a01b037f000000000000000000000000c4e6a85630ca1d9b754518f653cb43c3f768215b1690636352211e90602401602060405180830381865afa158015611cbb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cdf9190615674565b905061120e818585604051806020016040528060008152506125df565b600f546001600160a01b03163314611d275760405163f37fda0760e01b815260040160405180910390fd5b600f8054600e80546001600160a01b0383166001600160a01b031991821681179092559091169091556040517f03ae59c1e4263c9049c7aab44b77283fa0484d5d0f714e102cd9857f8fc5274d90600090a2565b60095460009015611d9e57611d9060096131a2565b6001600160e01b0316905090565b5060085490565b60008585858585604051602001611dc095949392919061573c565b60408051601f1981840301815291905280516020909101209695505050505050565b60006127106010547f000000000000000000000000c4e6a85630ca1d9b754518f653cb43c3f768215b6001600160a01b0316638e539e8c600142611e26919061541f565b6040518263ffffffff1660e01b8152600401611e4491815260200190565b602060405180830381865afa158015611e61573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e8591906155eb565b611e8f9190615604565b611c4c9190615631565b600d546001600160a01b03163314611ec45760405163071110c760e51b815260040160405180910390fd5b600d8054600c80546001600160a01b0383166001600160a01b031991821681179092559091169091556040517fe25466fe8250322bee73bc230e10775fe0da57be723ebdabfdc8b62b4ba0d10c90600090a2565b600080339050611f638882898989898080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508b92506131db915050565b98975050505050505050565b6000610cdf826131eb565b333014611f995760405162461bcd60e51b8152600401610d0490615388565b611fb0565b80611fa96005612386565b03611f9e57505b600080856001600160a01b0316858585604051611fce9291906153bf565b60006040518083038185875af1925050503d806000811461200b576040519150601f19603f3d011682016040523d82523d6000602084013e612010565b606091505b5091509150612038828260405180606001604052806028815260200161594b60289139613227565b50505050505050565b6000803390506116b18782888888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061324092505050565b6000612098858585856125df565b95945050505050565b3330146120c05760405162461bcd60e51b8152600401610d0490615388565b6120d7565b806120d06005612386565b036120c557505b610d2d8161326e565b600e546001600160a01b0316331461210b57604051636184ba1160e01b815260040160405180910390fd5b6001600160a01b0381166121325760405163d92e233d60e01b815260040160405180910390fd5b600f80546001600160a01b0319166001600160a01b0392909216919091179055565b6000803390506120988582868660405180602001604052806000815250613240565b6000606461218383611912565b604051632394e7a360e21b8152600481018590527f000000000000000000000000c4e6a85630ca1d9b754518f653cb43c3f768215b6001600160a01b031690638e539e8c90602401602060405180830381865afa1580156121e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061220c91906155eb565b6122169190615604565b610cdf9190615631565b6000806122c46122bc7fb3b3f3b703cd84ce352197dcff232b1b5d3cfb2025ce47cf04742d0651f1af888d8c8c8c60405161225c9291906153bf565b60405180910390208b805190602001206040516020016122a1959493929190948552602085019390935260ff9190911660408401526060830152608082015260a00190565b604051602081830303815290604052805190602001206132d8565b868686613305565b905061230b8b828c8c8c8c8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508e92506131db915050565b9b9a5050505050505050505050565b604080517f150214d74d59b7d1e90c73fc22ef3d991dd0a76b046543d4d80ab92d2a50328f602082015290810187905260ff851660608201526000908190612368906122bc906080016122a1565b9050611f638882898960405180602001604052806000815250613240565b60006123a18254600f81810b600160801b909204900b131590565b156123bf57604051631ed9509560e11b815260040160405180910390fd5b508054600f0b6000818152600180840160205260408220805492905583546fffffffffffffffffffffffffffffffff191692016001600160801b03169190911790915590565b60648111156124885760405162461bcd60e51b815260206004820152604360248201527f476f7665726e6f72566f74657351756f72756d4672616374696f6e3a2071756f60448201527f72756d4e756d657261746f72206f7665722071756f72756d44656e6f6d696e616064820152623a37b960e91b608482015260a401610d04565b6000612492611d7b565b905080158015906124a35750600954155b15612507576040805180820190915260008152600990602081016124c68461332d565b6001600160e01b039081169091528254600181018455600093845260209384902083519490930151909116600160201b0263ffffffff909316929092179101555b612534612522612515611bc3565b65ffffffffffff16612deb565b61252b8461332d565b60099190613396565b505060408051828152602081018490527f0553476bf02ef2726e8ce5ced78d63e26e602e4a2257b1f559418e24b4633997910160405180910390a15050565b60006001600160401b038211156125db5760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203660448201526534206269747360d01b6064820152608401610d04565b5090565b60405161f8e560ef1b81526004810184905260009081906001600160a01b037f000000000000000000000000c4e6a85630ca1d9b754518f653cb43c3f768215b1690637c72800090602401602060405180830381865afa158015612647573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061266b9190615798565b9050600281600281111561268157612681614d4a565b036126d85760405162461bcd60e51b815260206004820152602160248201527f476f7665726e6f723a206d616e61676564206e66742063616e6e6f7420766f746044820152606560f81b6064820152608401610d04565b60008160028111156126ec576126ec614d4a565b0361279157604051634d6fb77560e01b81526001600160a01b03878116600483015260248201879052604482018690527f000000000000000000000000c4e6a85630ca1d9b754518f653cb43c3f768215b1690634d6fb77590606401602060405180830381865afa158015612765573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061278991906155eb565b91505061120e565b6040516319a0a9d560e01b8152600481018690526000907f000000000000000000000000c4e6a85630ca1d9b754518f653cb43c3f768215b6001600160a01b0316906319a0a9d590602401602060405180830381865afa1580156127f9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061281d91906155eb565b905060006128556001600160a01b037f000000000000000000000000c4e6a85630ca1d9b754518f653cb43c3f768215b1683886133b1565b604051631e09967560e31b81526004810184905265ffffffffffff821660248201529091506000906001600160a01b037f000000000000000000000000c4e6a85630ca1d9b754518f653cb43c3f768215b169063f04cb3a890604401608060405180830381865afa1580156128ce573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128f291906157b9565b60600151905080600003612a9157604051634d6fb77560e01b81526001600160a01b038a81166004830152602482018a9052604482018990526000917f000000000000000000000000c4e6a85630ca1d9b754518f653cb43c3f768215b90911690634d6fb77590606401602060405180830381865afa158015612979573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061299d91906155eb565b60405163145615f560e21b8152600481018b9052602481018690529091506000906001600160a01b037f000000000000000000000000c4e6a85630ca1d9b754518f653cb43c3f768215b169063515857d490604401602060405180830381865afa158015612a0f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a3391906155eb565b90506000612a6c6001600160a01b037f000000000000000000000000c4e6a85630ca1d9b754518f653cb43c3f768215b16878d8d6136a2565b905082612a798284615473565b612a839190615473565b97505050505050505061120e565b604051634d6fb77560e01b81526001600160a01b038a81166004830152602482018a9052604482018990527f000000000000000000000000c4e6a85630ca1d9b754518f653cb43c3f768215b1690634d6fb77590606401602060405180830381865afa158015612b05573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b2991906155eb565b9998505050505050505050565b600080612b428361145f565b90506008816008811115612b5857612b58614d4a565b14158015612b7857506002816008811115612b7557612b75614d4a565b14155b8015612b9657506005816008811115612b9357612b93614d4a565b14155b8015612bb457506007816008811115612bb157612bb1614d4a565b14155b612c005760405162461bcd60e51b815260206004820152601d60248201527f476f7665726e6f723a2070726f706f73616c206e6f74206163746976650000006044820152606401610d04565b60008381526004602052604090819020600201805462ff0000191662010000179055517fde0cea2a3a0097cc3d981d40c375407760e85bc9c5e69aea449ac3885f8615c690612c529085815260200190565b60405180910390a15090919050565b600081815260076020526040812060028101546001820154612c839190615473565b600084815260046020526040902054612ca4906001600160401b0316612176565b11159392505050565b600080612cbd8787878787611da5565b90506000612cca8261145f565b90506008816008811115612ce057612ce0614d4a565b14158015612d0057506002816008811115612cfd57612cfd614d4a565b14155b8015612d1e57506005816008811115612d1b57612d1b614d4a565b14155b8015612d3c57506007816008811115612d3957612d39614d4a565b14155b612d885760405162461bcd60e51b815260206004820152601d60248201527f476f7665726e6f723a2070726f706f73616c206e6f74206163746976650000006044820152606401610d04565b60008281526004602052604090819020600201805461ff001916610100179055517f789cf55be980739dad1d0699b93b58e806b51c9d96619bfa8fe0a28abaa7b30c90612dd89084815260200190565b60405180910390a1509695505050505050565b600063ffffffff8211156125db5760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203360448201526532206269747360d01b6064820152608401610d04565b815460009081816005811115612ead576000612e6b84613c89565b612e75908561541f565b60008881526020902090915081015463ffffffff9081169087161015612e9d57809150612eab565b612ea8816001615473565b92505b505b6000612ebb87878585613d71565b90508015612ef657612ee087612ed260018461541f565b600091825260209091200190565b54600160201b90046001600160e01b03166116b1565b6000979650505050505050565b612f86565b8181101561203857306001600160a01b0316868281518110612f2c57612f2c6156fe565b60200260200101516001600160a01b031603612f7657612f76848281518110612f5757612f576156fe565b6020026020010151805190602001206005613dcf90919063ffffffff16565b612f7f81615824565b9050612f08565b5050505050565b600060405180606001604052806027815260200161597360279139855190915060005b8181101561308557600080888381518110612fcd57612fcd6156fe565b60200260200101516001600160a01b0316888481518110612ff057612ff06156fe565b602002602001015188858151811061300a5761300a6156fe565b602002602001015160405161301f919061583d565b60006040518083038185875af1925050503d806000811461305c576040519150601f19603f3d011682016040523d82523d6000602084013e613061565b606091505b5091509150613071828287613227565b5050508061307e90615824565b9050612fb0565b5050505050505050565b606060ff8316156130aa576130a383613e0b565b9050610cdf565b8180546130b6906153cf565b80601f01602080910402602001604051908101604052809291908181526020018280546130e2906153cf565b801561312f5780601f106131045761010080835404028352916020019161312f565b820191906000526020600020905b81548152906001019060200180831161311257829003601f168201915b50505050509050610cdf565b600065ffffffffffff8211156125db5760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203460448201526538206269747360d01b6064820152608401610d04565b805460009080156131d2576131bc83612ed260018461541f565b54600160201b90046001600160e01b03166111fe565b60009392505050565b60006116b1878787878787613e40565b600081815260046020526040812060010154610cdf906001600160401b03166000848152600b60205260409020546001600160401b0316613f42565b606083156132365750816111fe565b6111fe8383613f58565b6000613264868686868661325f60408051602081019091526000815290565b6131db565b9695505050505050565b600a54604080516001600160401b03928316815291831660208301527f7ca4ac117ed3cdce75c1161d8207c440389b1a15d69d096831664657c07dafc2910160405180910390a1600a805467ffffffffffffffff19166001600160401b0392909216919091179055565b6000610cdf6132e5613f82565b8360405161190160f01b8152600281019290925260228201526042902090565b6000806000613316878787876140ad565b9150915061332381614171565b5095945050505050565b60006001600160e01b038211156125db5760405162461bcd60e51b815260206004820152602760248201527f53616665436173743a2076616c756520646f65736e27742066697420696e20326044820152663234206269747360c81b6064820152608401610d04565b6000806133a48585856142bb565b915091505b935093915050565b604051635058979360e01b81526004810183905260009081906001600160a01b03861690635058979390602401602060405180830381865afa1580156133fb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061341f9190615714565b90508065ffffffffffff1660000361343b5760009150506111fe565b826001600160a01b03861663f04cb3a886613457600186615859565b6040516001600160e01b031960e085901b168152600481019290925265ffffffffffff166024820152604401608060405180830381865afa1580156134a0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134c491906157b9565b51116134dd576134d5600182615859565b9150506111fe565b604051631e09967560e31b8152600481018590526000602482015283906001600160a01b0387169063f04cb3a890604401608060405180830381865afa15801561352b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061354f91906157b9565b5111156135605760009150506111fe565b60008061356e600184615859565b90506135a460405180608001604052806000815260200160006001600160a01b0316815260200160008152602001600081525090565b8265ffffffffffff168265ffffffffffff16111561369657600060026135ca8585615859565b6135d4919061587f565b6135de9084615859565b604051631e09967560e31b8152600481018a905265ffffffffffff821660248201529091506001600160a01b038a169063f04cb3a890604401608060405180830381865afa158015613634573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061365891906157b9565b9150868260000151036136715794506111fe9350505050565b815187111561368257809350613690565b61368d600182615859565b92505b506135a4565b50909695505050505050565b60405163539c6d4160e11b81526004810184905260009081906001600160a01b0387169063a738da8290602401602060405180830381865afa1580156136ec573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137109190615674565b604051635058979360e01b8152600481018690529091506001600160a01b03821690635058979390602401602060405180830381865afa158015613758573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061377c91906155eb565b60000361378d57600091505061120e565b6000866001600160a01b031663fc0c546a6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156137cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137f19190615674565b60405163f25e55a560e01b81526001600160a01b03808316600483015260248201889052919250600091600191839161387d919087169063f25e55a590604401602060405180830381865afa15801561384e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061387291906155eb565b62093a808106900390565b6040516328a3532760e21b8152600481018a9052602481018290529091506000906001600160a01b0387169063a28d4c9c90604401602060405180830381865afa1580156138cf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138f391906155eb565b604051631277308160e21b8152600481018b90526024810182905290915060009081906001600160a01b038916906349dcc204906044016040805180830381865afa158015613946573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061396a91906158a4565b90925090506139808462093a8084068403613f42565b9350600062093a8061399886828e068e03830161541f565b6139a29190615631565b905060008115613c765760005b82811015613c74576001600160a01b038b1663a28d4c9c8f60016139d662093a808c615473565b6139e0919061541f565b6040516001600160e01b031960e085901b16815260048101929092526024820152604401602060405180830381865afa158015613a21573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613a4591906155eb565b95508a6001600160a01b03166349dcc2048f886040518363ffffffff1660e01b8152600401613a7e929190918252602082015260400190565b6040805180830381865afa158015613a9a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613abe91906158a4565b90955093506001600160a01b038b1663f7412baf816376f4be366001613ae762093a808d615473565b613af1919061541f565b6040518263ffffffff1660e01b8152600401613b0f91815260200190565b602060405180830381865afa158015613b2c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b5091906155eb565b6040518263ffffffff1660e01b8152600401613b6e91815260200190565b6040805180830381865afa158015613b8a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613bae91906158a4565b9250613bbd9050826001613f42565b6040516392777b2960e01b81526001600160a01b038c81166004830152602482018a905291995089918d16906392777b2990604401602060405180830381865afa158015613c0f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613c3391906155eb565b613c3d9086615604565b613c479190615631565b613c51908a615473565b9850613c6062093a8088615473565b965080613c6c81615824565b9150506139af565b505b50959d9c50505050505050505050505050565b600081600003613c9b57506000919050565b60006001613ca88461445a565b901c6001901b90506001818481613cc157613cc161561b565b048201901c90506001818481613cd957613cd961561b565b048201901c90506001818481613cf157613cf161561b565b048201901c90506001818481613d0957613d0961561b565b048201901c90506001818481613d2157613d2161561b565b048201901c90506001818481613d3957613d3961561b565b048201901c90506001818481613d5157613d5161561b565b048201901c90506111fe81828581613d6b57613d6b61561b565b046144ee565b60005b81831015613dc7576000613d8884846144fd565b60008781526020902090915063ffffffff86169082015463ffffffff161115613db357809250613dc1565b613dbe816001615473565b93505b50613d74565b509392505050565b8154600160801b90819004600f0b6000818152600180860160205260409091209390935583546001600160801b03908116939091011602179055565b60408051602080825281830190925260609160ff84169160009180820181803683375050509182525060208101929092525090565b600080613e51888888888888614518565b6000898152600b60205260409020549091506001600160401b0316158015613e7d5750613e7d88612c61565b156116b1576000613e96600a546001600160401b031690565b613e9e611bc3565b65ffffffffffff16613eb091906158c8565b9050613ebb89611f6f565b816001600160401b03161115613f0a576040516001600160401b038216815289907f541f725fb9f7c98a30cc9c0ff32fbb14358cd7159c847a3aa20a2bdc442ba5119060200160405180910390a25b6000898152600b60205260409020805467ffffffffffffffff19166001600160401b0392909216919091179055979650505050505050565b6000818311613f5157816111fe565b5090919050565b815115613f685781518083602001fd5b8060405162461bcd60e51b8152600401610d0491906148d5565b6000306001600160a01b037f00000000000000000000000089dc1de2f8531362c92dda43f1ae50e1ed56862816148015613fdb57507f000000000000000000000000000000000000000000000000000000000000078346145b1561400557507f487a4022e1b28efa92b2cac105709eafcf6f973ac6d64b5038a10e17590335f290565b611c4c604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60208201527f9f70edfdbecfc64caeccd8bcd1749438c9e00ec4c7ffb4422b984559ed301787918101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260009060c00160405160208183030381529060405280519060200120905090565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08311156140e45750600090506003614168565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015614138573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811661416157600060019250925050614168565b9150600090505b94509492505050565b600081600481111561418557614185614d4a565b0361418d5750565b60018160048111156141a1576141a1614d4a565b036141ee5760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e617475726500000000000000006044820152606401610d04565b600281600481111561420257614202614d4a565b0361424f5760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152606401610d04565b600381600481111561426357614263614d4a565b03610d2d5760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b6064820152608401610d04565b8254600090819080156144015760006142d987612ed260018561541f565b60408051808201909152905463ffffffff808216808452600160201b9092046001600160e01b03166020840152919250908716101561435a5760405162461bcd60e51b815260206004820152601b60248201527f436865636b706f696e743a2064656372656173696e67206b65797300000000006044820152606401610d04565b805163ffffffff8088169116036143a2578461437b88612ed260018661541f565b80546001600160e01b0392909216600160201b0263ffffffff9092169190911790556143f1565b6040805180820190915263ffffffff80881682526001600160e01b0380881660208085019182528b54600181018d5560008d81529190912094519151909216600160201b029216919091179101555b6020015192508391506133a99050565b50506040805180820190915263ffffffff80851682526001600160e01b0380851660208085019182528854600181018a5560008a815291822095519251909316600160201b0291909316179201919091559050816133a9565b600080608083901c1561446f57608092831c92015b604083901c1561448157604092831c92015b602083901c1561449357602092831c92015b601083901c156144a557601092831c92015b600883901c156144b757600892831c92015b600483901c156144c957600492831c92015b600283901c156144db57600292831c92015b600183901c15610cdf5760010192915050565b6000818310613f5157816111fe565b600061450c6002848418615631565b6111fe90848416615473565b600086815260046020526040812060016145318961145f565b600881111561454257614542614d4a565b1461459b5760405162461bcd60e51b815260206004820152602360248201527f476f7665726e6f723a20766f7465206e6f742063757272656e746c792061637460448201526269766560e81b6064820152608401610d04565b80546000906145b790899089906001600160401b0316876125df565b90506145c68988888488614672565b835160000361461c5786886001600160a01b03167f02ecdb7f59712b7ae7cb6851cce1c64e98f94e5b51ec63809112c054622b25548b89858a60405161460f94939291906158e8565b60405180910390a3611f63565b86886001600160a01b03167f7dcdc52e34b09364e599a32b0e3ccb5b730a7b952ddbdf4f237ea785da228ce78b89858a8a60405161465e959493929190615910565b60405180910390a398975050505050505050565b6000858152600760209081526040808320878452600381019092529091205460ff16156146f15760405162461bcd60e51b815260206004820152602760248201527f476f7665726e6f72566f74696e6753696d706c653a20766f746520616c726561604482015266191e4818d85cdd60ca1b6064820152608401610d04565b600083116147525760405162461bcd60e51b815260206004820152602860248201527f476f7665726e6f72566f74696e6753696d706c653a207a65726f20766f74696e60448201526719c81dd95a59da1d60c21b6064820152608401610d04565b60008581526003820160205260409020805460ff1916600117905560ff841661479457828160000160008282546147899190615473565b9091555061483a9050565b60001960ff8516016147b457828160010160008282546147899190615473565b60011960ff8516016147d457828160020160008282546147899190615473565b60405162461bcd60e51b815260206004820152603560248201527f476f7665726e6f72566f74696e6753696d706c653a20696e76616c69642076616044820152746c756520666f7220656e756d20566f74655479706560581b6064820152608401610d04565b505050505050565b60006020828403121561485457600080fd5b81356001600160e01b0319811681146111fe57600080fd5b60006020828403121561487e57600080fd5b5035919050565b60005b838110156148a0578181015183820152602001614888565b50506000910152565b600081518084526148c1816020860160208601614885565b601f01601f19169290920160200192915050565b6020815260006111fe60208301846148a9565b6001600160a01b0381168114610d2d57600080fd5b60006020828403121561490f57600080fd5b81356111fe816148e8565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b03811182821017156149585761495861491a565b604052919050565b60006001600160401b038211156149795761497961491a565b5060051b60200190565b600082601f83011261499457600080fd5b813560206149a96149a483614960565b614930565b82815260059290921b840181019181810190868411156149c857600080fd5b8286015b84811015611aca5780356149df816148e8565b83529183019183016149cc565b600082601f8301126149fd57600080fd5b81356020614a0d6149a483614960565b82815260059290921b84018101918181019086841115614a2c57600080fd5b8286015b84811015611aca5780358352918301918301614a30565b60006001600160401b03821115614a6057614a6061491a565b50601f01601f191660200190565b6000614a7c6149a484614a47565b9050828152838383011115614a9057600080fd5b828260208301376000602084830101529392505050565b600082601f830112614ab857600080fd5b6111fe83833560208501614a6e565b600082601f830112614ad857600080fd5b81356020614ae86149a483614960565b82815260059290921b84018101918181019086841115614b0757600080fd5b8286015b84811015611aca5780356001600160401b03811115614b2a5760008081fd5b614b388986838b0101614aa7565b845250918301918301614b0b565b600080600080600060a08688031215614b5e57600080fd5b8535945060208601356001600160401b0380821115614b7c57600080fd5b614b8889838a01614983565b95506040880135915080821115614b9e57600080fd5b614baa89838a016149ec565b94506060880135915080821115614bc057600080fd5b614bcc89838a01614ac7565b93506080880135915080821115614be257600080fd5b508601601f81018813614bf457600080fd5b614c0388823560208401614a6e565b9150509295509295909350565b600080600060608486031215614c2557600080fd5b8335614c30816148e8565b95602085013595506040909401359392505050565b60008060008060808587031215614c5b57600080fd5b8435614c66816148e8565b93506020850135614c76816148e8565b92506040850135915060608501356001600160401b03811115614c9857600080fd5b614ca487828801614aa7565b91505092959194509250565b60008083601f840112614cc257600080fd5b5081356001600160401b03811115614cd957600080fd5b602083019150836020828501011115614cf157600080fd5b9250929050565b60008060008060608587031215614d0e57600080fd5b843593506020850135925060408501356001600160401b03811115614d3257600080fd5b614d3e87828801614cb0565b95989497509550505050565b634e487b7160e01b600052602160045260246000fd5b6020810160098310614d8257634e487b7160e01b600052602160045260246000fd5b91905290565b60008060008060808587031215614d9e57600080fd5b84356001600160401b0380821115614db557600080fd5b614dc188838901614983565b95506020870135915080821115614dd757600080fd5b614de3888389016149ec565b94506040870135915080821115614df957600080fd5b50614e0687828801614ac7565b949793965093946060013593505050565b600080600080600060a08688031215614e2f57600080fd5b85356001600160401b0380821115614e4657600080fd5b614e5289838a01614983565b96506020880135915080821115614e6857600080fd5b614e7489838a016149ec565b95506040880135915080821115614e8a57600080fd5b50614e9788828901614ac7565b935050606086013591506080860135614eaf816148e8565b809150509295509295909350565b60008060408385031215614ed057600080fd5b50508035926020909101359150565b600081518084526020808501945080840160005b83811015614f0f57815187529582019590820190600101614ef3565b509495945050505050565b60ff60f81b8816815260e060208201526000614f3960e08301896148a9565b8281036040840152614f4b81896148a9565b606084018890526001600160a01b038716608085015260a0840186905283810360c08501529050614f7c8185614edf565b9a9950505050505050505050565b600080600080600060a08688031215614fa257600080fd5b8535614fad816148e8565b94506020860135614fbd816148e8565b935060408601356001600160401b0380821115614fd957600080fd5b614fe589838a016149ec565b94506060880135915080821115614ffb57600080fd5b61500789838a016149ec565b9350608088013591508082111561501d57600080fd5b50614c0388828901614aa7565b803560ff8116811461188c57600080fd5b60008060008060008060a0878903121561505457600080fd5b863595506020870135945061506b6040880161502a565b935060608701356001600160401b038082111561508757600080fd5b6150938a838b01614cb0565b909550935060808901359150808211156150ac57600080fd5b506150b989828a01614aa7565b9150509295509295509295565b600080600080606085870312156150dc57600080fd5b84356150e7816148e8565b93506020850135925060408501356001600160401b03811115614d3257600080fd5b60008060008060006080868803121561512157600080fd5b85359450602086013593506151386040870161502a565b925060608601356001600160401b0381111561515357600080fd5b61515f88828901614cb0565b969995985093965092949392505050565b6000806000806080858703121561518657600080fd5b8435615191816148e8565b9350602085013592506040850135915060608501356001600160401b03811115614c9857600080fd5b6000602082840312156151cc57600080fd5b81356001600160401b03811681146111fe57600080fd5b6000806000606084860312156151f857600080fd5b833592506020840135915061520f6040850161502a565b90509250925092565b600080600080600060a0868803121561523057600080fd5b853561523b816148e8565b9450602086013561524b816148e8565b9350604086013592506060860135915060808601356001600160401b0381111561527457600080fd5b614c0388828901614aa7565b60008060008060008060008060006101008a8c03121561529f57600080fd5b8935985060208a013597506152b660408b0161502a565b965060608a01356001600160401b03808211156152d257600080fd5b6152de8d838e01614cb0565b909850965060808c01359150808211156152f757600080fd5b506153048c828d01614aa7565b94505061531360a08b0161502a565b925060c08a0135915060e08a013590509295985092959850929598565b60008060008060008060c0878903121561534957600080fd5b86359550602087013594506153606040880161502a565b935061536e6060880161502a565b92506080870135915060a087013590509295509295509295565b60208082526018908201527f476f7665726e6f723a206f6e6c79476f7665726e616e63650000000000000000604082015260600190565b8183823760009101908152919050565b600181811c908216806153e357607f821691505b60208210810361540357634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b81810381811115610cdf57610cdf615409565b60208082526021908201527f476f7665726e6f723a20696e76616c69642070726f706f73616c206c656e67746040820152600d60fb1b606082015260800190565b80820180821115610cdf57610cdf615409565b600081518084526020808501945080840160005b83811015614f0f5781516001600160a01b03168752958201959082019060010161549a565b600081518084526020808501808196508360051b8101915082860160005b858110156155075782840389526154f58483516148a9565b988501989350908401906001016154dd565b5091979650505050505050565b60006101208b8352602060018060a01b038c168185015281604085015261553d8285018c615486565b91508382036060850152615551828b614edf565b915083820360808501528189518084528284019150828160051b850101838c0160005b838110156155a257601f198784030185526155908383516148a9565b94860194925090850190600101615574565b505086810360a08801526155b6818c6154bf565b9450505050508560c08401528460e08401528281036101008401526155db81856148a9565b9c9b505050505050505050505050565b6000602082840312156155fd57600080fd5b5051919050565b8082028115828204841417610cdf57610cdf615409565b634e487b7160e01b600052601260045260246000fd5b6000826156405761564061561b565b500490565b60208152816020820152818360408301376000818301604090810191909152601f909201601f19160101919050565b60006020828403121561568657600080fd5b81516111fe816148e8565b6000602082840312156156a357600080fd5b81516001600160401b038111156156b957600080fd5b8201601f810184136156ca57600080fd5b80516156d86149a482614a47565b8181528560208385010111156156ed57600080fd5b612098826020830160208601614885565b634e487b7160e01b600052603260045260246000fd5b60006020828403121561572657600080fd5b815165ffffffffffff811681146111fe57600080fd5b60a08152600061574f60a0830188615486565b82810360208401526157618188614edf565b9050828103604084015261577581876154bf565b606084019590955250506001600160a01b03919091166080909101529392505050565b6000602082840312156157aa57600080fd5b8151600381106111fe57600080fd5b6000608082840312156157cb57600080fd5b604051608081018181106001600160401b03821117156157ed576157ed61491a565b604052825181526020830151615802816148e8565b6020820152604083810151908201526060928301519281019290925250919050565b60006001820161583657615836615409565b5060010190565b6000825161584f818460208701614885565b9190910192915050565b65ffffffffffff82811682821603908082111561587857615878615409565b5092915050565b600065ffffffffffff808416806158985761589861561b565b92169190910492915050565b600080604083850312156158b757600080fd5b505080516020909101519092909150565b6001600160401b0381811683821601908082111561587857615878615409565b84815260ff8416602082015282604082015260806060820152600061326460808301846148a9565b85815260ff8516602082015283604082015260a06060820152600061593860a08301856148a9565b8281036080840152611f6381856148a956fe476f7665726e6f723a2072656c617920726576657274656420776974686f7574206d657373616765476f7665726e6f723a2063616c6c20726576657274656420776974686f7574206d657373616765a2646970667358221220ff5084ec0901c5f666a0f87da4e27382ca272edf4b32c142c7bd9cf6228504e764736f6c63430008130033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000c4e6a85630ca1d9b754518f653cb43c3f768215b000000000000000000000000612c5dc0256b8da00bfd6b2b8f711e24b0509044
-----Decoded View---------------
Arg [0] : _ve (address): 0xC4E6a85630cA1d9B754518f653cb43C3F768215B
Arg [1] : _voter (address): 0x612c5dc0256b8Da00BFd6B2B8F711E24b0509044
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 000000000000000000000000c4e6a85630ca1d9b754518f653cb43c3f768215b
Arg [1] : 000000000000000000000000612c5dc0256b8da00bfd6b2b8f711e24b0509044
Net Worth in USD
Net Worth in ETH
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
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.