Source Code
Overview
ETH Balance
0 ETH
ETH Value
$0.00View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Cross-Chain Transactions
Loading...
Loading
Contract Name:
EpochGovernor
Compiler Version
v0.8.19+commit.7dd6d404
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
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 {IVoter} from "contracts/interfaces/IVoter.sol";
import {IGovernor} from "./governance/IGovernor.sol";
import {GovernorSimple} from "./governance/GovernorSimple.sol";
import {GovernorCountingMajority} from "./governance/GovernorCountingMajority.sol";
import {GovernorSimpleVotes} from "./governance/GovernorSimpleVotes.sol";
/**
* @title EpochGovernor
* @notice Epoch based governance system that allows for a three option majority (against, for, abstain).
* @notice Refer to SPECIFICATION.md.
* @dev Note that hash proposals are unique per epoch, but calls to a function with different values
* may be allowed any number of times. It is best to use EpochGovernor with a function that accepts
* no values.
*/
contract EpochGovernor is GovernorSimple, GovernorCountingMajority, GovernorSimpleVotes {
constructor(
address _forwarder,
IVotes _ve,
address _minter,
IVoter _voter
) GovernorSimple(_forwarder, "Epoch Governor", _minter, _voter) GovernorSimpleVotes(_ve) {}
function votingDelay() public pure override(IGovernor) returns (uint256) {
return (15 minutes);
}
function votingPeriod() public pure override(IGovernor) returns (uint256) {
return (1 weeks);
}
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.19;
import {GovernorSimple} from "./GovernorSimple.sol";
/**
* @dev Modified lightly from OpenZeppelin's GovernorCountingSimple to support a simple three option majority.
*
*/
abstract contract GovernorCountingMajority is GovernorSimple {
/**
* @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 Select winner of majority vote.
*/
function _selectWinner(uint256 proposalId) internal view override returns (ProposalState) {
ProposalVote storage proposalVote = _proposalVotes[proposalId];
uint256 againstVotes = proposalVote.againstVotes;
uint256 forVotes = proposalVote.forVotes;
uint256 abstainVotes = proposalVote.abstainVotes;
if ((againstVotes > forVotes) && (againstVotes > abstainVotes)) {
return ProposalState.Defeated;
} else if ((forVotes > againstVotes) && (forVotes > abstainVotes)) {
return ProposalState.Succeeded;
} else {
return ProposalState.Expired;
}
}
/**
* @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: BUSL-1.1
pragma solidity 0.8.19;
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 {ERC2771Context} from "@openzeppelin/contracts/metatx/ERC2771Context.sol";
import {Timers} from "@openzeppelin/contracts/utils/Timers.sol";
import {Strings} from "@openzeppelin/contracts/utils/Strings.sol";
import {IGovernor} from "./IGovernor.sol";
import {IMinter} from "../interfaces/IMinter.sol";
import {TimeLibrary} from "../libraries/TimeLibrary.sol";
import {IVoter} from "contracts/interfaces/IVoter.sol";
import {IVotingEscrow} from "contracts/interfaces/IVotingEscrow.sol";
import {IVetoGovernor} from "contracts/governance/IVetoGovernor.sol";
/**
* @dev Modified lightly from OpenZeppelin's Governor contract to support three option voting via callback.
* A counting module is only required to implement _selectWinner and _countVote.
* Adheres to IGovernor interface, with the following changes:
* - hashProposal(...) generates a hash that allows for only one proposal per epoch
* - state(...) returns a simple majority
* - _selectWinner(...) returns simple majority winner from the three outcomes.
* - execute(...) requires one of three states (Suceeded, Defeated, Expired) to execute.
* - execute(...) sets the result based on the current epoch.
* - cancel(...) does not exist by default (Modified from OZ's IGovernor).
*
* propose(...) creates a proposal for the following epoch. This proposal can only be executed during that epoch.
*/
abstract contract GovernorSimple is ERC2771Context, ERC165, EIP712, IGovernor, 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;
}
// solhint-enable var-name-mixedcase
string private _name;
address public minter;
uint256 public constant COMMENT_DENOMINATOR = 1_000_000_000;
IVoter public immutable _voter;
IVotingEscrow public immutable escrow;
mapping(uint256 => ProposalCore) private _proposals;
/// @dev Stores most recent voting result. Will be either Defeated, Succeeded or Expired.
/// Any contracts that wish to use this governor must read from this to determine results.
ProposalState public result;
// 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(), "GovernorSimple: 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}, and sets up meta-tx
*/
constructor(
address forwarder_,
string memory name_,
address minter_,
IVoter voter_
) ERC2771Context(forwarder_) EIP712(name_, version()) {
_name = name_;
minter = minter_;
_voter = voter_;
escrow = IVotingEscrow(voter_.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(IGovernor).interfaceId ^
type(IERC6372).interfaceId ^
this.castVoteWithReasonAndParams.selector ^
this.castVoteWithReasonAndParamsBySig.selector ^
this.getVotesWithParams.selector) ||
// Previous interface for backwards compatibility
interfaceId == (type(IGovernor).interfaceId ^ type(IERC6372).interfaceId) ||
interfaceId == type(IERC1155Receiver).interfaceId ||
super.supportsInterface(interfaceId);
}
/**
* @dev See {IGovernor-name}.
*/
function name() public view virtual override returns (string memory) {
return _name;
}
/**
* @dev See {IGovernor-version}.
*/
function version() public view virtual override returns (string memory) {
return "1";
}
/**
* @dev See {IGovernor-hashProposal}.
*
* The proposal id is produced by hashing the ABI encoded `targets` array, the `values` array, the `calldatas` array
* and the descriptionHash (bytes32 which itself is the keccak256 hash of the description string). This proposal id
* can be produced from the proposal data which is part of the {ProposalCreated} event. It can even be computed in
* advance, before the proposal is submitted.
*
* Note that the chainId and the governor address are not part of the proposal id computation. Consequently, the
* same proposal (with same operation and same description) will have the same id if submitted on multiple governors
* across multiple networks. This also means that in order to execute the same operation twice (on the same
* governor) the proposer will have to change the description in order to avoid proposal id conflicts.
*
* The proposal id ignores description hash and uses the epoch start time for the following week. This ensures that only
* one proposal can be created per week.
*/
function hashProposal(
address[] memory targets,
uint256[] memory values,
bytes[] memory calldatas,
bytes32 epochStart
) public pure virtual override returns (uint256) {
return uint256(keccak256(abi.encode(targets, values, calldatas, epochStart)));
}
/**
* @dev See {IGovernor-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;
}
uint256 snapshot = proposalSnapshot(proposalId);
if (snapshot == 0) {
revert("GovernorSimple: unknown proposal id");
}
uint256 currentTimepoint = clock();
if (snapshot >= currentTimepoint) {
return ProposalState.Pending;
}
uint256 deadline = proposalDeadline(proposalId);
if (deadline >= currentTimepoint) {
return ProposalState.Active;
}
return _selectWinner(proposalId);
}
/**
* @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 Select winner of majority vote.
*/
function _selectWinner(uint256 proposalId) internal view virtual returns (ProposalState);
/**
* @dev See {IGovernor-proposalSnapshot}.
*/
function proposalSnapshot(uint256 proposalId) public view virtual override returns (uint256) {
return _proposals[proposalId].voteStart;
}
/**
* @dev See {IGovernor-proposalDeadline}.
*/
function proposalDeadline(uint256 proposalId) public view virtual override returns (uint256) {
return _proposals[proposalId].voteEnd;
}
/**
* @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 {IGovernor-propose}.
* description is ignored. The proposalId is created using the following epoch's start date.
*/
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(),
"GovernorSimple: proposer votes below proposal threshold"
);
require(targets.length == 1, "GovernorSimple: only one target allowed");
require(address(targets[0]) == minter, "GovernorSimple: only minter allowed");
require(calldatas.length == 1, "GovernorSimple: only one calldata allowed");
require(bytes4(calldatas[0]) == IMinter.nudge.selector, "GovernorSimple: only nudge allowed");
bytes32 epochStart = bytes32(TimeLibrary.epochStart(block.timestamp) + (1 weeks));
uint256 proposalId = hashProposal(targets, values, calldatas, epochStart);
require(targets.length > 0, "GovernorSimple: empty proposal");
require(_proposals[proposalId].proposer == address(0), "GovernorSimple: 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
});
emit ProposalCreated(
proposalId,
proposer,
targets,
values,
new string[](targets.length),
calldatas,
snapshot,
deadline,
Strings.toString(uint256(epochStart))
);
return proposalId;
}
/**
* @dev See {IGovernor-execute}.
* Executes a proposal with a start time at the beginning of this epoch.
*/
function execute(
address[] memory targets,
uint256[] memory values,
bytes[] memory calldatas,
bytes32 descriptionHash
) public payable virtual override returns (uint256) {
bytes32 epochStart = bytes32(TimeLibrary.epochStart(block.timestamp));
uint256 proposalId = hashProposal(targets, values, calldatas, epochStart);
ProposalState status = state(proposalId);
require(
status == ProposalState.Succeeded, "GovernorSimple: proposal not successful"
);
_proposals[proposalId].executed = true;
emit ProposalExecuted(proposalId);
result = status;
_beforeExecute(proposalId, targets, values, calldatas, descriptionHash);
_execute(proposalId, targets, values, calldatas, descriptionHash);
_afterExecute(proposalId, targets, values, calldatas, descriptionHash);
return proposalId;
}
/**
* @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 See {IGovernor-getVotes}.
*/
function getVotes(
address account,
uint256 tokenId,
uint256 timepoint
) public view virtual override returns (uint256) {
return _getVotes(account, tokenId, timepoint, _defaultParams());
}
/**
* @dev See {IGovernor-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 {IGovernor-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 {IGovernor-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 {IGovernor-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 {IGovernor-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 {IGovernor-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 {IGovernor-getVotes} and call the {_countVote} internal function. Uses the _defaultParams().
*
* Emits a {IGovernor-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 {IGovernor-getVotes} and call the {_countVote} internal function.
*
* Emits a {IGovernor-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, "GovernorSimple: 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,
"EpochGovernor: not active or pending"
);
uint256 startTime = proposal.voteStart;
address account = _msgSender();
uint256 weight = _getVotes(account, tokenId, startTime, params);
uint256 commentWeighting = IVetoGovernor(_voter.governor()).commentWeighting();
uint256 minimumWeight = (escrow.getPastTotalSupply(startTime) * commentWeighting) / COMMENT_DENOMINATOR;
require(weight > minimumWeight, "EpochGovernor: insufficient voting power");
emit Comment(proposalId, account, tokenId, 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
pragma solidity 0.8.19;
import {IERC6372} from "@openzeppelin/contracts/interfaces/IERC6372.sol";
import {IVotes} from "./IVotes.sol";
import {SafeCast} from "@openzeppelin/contracts/utils/math/SafeCast.sol";
import {GovernorSimple} from "./GovernorSimple.sol";
import {IVotingEscrow} from "contracts/interfaces/IVotingEscrow.sol";
import {DelegationHelperLibrary} from "contracts/libraries/DelegationHelperLibrary.sol";
/**
* @dev Modified lightly from OpenZeppelin's GovernorVotes
*/
abstract contract GovernorSimpleVotes is GovernorSimple {
using DelegationHelperLibrary for IVotingEscrow;
IVotes public immutable token;
IVotingEscrow public immutable ve;
constructor(IVotes tokenAddress) {
token = IVotes(address(tokenAddress));
ve = IVotingEscrow(address(token));
}
/**
* @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, "EpochGovernor: 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
pragma solidity ^0.8.0;
import {IERC165} from "@openzeppelin/contracts/utils/introspection/ERC165.sol";
import {IERC6372} from "@openzeppelin/contracts/interfaces/IERC6372.sol";
/**
* @dev Taken from OpenZeppelin's IGovernor. Excludes `cancel` and `quorum`.
*/
abstract contract IGovernor is IERC165, IERC6372 {
enum ProposalState {
Pending,
Active,
Canceled,
Defeated,
Succeeded,
Queued, // unused, required for backwards compatibility
Expired,
Executed
}
/**
* @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 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 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
) 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: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
) public payable 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;
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: MIT
pragma solidity ^0.8.0;
import {INeptune} from "./INeptune.sol";
import {IVoter} from "./IVoter.sol";
import {IVotingEscrow} from "./IVotingEscrow.sol";
import {IRewardsDistributor} from "./IRewardsDistributor.sol";
interface IMinter {
struct AirdropParams {
// List of addresses to receive Liquid Tokens from the airdrop
address[] liquidWallets;
// List of amounts of Liquid Tokens to be issued
uint256[] liquidAmounts;
// List of addresses to receive Locked NFTs from the airdrop
address[] lockedWallets;
// List of amounts of Locked NFTs to be issued
uint256[] lockedAmounts;
}
error NotTeam();
error RateTooHigh();
error ZeroAddress();
error InvalidParams();
error AlreadyNudged();
error NotPendingTeam();
error NotEpochGovernor();
error AlreadyInitialized();
error TailEmissionsInactive();
event Mint(address indexed _sender, uint256 _weekly, uint256 _circulating_supply, bool indexed _tail);
event DistributeLocked(address indexed _destination, uint256 _amount, uint256 _tokenId);
event Nudge(uint256 indexed _period, uint256 _oldRate, uint256 _newRate);
event DistributeLiquid(address indexed _destination, uint256 _amount);
event AcceptTeam(address indexed _newTeam);
event AcceptMarketing(address indexed _newMarketing);
/// @notice Interface of Neptune.sol
function neptune() external view returns (INeptune);
/// @notice Interface of Voter.sol
function voter() external view returns (IVoter);
/// @notice Interface of IVotingEscrow.sol
function ve() external view returns (IVotingEscrow);
/// @notice Interface of RewardsDistributor.sol
function rewardsDistributor() external view returns (IRewardsDistributor);
/// @notice Duration of epoch in seconds
function WEEK() external view returns (uint256);
/// @notice Growth rate of emissions as percentage of `MAX_BPS` in first 15 weeks
function WEEKLY_GROWTH() external view returns (uint256);
/// @notice Maximum tail emission rate in basis points.
function MAXIMUM_TAIL_RATE() external view returns (uint256);
/// @notice Minimum tail emission rate in basis points.
function MINIMUM_TAIL_RATE() external view returns (uint256);
/// @notice Denominator for emissions calculations (as basis points)
function MAX_BPS() external view returns (uint256);
/// @notice Rate change per proposal
function NUDGE() external view returns (uint256);
/// @notice When epoch higher than this amount, begin tail emissions
function EPOCH_TAIL_START() external view returns (uint256);
/// @notice Maximum team percentage in basis points
function MAXIMUM_TEAM_RATE() external view returns (uint256);
/// @notice Maximum marketing percentage in basis points
function MAXIMUM_MARKETING_RATE() external view returns (uint256);
/// @notice Current team percentage in basis points
function teamRate() external view returns (uint256);
/// @notice Current marketing percentage in basis points
function marketingRate() external view returns (uint256);
/// @notice Tail emissions rate in basis points
function tailEmissionRate() external view returns (uint256);
/// @notice Starting weekly emission of 50k NEP (NEP has 18 decimals)
function weekly() external view returns (uint256);
/// @notice Timestamp of start of epoch that updatePeriod was last called in
function activePeriod() external view returns (uint256);
/// @notice Number of epochs in which updatePeriod was called
function epochCount() external view returns (uint256);
/// @notice Boolean used to verify if contract has been initialized
function initialized() external returns (bool);
/// @dev activePeriod => proposal existing, used to enforce one proposal per epoch
/// @param _activePeriod Timestamp of start of epoch
/// @return True if proposal has been executed, else false
function proposals(uint256 _activePeriod) external view returns (bool);
/// @notice Current team address in charge of emissions
function team() external view returns (address);
/// @notice Possible team address pending approval of current team
function pendingTeam() external view returns (address);
/// @notice Current marketing address in charge of emissions
function marketing() external view returns (address);
/// @notice Mints liquid tokens and permanently locked NFTs to the provided accounts
/// @param params Struct that stores the wallets and amounts for the Airdrops
function initialize(AirdropParams memory params) external;
/// @notice Creates a request to change the current team's address
/// @param _team Address of the new team to be chosen
function setTeam(address _team) external;
/// @notice Accepts the request to replace the current team's address
/// with the requested one, present on variable pendingTeam
function acceptTeam() external;
/// @notice Creates a request to change the current team's percentage
/// @param _rate New team rate to be set in basis points
function setTeamRate(uint256 _rate) external;
/// @notice Creates a request to change the current marketing's address
/// @param _marketing Address of the new marketing to be chosen
function setMarketing(address _marketing) external;
/// @notice Creates a request to change the current marketing's percentage
/// @param _rate New marketing rate to be set in basis points
function setMarketingRate(uint256 _rate) external;
/// @notice Allows epoch governor to modify the tail emission rate by at most 1 basis point
/// per epoch to a maximum of 100 basis points or to a minimum of 1 basis point.
/// Note: the very first nudge proposal must take place the week prior
/// to the tail emission schedule starting.
/// @dev Throws if not epoch governor.
/// Throws if not currently in tail emission schedule.
/// Throws if already nudged this epoch.
/// Throws if nudging above maximum rate.
/// Throws if nudging below minimum rate.
/// This contract is coupled to EpochGovernor as it requires three option simple majority voting.
function nudge() external;
/// @notice Calculates rebases according to the formula
/// weekly * ((neptune.totalsupply - ve.totalSupply) / neptune.totalsupply) ^ 2 / 2
/// Note that ve.totalSupply is the locked ve supply
/// neptune.totalSupply is the total ve supply minted
/// @param _minted Amount of NEP minted this epoch
/// @return _growth Rebases
function calculateGrowth(uint256 _minted) external view returns (uint256 _growth);
/// @notice Processes emissions and rebases. Callable once per epoch (1 week).
/// @return _period Start of current epoch.
function updatePeriod() external returns (uint256 _period);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
interface INeptune is IERC20 {
error NotMinter();
error NotOwner();
/// @notice Mint an amount of tokens to an account
/// Only callable by Minter.sol
/// @return True if success
function mint(address account, uint256 amount) external returns (bool);
/// @notice Address of Minter.sol
function minter() external view returns (address);
}// 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;
import {IVotingEscrow} from "./IVotingEscrow.sol";
interface IRewardsDistributor {
event CheckpointToken(uint256 time, uint256 tokens);
event Claimed(uint256 indexed tokenId, uint256 indexed epochStart, uint256 indexed epochEnd, uint256 amount);
error NotMinter();
error NotManagedOrNormalNFT();
error UpdatePeriod();
/// @notice 7 days in seconds
function WEEK() external view returns (uint256);
/// @notice Timestamp of contract creation
function startTime() external view returns (uint256);
/// @notice Timestamp of most recent claim of tokenId
function timeCursorOf(uint256 tokenId) external view returns (uint256);
/// @notice The last timestamp Minter has called checkpointToken()
function lastTokenTime() external view returns (uint256);
/// @notice Interface of VotingEscrow.sol
function ve() external view returns (IVotingEscrow);
/// @notice Address of token used for distributions (NEP)
function token() external view returns (address);
/// @notice Address of Minter.sol
/// Authorized caller of checkpointToken()
function minter() external view returns (address);
/// @notice Amount of token in contract when checkpointToken() was last called
function tokenLastBalance() external view returns (uint256);
/// @notice Called by Minter to notify Distributor of rebases
function checkpointToken() external;
/// @notice Returns the amount of rebases claimable for a given token ID
/// @dev Allows claiming of rebases up to 50 epochs old
/// @param tokenId The token ID to check
/// @return The amount of rebases claimable for the given token ID
function claimable(uint256 tokenId) external view returns (uint256);
/// @notice Claims rebases for a given token ID
/// @dev Allows claiming of rebases up to 50 epochs old
/// `Minter.updatePeriod()` must be called before claiming
/// @param tokenId The token ID to claim for
/// @return The amount of rebases claimed
function claim(uint256 tokenId) external returns (uint256);
/// @notice Claims rebases for a list of token IDs
/// @dev `Minter.updatePeriod()` must be called before claiming
/// @param tokenIds The token IDs to claim for
/// @return Whether or not the claim succeeded
function claimMany(uint256[] calldata tokenIds) external returns (bool);
/// @notice Used to set minter once on initialization
/// @dev Callable once by Minter only, Minter is immutable
function setMinter(address _minter) external;
}// 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.7.0) (metatx/ERC2771Context.sol)
pragma solidity ^0.8.9;
import "../utils/Context.sol";
/**
* @dev Context variant with ERC2771 support.
*/
abstract contract ERC2771Context is Context {
/// @custom:oz-upgrades-unsafe-allow state-variable-immutable
address private immutable _trustedForwarder;
/// @custom:oz-upgrades-unsafe-allow constructor
constructor(address trustedForwarder) {
_trustedForwarder = trustedForwarder;
}
function isTrustedForwarder(address forwarder) public view virtual returns (bool) {
return forwarder == _trustedForwarder;
}
function _msgSender() internal view virtual override returns (address sender) {
if (isTrustedForwarder(msg.sender)) {
// The assembly code is more direct than the Solidity version using `abi.decode`.
/// @solidity memory-safe-assembly
assembly {
sender := shr(96, calldataload(sub(calldatasize(), 20)))
}
} else {
return super._msgSender();
}
}
function _msgData() internal view virtual override returns (bytes calldata) {
if (isTrustedForwarder(msg.sender)) {
return msg.data[:msg.data.length - 20];
} else {
return super._msgData();
}
}
}// 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 (last updated v4.6.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, uint256 amount) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `from` to `to` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(address from, address to, uint256 amount) external returns (bool);
}// 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 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;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Timers.sol)
pragma solidity ^0.8.0;
/**
* @dev Tooling for timepoints, timers and delays
*
* CAUTION: This file is deprecated as of 4.9 and will be removed in the next major release.
*/
library Timers {
struct Timestamp {
uint64 _deadline;
}
function getDeadline(Timestamp memory timer) internal pure returns (uint64) {
return timer._deadline;
}
function setDeadline(Timestamp storage timer, uint64 timestamp) internal {
timer._deadline = timestamp;
}
function reset(Timestamp storage timer) internal {
timer._deadline = 0;
}
function isUnset(Timestamp memory timer) internal pure returns (bool) {
return timer._deadline == 0;
}
function isStarted(Timestamp memory timer) internal pure returns (bool) {
return timer._deadline > 0;
}
function isPending(Timestamp memory timer) internal view returns (bool) {
return timer._deadline > block.timestamp;
}
function isExpired(Timestamp memory timer) internal view returns (bool) {
return isStarted(timer) && timer._deadline <= block.timestamp;
}
struct BlockNumber {
uint64 _deadline;
}
function getDeadline(BlockNumber memory timer) internal pure returns (uint64) {
return timer._deadline;
}
function setDeadline(BlockNumber storage timer, uint64 timestamp) internal {
timer._deadline = timestamp;
}
function reset(BlockNumber storage timer) internal {
timer._deadline = 0;
}
function isUnset(BlockNumber memory timer) internal pure returns (bool) {
return timer._deadline == 0;
}
function isStarted(BlockNumber memory timer) internal pure returns (bool) {
return timer._deadline > 0;
}
function isPending(BlockNumber memory timer) internal view returns (bool) {
return timer._deadline > block.number;
}
function isExpired(BlockNumber memory timer) internal view returns (bool) {
return isStarted(timer) && timer._deadline <= block.number;
}
}{
"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":"address","name":"_forwarder","type":"address"},{"internalType":"contract IVotes","name":"_ve","type":"address"},{"internalType":"address","name":"_minter","type":"address"},{"internalType":"contract IVoter","name":"_voter","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"string","name":"str","type":"string"}],"name":"StringTooLong","type":"error"},{"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":"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":"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":"_voter","outputs":[{"internalType":"contract IVoter","name":"","type":"address"}],"stateMutability":"view","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":"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"}],"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":"epochStart","type":"bytes32"}],"name":"hashProposal","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"forwarder","type":"address"}],"name":"isTrustedForwarder","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minter","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256[]","name":"","type":"uint256[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC1155BatchReceived","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC1155Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC721Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"}],"name":"proposalDeadline","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"}],"name":"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":"","type":"string"}],"name":"propose","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"result","outputs":[{"internalType":"enum IGovernor.ProposalState","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"}],"name":"state","outputs":[{"internalType":"enum IGovernor.ProposalState","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"token","outputs":[{"internalType":"contract IVotes","name":"","type":"address"}],"stateMutability":"view","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":[],"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
6102006040523480156200001257600080fd5b5060405162004b2738038062004b278339810160408190526200003591620002b3565b82846040518060400160405280600e81526020016d22b837b1b41023b7bb32b93737b960911b81525084848262000071620001fa60201b60201c565b6001600160a01b0386166080526200008b82600062000215565b610100526200009c81600162000215565b61012052815160208084019190912061014052815190820120610160524660c0526200012c6101405161016051604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60208201529081019290925260608201524660808201523060a082015260009060c00160405160208183030381529060405280519060200120905090565b60a05250503060e0526002620001438482620003c0565b50600380546001600160a01b0319166001600160a01b0384811691909117909155811661018081905260408051630fc2838b60e11b81529051631f850716916004808201926020929091908290030181865afa158015620001a8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001ce91906200048c565b6001600160a01b039081166101a052949094166101c08190526101e05250620005289650505050505050565b6040805180820190915260018152603160f81b602082015290565b600060208351101562000235576200022d836200024e565b905062000248565b81620002428482620003c0565b50600090505b92915050565b600080829050601f8151111562000285578260405163305a27a960e01b81526004016200027c9190620004b3565b60405180910390fd5b8051620002928262000503565b179392505050565b6001600160a01b0381168114620002b057600080fd5b50565b60008060008060808587031215620002ca57600080fd5b8451620002d7816200029a565b6020860151909450620002ea816200029a565b6040860151909350620002fd816200029a565b606086015190925062000310816200029a565b939692955090935050565b634e487b7160e01b600052604160045260246000fd5b600181811c908216806200034657607f821691505b6020821081036200036757634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115620003bb57600081815260208120601f850160051c81016020861015620003965750805b601f850160051c820191505b81811015620003b757828155600101620003a2565b5050505b505050565b81516001600160401b03811115620003dc57620003dc6200031b565b620003f481620003ed845462000331565b846200036d565b602080601f8311600181146200042c5760008415620004135750858301515b600019600386901b1c1916600185901b178555620003b7565b600085815260208120601f198616915b828110156200045d578886015182559484019460019091019084016200043c565b50858210156200047c5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6000602082840312156200049f57600080fd5b8151620004ac816200029a565b9392505050565b600060208083528351808285015260005b81811015620004e257858101830151858201604001528201620004c4565b506000604082860101526040601f19601f8301168501019250505092915050565b80516020808301519190811015620003675760001960209190910360031b1b16919050565b60805160a05160c05160e05161010051610120516101405161016051610180516101a0516101c0516101e0516145046200062360003960008181610387015281816116f601528181611b7a01528181611d2901528181611dad01528181611e0601528181611f470152611fc30152600081816108c7015281816114ff0152818161164901528181611c9d01528181611eaf015261203d015260008181610827015261128b015260008181610485015261119e0152600061328101526000613259015260006115f5015260006115cb015260006131b4015260006131de015260006132080152600081816105850152611a1b01526145046000f3fe60806040526004361061023f5760003560e01c806364390ff11161012e578063c59057e4116100ab578063e2fdcc171161006f578063e2fdcc1714610815578063f23a6e6114610849578063f945970a14610875578063fa25f37714610895578063fc0c546a146108b557600080fd5b8063c59057e41461073b578063cf781d451461075b578063dd4e2ba51461077b578063dea112a6146107c1578063deaaa7cc146107e157600080fd5b8063b58131b0116100f2578063b58131b014610682578063bc197c8114610696578063be443ad0146106c2578063c01f9e37146106e2578063c2e863e41461071b57600080fd5b806364390ff1146105b557806365372147146105f457806384b0196e1461060e57806391ddadf41461063657806391f366331461066257600080fd5b80632d63f693116101bc5780633e4f49e6116101805780633e4f49e6146104a75780634bf5d7e9146104d4578063544ffc9c146104e957806354fd4d501461053e578063572b6c051461056857600080fd5b80632d63f693146103d45780632fe3e2611461040a578063380a243a1461043e5780633932abb11461045e5780633db9b42a1461047357600080fd5b806311fd26f41161020357806311fd26f41461031c578063150b7a021461033c5780631f8507161461037557806322b36ac6146103a95780632656227d146103c157600080fd5b806301ffc9a71461024d57806302a251a31461028257806306fdde03146102a257806307546172146102c45780630f8a8836146102fc57600080fd5b3661024857005b005b600080fd5b34801561025957600080fd5b5061026d610268366004613523565b6108e9565b60405190151581526020015b60405180910390f35b34801561028e57600080fd5b5062093a805b604051908152602001610279565b3480156102ae57600080fd5b506102b7610956565b604051610279919061359d565b3480156102d057600080fd5b506003546102e4906001600160a01b031681565b6040516001600160a01b039091168152602001610279565b34801561030857600080fd5b506102946103173660046137f1565b6109e8565b34801561032857600080fd5b506102946103373660046138bb565b610f43565b34801561034857600080fd5b5061035c6103573660046138f0565b610f6f565b6040516001600160e01b03199091168152602001610279565b34801561038157600080fd5b506102e47f000000000000000000000000000000000000000000000000000000000000000081565b3480156103b557600080fd5b50610294633b9aca0081565b6102946103cf36600461395b565b610f80565b3480156103e057600080fd5b506102946103ef3660046139ea565b6000908152600460205260409020546001600160401b031690565b34801561041657600080fd5b506102947fb3b3f3b703cd84ce352197dcff232b1b5d3cfb2025ce47cf04742d0651f1af8881565b34801561044a57600080fd5b50610246610459366004613a4b565b6110ce565b34801561046a57600080fd5b50610384610294565b34801561047f57600080fd5b506102e47f000000000000000000000000000000000000000000000000000000000000000081565b3480156104b357600080fd5b506104c76104c23660046139ea565b6113e1565b6040516102799190613ab3565b3480156104e057600080fd5b506102b76114fb565b3480156104f557600080fd5b506105236105043660046139ea565b6000908152600860205260409020805460018201546002909201549092565b60408051938452602084019290925290820152606001610279565b34801561054a57600080fd5b506040805180820190915260018152603160f81b60208201526102b7565b34801561057457600080fd5b5061026d610583366004613adb565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0390811691161490565b3480156105c157600080fd5b5061026d6105d0366004613af8565b60009182526008602090815260408084209284526003909201905290205460ff1690565b34801561060057600080fd5b506005546104c79060ff1681565b34801561061a57600080fd5b506106236115bd565b6040516102799796959493929190613b55565b34801561064257600080fd5b5061064b611645565b60405165ffffffffffff9091168152602001610279565b34801561066e57600080fd5b5061029461067d366004613af8565b6116d3565b34801561068e57600080fd5b506000610294565b3480156106a257600080fd5b5061035c6106b1366004613bc5565b63bc197c8160e01b95945050505050565b3480156106ce57600080fd5b506102946106dd366004613c76565b61177e565b3480156106ee57600080fd5b506102946106fd3660046139ea565b6000908152600460205260409020600101546001600160401b031690565b34801561072757600080fd5b50610294610736366004613d01565b6117dc565b34801561074757600080fd5b5061029461075636600461395b565b611837565b34801561076757600080fd5b50610294610776366004613d68565b611871565b34801561078757600080fd5b506040805180820190915260208082527f737570706f72743d627261766f2671756f72756d3d666f722c6162737461696e908201526102b7565b3480156107cd57600080fd5b506102946107dc366004613db2565b611888565b3480156107ed57600080fd5b506102947f150214d74d59b7d1e90c73fc22ef3d991dd0a76b046543d4d80ab92d2a50328f81565b34801561082157600080fd5b506102e47f000000000000000000000000000000000000000000000000000000000000000081565b34801561085557600080fd5b5061035c610864366004613de7565b63f23a6e6160e01b95945050505050565b34801561088157600080fd5b50610294610890366004613e4f565b6118b1565b3480156108a157600080fd5b506102946108b0366004613eff565b6119ab565b3480156108c157600080fd5b506102e47f000000000000000000000000000000000000000000000000000000000000000081565b60006001600160e01b03198216632003110360e01b148061091a57506001600160e01b03198216632a1ea86760e21b145b8061093557506001600160e01b03198216630271189760e51b145b8061095057506301ffc9a760e01b6001600160e01b03198316145b92915050565b60606002805461096590613f57565b80601f016020809104026020016040519081016040528092919081815260200182805461099190613f57565b80156109de5780601f106109b3576101008083540402835291602001916109de565b820191906000526020600020905b8154815290600101906020018083116109c157829003601f168201915b5050505050905090565b6000806109f3611a17565b905060006109ff611645565b65ffffffffffff1690506000610a1b838a610337600186613fa7565b1015610a945760405162461bcd60e51b815260206004820152603760248201527f476f7665726e6f7253696d706c653a2070726f706f73657220766f746573206260448201527f656c6f772070726f706f73616c207468726573686f6c6400000000000000000060648201526084015b60405180910390fd5b8651600114610af55760405162461bcd60e51b815260206004820152602760248201527f476f7665726e6f7253696d706c653a206f6e6c79206f6e652074617267657420604482015266185b1b1bddd95960ca1b6064820152608401610a8b565b60035487516001600160a01b03909116908890600090610b1757610b17613fba565b60200260200101516001600160a01b031614610b815760405162461bcd60e51b815260206004820152602360248201527f476f7665726e6f7253696d706c653a206f6e6c79206d696e74657220616c6c6f6044820152621dd95960ea1b6064820152608401610a8b565b8451600114610be45760405162461bcd60e51b815260206004820152602960248201527f476f7665726e6f7253696d706c653a206f6e6c79206f6e652063616c6c6461746044820152681848185b1b1bddd95960ba1b6064820152608401610a8b565b8451634804532160e11b908690600090610c0057610c00613fba565b6020026020010151610c1190613fd0565b6001600160e01b03191614610c735760405162461bcd60e51b815260206004820152602260248201527f476f7665726e6f7253696d706c653a206f6e6c79206e7564676520616c6c6f77604482015261195960f21b6064820152608401610a8b565b6000610c844262093a808106900390565b610c919062093a80614007565b90506000610ca189898985611837565b90506000895111610cf45760405162461bcd60e51b815260206004820152601e60248201527f476f7665726e6f7253696d706c653a20656d7074792070726f706f73616c00006044820152606401610a8b565b600081815260046020526040902054600160401b90046001600160a01b031615610d705760405162461bcd60e51b815260206004820152602760248201527f476f7665726e6f7253696d706c653a2070726f706f73616c20616c72656164796044820152662065786973747360c81b6064820152608401610a8b565b6000610d7e61038485614007565b90506000610d8f62093a8083614007565b90506040518060e00160405280610da584611a5b565b6001600160401b031681526001600160a01b038816602082015260006040820152606001610dd283611a5b565b6001600160401b039081168252600060208084018290526040808501839052606094850183905288835260048252918290208551815492870151878501519186166001600160e01b031990941693909317600160401b6001600160a01b039094168402176001600160e01b0316600160e01b60e09290921c91909102178155938501516080860151908416921c0217600183015560a08301516002909201805460c09094015161ffff1990941692151561ff00191692909217610100931515939093029290921790558b517f7d84a6263ae0d98d3329bd7b46bb4e8d6f98cd35a7adb45c274c8b7fd5ebd5e091859189918f918f91811115610ed657610ed66135b0565b604051908082528060200260200182016040528015610f0957816020015b6060815260200190600190039081610ef45790505b508e8888610f168d611ac7565b604051610f2b999897969594939291906140a8565b60405180910390a150909a9950505050505050505050565b6000610f65848484610f6060408051602081019091526000815290565b611b59565b90505b9392505050565b630a85bd0160e11b5b949350505050565b600080610f924262093a808106900390565b90506000610fa287878785611837565b90506000610faf826113e1565b90506004816007811115610fc557610fc5613a9d565b146110225760405162461bcd60e51b815260206004820152602760248201527f476f7665726e6f7253696d706c653a2070726f706f73616c206e6f742073756360448201526618d95cdcd99d5b60ca1b6064820152608401610a8b565b60008281526004602052604090819020600201805460ff19166001179055517f712ae1383f79ac853f8d882153778e0260ef8f03b504e2866e0593e04d2b291f906110709084815260200190565b60405180910390a16005805482919060ff1916600183600781111561109757611097613a9d565b02179055506110a982898989896120b5565b6110b68289898989612142565b6110c382898989896120b5565b509695505050505050565b60008481526004602052604081206060916110e8876113e1565b905060018160078111156110fe576110fe613a9d565b148061111b5750600081600781111561111957611119613a9d565b145b6111735760405162461bcd60e51b8152602060048201526024808201527f45706f6368476f7665726e6f723a206e6f7420616374697665206f722070656e60448201526364696e6760e01b6064820152608401610a8b565b81546001600160401b03166000611188611a17565b90506000611198828a8589611b59565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316630c340a246040518163ffffffff1660e01b8152600401602060405180830381865afa1580156111fa573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061121e919061417f565b6001600160a01b031663525f9c3e6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561125b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061127f919061419c565b90506000633b9aca00827f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316638e539e8c886040518263ffffffff1660e01b81526004016112d791815260200190565b602060405180830381865afa1580156112f4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611318919061419c565b61132291906141b5565b61132c91906141e2565b905080831161138e5760405162461bcd60e51b815260206004820152602860248201527f45706f6368476f7665726e6f723a20696e73756666696369656e7420766f74696044820152673733903837bbb2b960c11b6064820152608401610a8b565b8a846001600160a01b03168d7fdb700dee4c69422ecdfd4ad68ffe25aa39c6ddffef4657f727571e095b642cc58d8d6040516113cb9291906141f6565b60405180910390a4505050505050505050505050565b6000818152600460205260408120600281015460ff16156114055750600792915050565b6002810154610100900460ff16156114205750600292915050565b6000838152600460205260408120546001600160401b0316908190036114945760405162461bcd60e51b815260206004820152602360248201527f476f7665726e6f7253696d706c653a20756e6b6e6f776e2070726f706f73616c604482015262081a5960ea1b6064820152608401610a8b565b600061149e611645565b65ffffffffffff1690508082106114ba57506000949350505050565b6000858152600460205260409020600101546001600160401b03168181106114e85750600195945050505050565b6114f186612244565b9695505050505050565b60607f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634bf5d7e96040518163ffffffff1660e01b8152600401600060405180830381865afa92505050801561157c57506040513d6000823e601f3d908101601f191682016040526115799190810190614225565b60015b6115b8575060408051808201909152601d81527f6d6f64653d626c6f636b6e756d6265722666726f6d3d64656661756c74000000602082015290565b919050565b6000606080828080836115f07f0000000000000000000000000000000000000000000000000000000000000000836122a8565b61161b7f000000000000000000000000000000000000000000000000000000000000000060016122a8565b60408051600080825260208201909252600f60f81b9b939a50919850469750309650945092509050565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166391ddadf46040518163ffffffff1660e01b8152600401602060405180830381865afa9250505080156116c1575060408051601f3d908101601f191682019092526116be91810190614292565b60015b6115b8576116ce43612354565b905090565b6040516331a9108f60e11b81526004810183905260009081906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636352211e90602401602060405180830381865afa15801561173d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611761919061417f565b9050610f7881858560405180602001604052806000815250611b59565b600080611789611a17565b90506117d08882898989898080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508b92506123bb915050565b98975050505050505050565b6000806117e7611a17565b905061182c8782888888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061251b92505050565b979650505050505050565b60008484848460405160200161185094939291906142ba565b60408051601f19818403018152919052805160209091012095945050505050565b600061187f85858585611b59565b95945050505050565b600080611893611a17565b905061187f858286866040518060200160405280600081525061251b565b60008061195561194d7fb3b3f3b703cd84ce352197dcff232b1b5d3cfb2025ce47cf04742d0651f1af888d8c8c8c6040516118ed929190614305565b60405180910390208b80519060200120604051602001611932959493929190948552602085019390935260ff9190911660408401526060830152608082015260a00190565b6040516020818303038152906040528051906020012061253f565b86868661256c565b905061199c8b828c8c8c8c8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508e92506123bb915050565b9b9a5050505050505050505050565b604080517f150214d74d59b7d1e90c73fc22ef3d991dd0a76b046543d4d80ab92d2a50328f602082015290810187905260ff8516606082015260009081906119f99061194d90608001611932565b90506117d0888289896040518060200160405280600081525061251b565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03163303611a56575060131936013560601c90565b503390565b60006001600160401b03821115611ac35760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203660448201526534206269747360d01b6064820152608401610a8b565b5090565b60606000611ad483612594565b60010190506000816001600160401b03811115611af357611af36135b0565b6040519080825280601f01601f191660200182016040528015611b1d576020820181803683370190505b5090508181016020015b600019016f181899199a1a9b1b9c1cb0b131b232b360811b600a86061a8153600a8504945084611b2757509392505050565b60405161f8e560ef1b81526004810184905260009081906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690637c72800090602401602060405180830381865afa158015611bc1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611be59190614315565b90506002816002811115611bfb57611bfb613a9d565b03611c575760405162461bcd60e51b815260206004820152602660248201527f45706f6368476f7665726e6f723a206d616e61676564206e66742063616e6e6f6044820152657420766f746560d01b6064820152608401610a8b565b6000816002811115611c6b57611c6b613a9d565b03611d1057604051634d6fb77560e01b81526001600160a01b03878116600483015260248201879052604482018690527f00000000000000000000000000000000000000000000000000000000000000001690634d6fb77590606401602060405180830381865afa158015611ce4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d08919061419c565b915050610f78565b6040516319a0a9d560e01b8152600481018690526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906319a0a9d590602401602060405180830381865afa158015611d78573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d9c919061419c565b90506000611dd46001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016838861266c565b604051631e09967560e31b81526004810184905265ffffffffffff821660248201529091506000906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063f04cb3a890604401608060405180830381865afa158015611e4d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e719190614336565b6060015190508060000361201057604051634d6fb77560e01b81526001600160a01b038a81166004830152602482018a9052604482018990526000917f000000000000000000000000000000000000000000000000000000000000000090911690634d6fb77590606401602060405180830381865afa158015611ef8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f1c919061419c565b60405163145615f560e21b8152600481018b9052602481018690529091506000906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063515857d490604401602060405180830381865afa158015611f8e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fb2919061419c565b90506000611feb6001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016878d8d61295d565b905082611ff88284614007565b6120029190614007565b975050505050505050610f78565b604051634d6fb77560e01b81526001600160a01b038a81166004830152602482018a9052604482018990527f00000000000000000000000000000000000000000000000000000000000000001690634d6fb77590606401602060405180830381865afa158015612084573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120a8919061419c565b9998505050505050505050565b61213b565b8181101561213857306001600160a01b03168682815181106120de576120de613fba565b60200260200101516001600160a01b0316036121285761212884828151811061210957612109613fba565b6020026020010151805190602001206006612f4490919063ffffffff16565b612131816143a1565b90506120ba565b50505b5050505050565b60006040518060600160405280602781526020016144a860279139855190915060005b8181101561223a5760008088838151811061218257612182613fba565b60200260200101516001600160a01b03168884815181106121a5576121a5613fba565b60200260200101518885815181106121bf576121bf613fba565b60200260200101516040516121d491906143ba565b60006040518083038185875af1925050503d8060008114612211576040519150601f19603f3d011682016040523d82523d6000602084013e612216565b606091505b5091509150612226828287612f89565b50505080612233906143a1565b9050612165565b5050505050505050565b6000818152600860205260408120805460018201546002830154818311801561226c57508083115b1561227d5750600395945050505050565b828211801561228b57508082115b1561229c5750600495945050505050565b50600695945050505050565b606060ff8316156122c3576122bc83612fa2565b9050610950565b8180546122cf90613f57565b80601f01602080910402602001604051908101604052809291908181526020018280546122fb90613f57565b80156123485780601f1061231d57610100808354040283529160200191612348565b820191906000526020600020905b81548152906001019060200180831161232b57829003601f168201915b50505050509050610950565b600065ffffffffffff821115611ac35760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203460448201526538206269747360d01b6064820152608401610a8b565b600086815260046020526040812060016123d4896113e1565b60078111156123e5576123e5613a9d565b146124445760405162461bcd60e51b815260206004820152602960248201527f476f7665726e6f7253696d706c653a20766f7465206e6f742063757272656e746044820152686c792061637469766560b81b6064820152608401610a8b565b805460009061246090899089906001600160401b031687611b59565b905061246f8988888488612fd7565b83516000036124c55786886001600160a01b03167f02ecdb7f59712b7ae7cb6851cce1c64e98f94e5b51ec63809112c054622b25548b89858a6040516124b894939291906143d6565b60405180910390a36117d0565b86886001600160a01b03167f7dcdc52e34b09364e599a32b0e3ccb5b730a7b952ddbdf4f237ea785da228ce78b89858a8a6040516125079594939291906143fe565b60405180910390a398975050505050505050565b60006114f1868686868661253a60408051602081019091526000815290565b6123bb565b600061095061254c6131a7565b8360405161190160f01b8152600281019290925260228201526042902090565b600080600061257d878787876132d2565b9150915061258a81613396565b5095945050505050565b60008072184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b83106125d35772184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b830492506040015b6d04ee2d6d415b85acef810000000083106125ff576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc10000831061261d57662386f26fc10000830492506010015b6305f5e1008310612635576305f5e100830492506008015b612710831061264957612710830492506004015b6064831061265b576064830492506002015b600a83106109505760010192915050565b604051635058979360e01b81526004810183905260009081906001600160a01b03861690635058979390602401602060405180830381865afa1580156126b6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126da9190614292565b90508065ffffffffffff166000036126f6576000915050610f68565b826001600160a01b03861663f04cb3a886612712600186614438565b6040516001600160e01b031960e085901b168152600481019290925265ffffffffffff166024820152604401608060405180830381865afa15801561275b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061277f9190614336565b511161279857612790600182614438565b915050610f68565b604051631e09967560e31b8152600481018590526000602482015283906001600160a01b0387169063f04cb3a890604401608060405180830381865afa1580156127e6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061280a9190614336565b51111561281b576000915050610f68565b600080612829600184614438565b905061285f60405180608001604052806000815260200160006001600160a01b0316815260200160008152602001600081525090565b8265ffffffffffff168265ffffffffffff16111561295157600060026128858585614438565b61288f919061445e565b6128999084614438565b604051631e09967560e31b8152600481018a905265ffffffffffff821660248201529091506001600160a01b038a169063f04cb3a890604401608060405180830381865afa1580156128ef573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129139190614336565b91508682600001510361292c579450610f689350505050565b815187111561293d5780935061294b565b612948600182614438565b92505b5061285f565b50909695505050505050565b60405163539c6d4160e11b81526004810184905260009081906001600160a01b0387169063a738da8290602401602060405180830381865afa1580156129a7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129cb919061417f565b604051635058979360e01b8152600481018690529091506001600160a01b03821690635058979390602401602060405180830381865afa158015612a13573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a37919061419c565b600003612a48576000915050610f78565b6000866001600160a01b031663fc0c546a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612a88573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612aac919061417f565b60405163f25e55a560e01b81526001600160a01b038083166004830152602482018890529192506000916001918391612b38919087169063f25e55a590604401602060405180830381865afa158015612b09573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b2d919061419c565b62093a808106900390565b6040516328a3532760e21b8152600481018a9052602481018290529091506000906001600160a01b0387169063a28d4c9c90604401602060405180830381865afa158015612b8a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612bae919061419c565b604051631277308160e21b8152600481018b90526024810182905290915060009081906001600160a01b038916906349dcc204906044016040805180830381865afa158015612c01573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c259190614483565b9092509050612c3b8462093a80840684036134e3565b9350600062093a80612c5386828e068e038301613fa7565b612c5d91906141e2565b905060008115612f315760005b82811015612f2f576001600160a01b038b1663a28d4c9c8f6001612c9162093a808c614007565b612c9b9190613fa7565b6040516001600160e01b031960e085901b16815260048101929092526024820152604401602060405180830381865afa158015612cdc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d00919061419c565b95508a6001600160a01b03166349dcc2048f886040518363ffffffff1660e01b8152600401612d39929190918252602082015260400190565b6040805180830381865afa158015612d55573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d799190614483565b90955093506001600160a01b038b1663f7412baf816376f4be366001612da262093a808d614007565b612dac9190613fa7565b6040518263ffffffff1660e01b8152600401612dca91815260200190565b602060405180830381865afa158015612de7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e0b919061419c565b6040518263ffffffff1660e01b8152600401612e2991815260200190565b6040805180830381865afa158015612e45573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e699190614483565b9250612e7890508260016134e3565b6040516392777b2960e01b81526001600160a01b038c81166004830152602482018a905291995089918d16906392777b2990604401602060405180830381865afa158015612eca573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612eee919061419c565b612ef890866141b5565b612f0291906141e2565b612f0c908a614007565b9850612f1b62093a8088614007565b965080612f27816143a1565b915050612c6a565b505b50959d9c50505050505050505050505050565b8154600160801b90819004600f0b6000818152600180860160205260409091209390935583546fffffffffffffffffffffffffffffffff908116939091011602179055565b60608315612f98575081610f68565b610f6883836134f9565b60408051602080825281830190925260609160ff84169160009180820181803683375050509182525060208101929092525090565b6000858152600860209081526040808320878452600381019092529091205460ff16156130565760405162461bcd60e51b815260206004820152602760248201527f476f7665726e6f72566f74696e6753696d706c653a20766f746520616c726561604482015266191e4818d85cdd60ca1b6064820152608401610a8b565b600083116130b75760405162461bcd60e51b815260206004820152602860248201527f476f7665726e6f72566f74696e6753696d706c653a207a65726f20766f74696e60448201526719c81dd95a59da1d60c21b6064820152608401610a8b565b60008581526003820160205260409020805460ff1916600117905560ff84166130f957828160000160008282546130ee9190614007565b9091555061319f9050565b60001960ff85160161311957828160010160008282546130ee9190614007565b60011960ff85160161313957828160020160008282546130ee9190614007565b60405162461bcd60e51b815260206004820152603560248201527f476f7665726e6f72566f74696e6753696d706c653a20696e76616c69642076616044820152746c756520666f7220656e756d20566f74655479706560581b6064820152608401610a8b565b505050505050565b6000306001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614801561320057507f000000000000000000000000000000000000000000000000000000000000000046145b1561322a57507f000000000000000000000000000000000000000000000000000000000000000090565b6116ce604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60208201527f0000000000000000000000000000000000000000000000000000000000000000918101919091527f000000000000000000000000000000000000000000000000000000000000000060608201524660808201523060a082015260009060c00160405160208183030381529060405280519060200120905090565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0831115613309575060009050600361338d565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa15801561335d573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166133865760006001925092505061338d565b9150600090505b94509492505050565b60008160048111156133aa576133aa613a9d565b036133b25750565b60018160048111156133c6576133c6613a9d565b036134135760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e617475726500000000000000006044820152606401610a8b565b600281600481111561342757613427613a9d565b036134745760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152606401610a8b565b600381600481111561348857613488613a9d565b036134e05760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b6064820152608401610a8b565b50565b60008183116134f25781610f68565b5090919050565b8151156135095781518083602001fd5b8060405162461bcd60e51b8152600401610a8b919061359d565b60006020828403121561353557600080fd5b81356001600160e01b031981168114610f6857600080fd5b60005b83811015613568578181015183820152602001613550565b50506000910152565b6000815180845261358981602086016020860161354d565b601f01601f19169290920160200192915050565b602081526000610f686020830184613571565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b03811182821017156135ee576135ee6135b0565b604052919050565b60006001600160401b0382111561360f5761360f6135b0565b5060051b60200190565b6001600160a01b03811681146134e057600080fd5b600082601f83011261363f57600080fd5b8135602061365461364f836135f6565b6135c6565b82815260059290921b8401810191818101908684111561367357600080fd5b8286015b848110156110c357803561368a81613619565b8352918301918301613677565b600082601f8301126136a857600080fd5b813560206136b861364f836135f6565b82815260059290921b840181019181810190868411156136d757600080fd5b8286015b848110156110c357803583529183019183016136db565b60006001600160401b0382111561370b5761370b6135b0565b50601f01601f191660200190565b600061372761364f846136f2565b905082815283838301111561373b57600080fd5b828260208301376000602084830101529392505050565b600082601f83011261376357600080fd5b610f6883833560208501613719565b600082601f83011261378357600080fd5b8135602061379361364f836135f6565b82815260059290921b840181019181810190868411156137b257600080fd5b8286015b848110156110c35780356001600160401b038111156137d55760008081fd5b6137e38986838b0101613752565b8452509183019183016137b6565b600080600080600060a0868803121561380957600080fd5b8535945060208601356001600160401b038082111561382757600080fd5b61383389838a0161362e565b9550604088013591508082111561384957600080fd5b61385589838a01613697565b9450606088013591508082111561386b57600080fd5b61387789838a01613772565b9350608088013591508082111561388d57600080fd5b508601601f8101881361389f57600080fd5b6138ae88823560208401613719565b9150509295509295909350565b6000806000606084860312156138d057600080fd5b83356138db81613619565b95602085013595506040909401359392505050565b6000806000806080858703121561390657600080fd5b843561391181613619565b9350602085013561392181613619565b92506040850135915060608501356001600160401b0381111561394357600080fd5b61394f87828801613752565b91505092959194509250565b6000806000806080858703121561397157600080fd5b84356001600160401b038082111561398857600080fd5b6139948883890161362e565b955060208701359150808211156139aa57600080fd5b6139b688838901613697565b945060408701359150808211156139cc57600080fd5b506139d987828801613772565b949793965093946060013593505050565b6000602082840312156139fc57600080fd5b5035919050565b60008083601f840112613a1557600080fd5b5081356001600160401b03811115613a2c57600080fd5b602083019150836020828501011115613a4457600080fd5b9250929050565b60008060008060608587031215613a6157600080fd5b843593506020850135925060408501356001600160401b03811115613a8557600080fd5b613a9187828801613a03565b95989497509550505050565b634e487b7160e01b600052602160045260246000fd5b6020810160088310613ad557634e487b7160e01b600052602160045260246000fd5b91905290565b600060208284031215613aed57600080fd5b8135610f6881613619565b60008060408385031215613b0b57600080fd5b50508035926020909101359150565b600081518084526020808501945080840160005b83811015613b4a57815187529582019590820190600101613b2e565b509495945050505050565b60ff60f81b8816815260e060208201526000613b7460e0830189613571565b8281036040840152613b868189613571565b606084018890526001600160a01b038716608085015260a0840186905283810360c08501529050613bb78185613b1a565b9a9950505050505050505050565b600080600080600060a08688031215613bdd57600080fd5b8535613be881613619565b94506020860135613bf881613619565b935060408601356001600160401b0380821115613c1457600080fd5b613c2089838a01613697565b94506060880135915080821115613c3657600080fd5b613c4289838a01613697565b93506080880135915080821115613c5857600080fd5b506138ae88828901613752565b803560ff811681146115b857600080fd5b60008060008060008060a08789031215613c8f57600080fd5b8635955060208701359450613ca660408801613c65565b935060608701356001600160401b0380821115613cc257600080fd5b613cce8a838b01613a03565b90955093506080890135915080821115613ce757600080fd5b50613cf489828a01613752565b9150509295509295509295565b600080600080600060808688031215613d1957600080fd5b8535945060208601359350613d3060408701613c65565b925060608601356001600160401b03811115613d4b57600080fd5b613d5788828901613a03565b969995985093965092949392505050565b60008060008060808587031215613d7e57600080fd5b8435613d8981613619565b9350602085013592506040850135915060608501356001600160401b0381111561394357600080fd5b600080600060608486031215613dc757600080fd5b8335925060208401359150613dde60408501613c65565b90509250925092565b600080600080600060a08688031215613dff57600080fd5b8535613e0a81613619565b94506020860135613e1a81613619565b9350604086013592506060860135915060808601356001600160401b03811115613e4357600080fd5b6138ae88828901613752565b60008060008060008060008060006101008a8c031215613e6e57600080fd5b8935985060208a01359750613e8560408b01613c65565b965060608a01356001600160401b0380821115613ea157600080fd5b613ead8d838e01613a03565b909850965060808c0135915080821115613ec657600080fd5b50613ed38c828d01613752565b945050613ee260a08b01613c65565b925060c08a0135915060e08a013590509295985092959850929598565b60008060008060008060c08789031215613f1857600080fd5b8635955060208701359450613f2f60408801613c65565b9350613f3d60608801613c65565b92506080870135915060a087013590509295509295509295565b600181811c90821680613f6b57607f821691505b602082108103613f8b57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b8181038181111561095057610950613f91565b634e487b7160e01b600052603260045260246000fd5b805160208201516001600160e01b03198082169291906004831015613fff5780818460040360031b1b83161693505b505050919050565b8082018082111561095057610950613f91565b600081518084526020808501945080840160005b83811015613b4a5781516001600160a01b03168752958201959082019060010161402e565b600081518084526020808501808196508360051b8101915082860160005b8581101561409b578284038952614089848351613571565b98850198935090840190600101614071565b5091979650505050505050565b60006101208b8352602060018060a01b038c16818501528160408501526140d18285018c61401a565b915083820360608501526140e5828b613b1a565b915083820360808501528189518084528284019150828160051b850101838c0160005b8381101561413657601f19878403018552614124838351613571565b94860194925090850190600101614108565b505086810360a088015261414a818c614053565b9450505050508560c08401528460e084015282810361010084015261416f8185613571565b9c9b505050505050505050505050565b60006020828403121561419157600080fd5b8151610f6881613619565b6000602082840312156141ae57600080fd5b5051919050565b808202811582820484141761095057610950613f91565b634e487b7160e01b600052601260045260246000fd5b6000826141f1576141f16141cc565b500490565b60208152816020820152818360408301376000818301604090810191909152601f909201601f19160101919050565b60006020828403121561423757600080fd5b81516001600160401b0381111561424d57600080fd5b8201601f8101841361425e57600080fd5b805161426c61364f826136f2565b81815285602083850101111561428157600080fd5b61187f82602083016020860161354d565b6000602082840312156142a457600080fd5b815165ffffffffffff81168114610f6857600080fd5b6080815260006142cd608083018761401a565b82810360208401526142df8187613b1a565b905082810360408401526142f38186614053565b91505082606083015295945050505050565b8183823760009101908152919050565b60006020828403121561432757600080fd5b815160038110610f6857600080fd5b60006080828403121561434857600080fd5b604051608081018181106001600160401b038211171561436a5761436a6135b0565b60405282518152602083015161437f81613619565b6020820152604083810151908201526060928301519281019290925250919050565b6000600182016143b3576143b3613f91565b5060010190565b600082516143cc81846020870161354d565b9190910192915050565b84815260ff841660208201528260408201526080606082015260006114f16080830184613571565b85815260ff8516602082015283604082015260a06060820152600061442660a0830185613571565b82810360808401526117d08185613571565b65ffffffffffff82811682821603908082111561445757614457613f91565b5092915050565b600065ffffffffffff80841680614477576144776141cc565b92169190910492915050565b6000806040838503121561449657600080fd5b50508051602090910151909290915056fe476f7665726e6f723a2063616c6c20726576657274656420776974686f7574206d657373616765a2646970667358221220de5fbeae0865b340cd002d902c2bcbae7c1a17f105f3f25584f33913f9a1d04164736f6c6343000813003300000000000000000000000019f7c4cfa2cccfaff16f66fb92f4c5d1f3fa9a57000000000000000000000000c4e6a85630ca1d9b754518f653cb43c3f768215b000000000000000000000000ee75b6685611396359d339434b1df012f5c82ba7000000000000000000000000612c5dc0256b8da00bfd6b2b8f711e24b0509044
Deployed Bytecode
0x60806040526004361061023f5760003560e01c806364390ff11161012e578063c59057e4116100ab578063e2fdcc171161006f578063e2fdcc1714610815578063f23a6e6114610849578063f945970a14610875578063fa25f37714610895578063fc0c546a146108b557600080fd5b8063c59057e41461073b578063cf781d451461075b578063dd4e2ba51461077b578063dea112a6146107c1578063deaaa7cc146107e157600080fd5b8063b58131b0116100f2578063b58131b014610682578063bc197c8114610696578063be443ad0146106c2578063c01f9e37146106e2578063c2e863e41461071b57600080fd5b806364390ff1146105b557806365372147146105f457806384b0196e1461060e57806391ddadf41461063657806391f366331461066257600080fd5b80632d63f693116101bc5780633e4f49e6116101805780633e4f49e6146104a75780634bf5d7e9146104d4578063544ffc9c146104e957806354fd4d501461053e578063572b6c051461056857600080fd5b80632d63f693146103d45780632fe3e2611461040a578063380a243a1461043e5780633932abb11461045e5780633db9b42a1461047357600080fd5b806311fd26f41161020357806311fd26f41461031c578063150b7a021461033c5780631f8507161461037557806322b36ac6146103a95780632656227d146103c157600080fd5b806301ffc9a71461024d57806302a251a31461028257806306fdde03146102a257806307546172146102c45780630f8a8836146102fc57600080fd5b3661024857005b005b600080fd5b34801561025957600080fd5b5061026d610268366004613523565b6108e9565b60405190151581526020015b60405180910390f35b34801561028e57600080fd5b5062093a805b604051908152602001610279565b3480156102ae57600080fd5b506102b7610956565b604051610279919061359d565b3480156102d057600080fd5b506003546102e4906001600160a01b031681565b6040516001600160a01b039091168152602001610279565b34801561030857600080fd5b506102946103173660046137f1565b6109e8565b34801561032857600080fd5b506102946103373660046138bb565b610f43565b34801561034857600080fd5b5061035c6103573660046138f0565b610f6f565b6040516001600160e01b03199091168152602001610279565b34801561038157600080fd5b506102e47f000000000000000000000000c4e6a85630ca1d9b754518f653cb43c3f768215b81565b3480156103b557600080fd5b50610294633b9aca0081565b6102946103cf36600461395b565b610f80565b3480156103e057600080fd5b506102946103ef3660046139ea565b6000908152600460205260409020546001600160401b031690565b34801561041657600080fd5b506102947fb3b3f3b703cd84ce352197dcff232b1b5d3cfb2025ce47cf04742d0651f1af8881565b34801561044a57600080fd5b50610246610459366004613a4b565b6110ce565b34801561046a57600080fd5b50610384610294565b34801561047f57600080fd5b506102e47f000000000000000000000000612c5dc0256b8da00bfd6b2b8f711e24b050904481565b3480156104b357600080fd5b506104c76104c23660046139ea565b6113e1565b6040516102799190613ab3565b3480156104e057600080fd5b506102b76114fb565b3480156104f557600080fd5b506105236105043660046139ea565b6000908152600860205260409020805460018201546002909201549092565b60408051938452602084019290925290820152606001610279565b34801561054a57600080fd5b506040805180820190915260018152603160f81b60208201526102b7565b34801561057457600080fd5b5061026d610583366004613adb565b7f00000000000000000000000019f7c4cfa2cccfaff16f66fb92f4c5d1f3fa9a576001600160a01b0390811691161490565b3480156105c157600080fd5b5061026d6105d0366004613af8565b60009182526008602090815260408084209284526003909201905290205460ff1690565b34801561060057600080fd5b506005546104c79060ff1681565b34801561061a57600080fd5b506106236115bd565b6040516102799796959493929190613b55565b34801561064257600080fd5b5061064b611645565b60405165ffffffffffff9091168152602001610279565b34801561066e57600080fd5b5061029461067d366004613af8565b6116d3565b34801561068e57600080fd5b506000610294565b3480156106a257600080fd5b5061035c6106b1366004613bc5565b63bc197c8160e01b95945050505050565b3480156106ce57600080fd5b506102946106dd366004613c76565b61177e565b3480156106ee57600080fd5b506102946106fd3660046139ea565b6000908152600460205260409020600101546001600160401b031690565b34801561072757600080fd5b50610294610736366004613d01565b6117dc565b34801561074757600080fd5b5061029461075636600461395b565b611837565b34801561076757600080fd5b50610294610776366004613d68565b611871565b34801561078757600080fd5b506040805180820190915260208082527f737570706f72743d627261766f2671756f72756d3d666f722c6162737461696e908201526102b7565b3480156107cd57600080fd5b506102946107dc366004613db2565b611888565b3480156107ed57600080fd5b506102947f150214d74d59b7d1e90c73fc22ef3d991dd0a76b046543d4d80ab92d2a50328f81565b34801561082157600080fd5b506102e47f000000000000000000000000c4e6a85630ca1d9b754518f653cb43c3f768215b81565b34801561085557600080fd5b5061035c610864366004613de7565b63f23a6e6160e01b95945050505050565b34801561088157600080fd5b50610294610890366004613e4f565b6118b1565b3480156108a157600080fd5b506102946108b0366004613eff565b6119ab565b3480156108c157600080fd5b506102e47f000000000000000000000000c4e6a85630ca1d9b754518f653cb43c3f768215b81565b60006001600160e01b03198216632003110360e01b148061091a57506001600160e01b03198216632a1ea86760e21b145b8061093557506001600160e01b03198216630271189760e51b145b8061095057506301ffc9a760e01b6001600160e01b03198316145b92915050565b60606002805461096590613f57565b80601f016020809104026020016040519081016040528092919081815260200182805461099190613f57565b80156109de5780601f106109b3576101008083540402835291602001916109de565b820191906000526020600020905b8154815290600101906020018083116109c157829003601f168201915b5050505050905090565b6000806109f3611a17565b905060006109ff611645565b65ffffffffffff1690506000610a1b838a610337600186613fa7565b1015610a945760405162461bcd60e51b815260206004820152603760248201527f476f7665726e6f7253696d706c653a2070726f706f73657220766f746573206260448201527f656c6f772070726f706f73616c207468726573686f6c6400000000000000000060648201526084015b60405180910390fd5b8651600114610af55760405162461bcd60e51b815260206004820152602760248201527f476f7665726e6f7253696d706c653a206f6e6c79206f6e652074617267657420604482015266185b1b1bddd95960ca1b6064820152608401610a8b565b60035487516001600160a01b03909116908890600090610b1757610b17613fba565b60200260200101516001600160a01b031614610b815760405162461bcd60e51b815260206004820152602360248201527f476f7665726e6f7253696d706c653a206f6e6c79206d696e74657220616c6c6f6044820152621dd95960ea1b6064820152608401610a8b565b8451600114610be45760405162461bcd60e51b815260206004820152602960248201527f476f7665726e6f7253696d706c653a206f6e6c79206f6e652063616c6c6461746044820152681848185b1b1bddd95960ba1b6064820152608401610a8b565b8451634804532160e11b908690600090610c0057610c00613fba565b6020026020010151610c1190613fd0565b6001600160e01b03191614610c735760405162461bcd60e51b815260206004820152602260248201527f476f7665726e6f7253696d706c653a206f6e6c79206e7564676520616c6c6f77604482015261195960f21b6064820152608401610a8b565b6000610c844262093a808106900390565b610c919062093a80614007565b90506000610ca189898985611837565b90506000895111610cf45760405162461bcd60e51b815260206004820152601e60248201527f476f7665726e6f7253696d706c653a20656d7074792070726f706f73616c00006044820152606401610a8b565b600081815260046020526040902054600160401b90046001600160a01b031615610d705760405162461bcd60e51b815260206004820152602760248201527f476f7665726e6f7253696d706c653a2070726f706f73616c20616c72656164796044820152662065786973747360c81b6064820152608401610a8b565b6000610d7e61038485614007565b90506000610d8f62093a8083614007565b90506040518060e00160405280610da584611a5b565b6001600160401b031681526001600160a01b038816602082015260006040820152606001610dd283611a5b565b6001600160401b039081168252600060208084018290526040808501839052606094850183905288835260048252918290208551815492870151878501519186166001600160e01b031990941693909317600160401b6001600160a01b039094168402176001600160e01b0316600160e01b60e09290921c91909102178155938501516080860151908416921c0217600183015560a08301516002909201805460c09094015161ffff1990941692151561ff00191692909217610100931515939093029290921790558b517f7d84a6263ae0d98d3329bd7b46bb4e8d6f98cd35a7adb45c274c8b7fd5ebd5e091859189918f918f91811115610ed657610ed66135b0565b604051908082528060200260200182016040528015610f0957816020015b6060815260200190600190039081610ef45790505b508e8888610f168d611ac7565b604051610f2b999897969594939291906140a8565b60405180910390a150909a9950505050505050505050565b6000610f65848484610f6060408051602081019091526000815290565b611b59565b90505b9392505050565b630a85bd0160e11b5b949350505050565b600080610f924262093a808106900390565b90506000610fa287878785611837565b90506000610faf826113e1565b90506004816007811115610fc557610fc5613a9d565b146110225760405162461bcd60e51b815260206004820152602760248201527f476f7665726e6f7253696d706c653a2070726f706f73616c206e6f742073756360448201526618d95cdcd99d5b60ca1b6064820152608401610a8b565b60008281526004602052604090819020600201805460ff19166001179055517f712ae1383f79ac853f8d882153778e0260ef8f03b504e2866e0593e04d2b291f906110709084815260200190565b60405180910390a16005805482919060ff1916600183600781111561109757611097613a9d565b02179055506110a982898989896120b5565b6110b68289898989612142565b6110c382898989896120b5565b509695505050505050565b60008481526004602052604081206060916110e8876113e1565b905060018160078111156110fe576110fe613a9d565b148061111b5750600081600781111561111957611119613a9d565b145b6111735760405162461bcd60e51b8152602060048201526024808201527f45706f6368476f7665726e6f723a206e6f7420616374697665206f722070656e60448201526364696e6760e01b6064820152608401610a8b565b81546001600160401b03166000611188611a17565b90506000611198828a8589611b59565b905060007f000000000000000000000000612c5dc0256b8da00bfd6b2b8f711e24b05090446001600160a01b0316630c340a246040518163ffffffff1660e01b8152600401602060405180830381865afa1580156111fa573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061121e919061417f565b6001600160a01b031663525f9c3e6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561125b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061127f919061419c565b90506000633b9aca00827f000000000000000000000000c4e6a85630ca1d9b754518f653cb43c3f768215b6001600160a01b0316638e539e8c886040518263ffffffff1660e01b81526004016112d791815260200190565b602060405180830381865afa1580156112f4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611318919061419c565b61132291906141b5565b61132c91906141e2565b905080831161138e5760405162461bcd60e51b815260206004820152602860248201527f45706f6368476f7665726e6f723a20696e73756666696369656e7420766f74696044820152673733903837bbb2b960c11b6064820152608401610a8b565b8a846001600160a01b03168d7fdb700dee4c69422ecdfd4ad68ffe25aa39c6ddffef4657f727571e095b642cc58d8d6040516113cb9291906141f6565b60405180910390a4505050505050505050505050565b6000818152600460205260408120600281015460ff16156114055750600792915050565b6002810154610100900460ff16156114205750600292915050565b6000838152600460205260408120546001600160401b0316908190036114945760405162461bcd60e51b815260206004820152602360248201527f476f7665726e6f7253696d706c653a20756e6b6e6f776e2070726f706f73616c604482015262081a5960ea1b6064820152608401610a8b565b600061149e611645565b65ffffffffffff1690508082106114ba57506000949350505050565b6000858152600460205260409020600101546001600160401b03168181106114e85750600195945050505050565b6114f186612244565b9695505050505050565b60607f000000000000000000000000c4e6a85630ca1d9b754518f653cb43c3f768215b6001600160a01b0316634bf5d7e96040518163ffffffff1660e01b8152600401600060405180830381865afa92505050801561157c57506040513d6000823e601f3d908101601f191682016040526115799190810190614225565b60015b6115b8575060408051808201909152601d81527f6d6f64653d626c6f636b6e756d6265722666726f6d3d64656661756c74000000602082015290565b919050565b6000606080828080836115f07f45706f636820476f7665726e6f7200000000000000000000000000000000000e836122a8565b61161b7f310000000000000000000000000000000000000000000000000000000000000160016122a8565b60408051600080825260208201909252600f60f81b9b939a50919850469750309650945092509050565b60007f000000000000000000000000c4e6a85630ca1d9b754518f653cb43c3f768215b6001600160a01b03166391ddadf46040518163ffffffff1660e01b8152600401602060405180830381865afa9250505080156116c1575060408051601f3d908101601f191682019092526116be91810190614292565b60015b6115b8576116ce43612354565b905090565b6040516331a9108f60e11b81526004810183905260009081906001600160a01b037f000000000000000000000000c4e6a85630ca1d9b754518f653cb43c3f768215b1690636352211e90602401602060405180830381865afa15801561173d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611761919061417f565b9050610f7881858560405180602001604052806000815250611b59565b600080611789611a17565b90506117d08882898989898080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508b92506123bb915050565b98975050505050505050565b6000806117e7611a17565b905061182c8782888888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061251b92505050565b979650505050505050565b60008484848460405160200161185094939291906142ba565b60408051601f19818403018152919052805160209091012095945050505050565b600061187f85858585611b59565b95945050505050565b600080611893611a17565b905061187f858286866040518060200160405280600081525061251b565b60008061195561194d7fb3b3f3b703cd84ce352197dcff232b1b5d3cfb2025ce47cf04742d0651f1af888d8c8c8c6040516118ed929190614305565b60405180910390208b80519060200120604051602001611932959493929190948552602085019390935260ff9190911660408401526060830152608082015260a00190565b6040516020818303038152906040528051906020012061253f565b86868661256c565b905061199c8b828c8c8c8c8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508e92506123bb915050565b9b9a5050505050505050505050565b604080517f150214d74d59b7d1e90c73fc22ef3d991dd0a76b046543d4d80ab92d2a50328f602082015290810187905260ff8516606082015260009081906119f99061194d90608001611932565b90506117d0888289896040518060200160405280600081525061251b565b60007f00000000000000000000000019f7c4cfa2cccfaff16f66fb92f4c5d1f3fa9a576001600160a01b03163303611a56575060131936013560601c90565b503390565b60006001600160401b03821115611ac35760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203660448201526534206269747360d01b6064820152608401610a8b565b5090565b60606000611ad483612594565b60010190506000816001600160401b03811115611af357611af36135b0565b6040519080825280601f01601f191660200182016040528015611b1d576020820181803683370190505b5090508181016020015b600019016f181899199a1a9b1b9c1cb0b131b232b360811b600a86061a8153600a8504945084611b2757509392505050565b60405161f8e560ef1b81526004810184905260009081906001600160a01b037f000000000000000000000000c4e6a85630ca1d9b754518f653cb43c3f768215b1690637c72800090602401602060405180830381865afa158015611bc1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611be59190614315565b90506002816002811115611bfb57611bfb613a9d565b03611c575760405162461bcd60e51b815260206004820152602660248201527f45706f6368476f7665726e6f723a206d616e61676564206e66742063616e6e6f6044820152657420766f746560d01b6064820152608401610a8b565b6000816002811115611c6b57611c6b613a9d565b03611d1057604051634d6fb77560e01b81526001600160a01b03878116600483015260248201879052604482018690527f000000000000000000000000c4e6a85630ca1d9b754518f653cb43c3f768215b1690634d6fb77590606401602060405180830381865afa158015611ce4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d08919061419c565b915050610f78565b6040516319a0a9d560e01b8152600481018690526000907f000000000000000000000000c4e6a85630ca1d9b754518f653cb43c3f768215b6001600160a01b0316906319a0a9d590602401602060405180830381865afa158015611d78573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d9c919061419c565b90506000611dd46001600160a01b037f000000000000000000000000c4e6a85630ca1d9b754518f653cb43c3f768215b16838861266c565b604051631e09967560e31b81526004810184905265ffffffffffff821660248201529091506000906001600160a01b037f000000000000000000000000c4e6a85630ca1d9b754518f653cb43c3f768215b169063f04cb3a890604401608060405180830381865afa158015611e4d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e719190614336565b6060015190508060000361201057604051634d6fb77560e01b81526001600160a01b038a81166004830152602482018a9052604482018990526000917f000000000000000000000000c4e6a85630ca1d9b754518f653cb43c3f768215b90911690634d6fb77590606401602060405180830381865afa158015611ef8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f1c919061419c565b60405163145615f560e21b8152600481018b9052602481018690529091506000906001600160a01b037f000000000000000000000000c4e6a85630ca1d9b754518f653cb43c3f768215b169063515857d490604401602060405180830381865afa158015611f8e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fb2919061419c565b90506000611feb6001600160a01b037f000000000000000000000000c4e6a85630ca1d9b754518f653cb43c3f768215b16878d8d61295d565b905082611ff88284614007565b6120029190614007565b975050505050505050610f78565b604051634d6fb77560e01b81526001600160a01b038a81166004830152602482018a9052604482018990527f000000000000000000000000c4e6a85630ca1d9b754518f653cb43c3f768215b1690634d6fb77590606401602060405180830381865afa158015612084573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120a8919061419c565b9998505050505050505050565b61213b565b8181101561213857306001600160a01b03168682815181106120de576120de613fba565b60200260200101516001600160a01b0316036121285761212884828151811061210957612109613fba565b6020026020010151805190602001206006612f4490919063ffffffff16565b612131816143a1565b90506120ba565b50505b5050505050565b60006040518060600160405280602781526020016144a860279139855190915060005b8181101561223a5760008088838151811061218257612182613fba565b60200260200101516001600160a01b03168884815181106121a5576121a5613fba565b60200260200101518885815181106121bf576121bf613fba565b60200260200101516040516121d491906143ba565b60006040518083038185875af1925050503d8060008114612211576040519150601f19603f3d011682016040523d82523d6000602084013e612216565b606091505b5091509150612226828287612f89565b50505080612233906143a1565b9050612165565b5050505050505050565b6000818152600860205260408120805460018201546002830154818311801561226c57508083115b1561227d5750600395945050505050565b828211801561228b57508082115b1561229c5750600495945050505050565b50600695945050505050565b606060ff8316156122c3576122bc83612fa2565b9050610950565b8180546122cf90613f57565b80601f01602080910402602001604051908101604052809291908181526020018280546122fb90613f57565b80156123485780601f1061231d57610100808354040283529160200191612348565b820191906000526020600020905b81548152906001019060200180831161232b57829003601f168201915b50505050509050610950565b600065ffffffffffff821115611ac35760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203460448201526538206269747360d01b6064820152608401610a8b565b600086815260046020526040812060016123d4896113e1565b60078111156123e5576123e5613a9d565b146124445760405162461bcd60e51b815260206004820152602960248201527f476f7665726e6f7253696d706c653a20766f7465206e6f742063757272656e746044820152686c792061637469766560b81b6064820152608401610a8b565b805460009061246090899089906001600160401b031687611b59565b905061246f8988888488612fd7565b83516000036124c55786886001600160a01b03167f02ecdb7f59712b7ae7cb6851cce1c64e98f94e5b51ec63809112c054622b25548b89858a6040516124b894939291906143d6565b60405180910390a36117d0565b86886001600160a01b03167f7dcdc52e34b09364e599a32b0e3ccb5b730a7b952ddbdf4f237ea785da228ce78b89858a8a6040516125079594939291906143fe565b60405180910390a398975050505050505050565b60006114f1868686868661253a60408051602081019091526000815290565b6123bb565b600061095061254c6131a7565b8360405161190160f01b8152600281019290925260228201526042902090565b600080600061257d878787876132d2565b9150915061258a81613396565b5095945050505050565b60008072184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b83106125d35772184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b830492506040015b6d04ee2d6d415b85acef810000000083106125ff576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc10000831061261d57662386f26fc10000830492506010015b6305f5e1008310612635576305f5e100830492506008015b612710831061264957612710830492506004015b6064831061265b576064830492506002015b600a83106109505760010192915050565b604051635058979360e01b81526004810183905260009081906001600160a01b03861690635058979390602401602060405180830381865afa1580156126b6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126da9190614292565b90508065ffffffffffff166000036126f6576000915050610f68565b826001600160a01b03861663f04cb3a886612712600186614438565b6040516001600160e01b031960e085901b168152600481019290925265ffffffffffff166024820152604401608060405180830381865afa15801561275b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061277f9190614336565b511161279857612790600182614438565b915050610f68565b604051631e09967560e31b8152600481018590526000602482015283906001600160a01b0387169063f04cb3a890604401608060405180830381865afa1580156127e6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061280a9190614336565b51111561281b576000915050610f68565b600080612829600184614438565b905061285f60405180608001604052806000815260200160006001600160a01b0316815260200160008152602001600081525090565b8265ffffffffffff168265ffffffffffff16111561295157600060026128858585614438565b61288f919061445e565b6128999084614438565b604051631e09967560e31b8152600481018a905265ffffffffffff821660248201529091506001600160a01b038a169063f04cb3a890604401608060405180830381865afa1580156128ef573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129139190614336565b91508682600001510361292c579450610f689350505050565b815187111561293d5780935061294b565b612948600182614438565b92505b5061285f565b50909695505050505050565b60405163539c6d4160e11b81526004810184905260009081906001600160a01b0387169063a738da8290602401602060405180830381865afa1580156129a7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129cb919061417f565b604051635058979360e01b8152600481018690529091506001600160a01b03821690635058979390602401602060405180830381865afa158015612a13573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a37919061419c565b600003612a48576000915050610f78565b6000866001600160a01b031663fc0c546a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612a88573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612aac919061417f565b60405163f25e55a560e01b81526001600160a01b038083166004830152602482018890529192506000916001918391612b38919087169063f25e55a590604401602060405180830381865afa158015612b09573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b2d919061419c565b62093a808106900390565b6040516328a3532760e21b8152600481018a9052602481018290529091506000906001600160a01b0387169063a28d4c9c90604401602060405180830381865afa158015612b8a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612bae919061419c565b604051631277308160e21b8152600481018b90526024810182905290915060009081906001600160a01b038916906349dcc204906044016040805180830381865afa158015612c01573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c259190614483565b9092509050612c3b8462093a80840684036134e3565b9350600062093a80612c5386828e068e038301613fa7565b612c5d91906141e2565b905060008115612f315760005b82811015612f2f576001600160a01b038b1663a28d4c9c8f6001612c9162093a808c614007565b612c9b9190613fa7565b6040516001600160e01b031960e085901b16815260048101929092526024820152604401602060405180830381865afa158015612cdc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d00919061419c565b95508a6001600160a01b03166349dcc2048f886040518363ffffffff1660e01b8152600401612d39929190918252602082015260400190565b6040805180830381865afa158015612d55573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d799190614483565b90955093506001600160a01b038b1663f7412baf816376f4be366001612da262093a808d614007565b612dac9190613fa7565b6040518263ffffffff1660e01b8152600401612dca91815260200190565b602060405180830381865afa158015612de7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e0b919061419c565b6040518263ffffffff1660e01b8152600401612e2991815260200190565b6040805180830381865afa158015612e45573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e699190614483565b9250612e7890508260016134e3565b6040516392777b2960e01b81526001600160a01b038c81166004830152602482018a905291995089918d16906392777b2990604401602060405180830381865afa158015612eca573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612eee919061419c565b612ef890866141b5565b612f0291906141e2565b612f0c908a614007565b9850612f1b62093a8088614007565b965080612f27816143a1565b915050612c6a565b505b50959d9c50505050505050505050505050565b8154600160801b90819004600f0b6000818152600180860160205260409091209390935583546fffffffffffffffffffffffffffffffff908116939091011602179055565b60608315612f98575081610f68565b610f6883836134f9565b60408051602080825281830190925260609160ff84169160009180820181803683375050509182525060208101929092525090565b6000858152600860209081526040808320878452600381019092529091205460ff16156130565760405162461bcd60e51b815260206004820152602760248201527f476f7665726e6f72566f74696e6753696d706c653a20766f746520616c726561604482015266191e4818d85cdd60ca1b6064820152608401610a8b565b600083116130b75760405162461bcd60e51b815260206004820152602860248201527f476f7665726e6f72566f74696e6753696d706c653a207a65726f20766f74696e60448201526719c81dd95a59da1d60c21b6064820152608401610a8b565b60008581526003820160205260409020805460ff1916600117905560ff84166130f957828160000160008282546130ee9190614007565b9091555061319f9050565b60001960ff85160161311957828160010160008282546130ee9190614007565b60011960ff85160161313957828160020160008282546130ee9190614007565b60405162461bcd60e51b815260206004820152603560248201527f476f7665726e6f72566f74696e6753696d706c653a20696e76616c69642076616044820152746c756520666f7220656e756d20566f74655479706560581b6064820152608401610a8b565b505050505050565b6000306001600160a01b037f000000000000000000000000af0cee13d5b09557363c46e352c45f1c00da8acd1614801561320057507f000000000000000000000000000000000000000000000000000000000000078346145b1561322a57507f051e21936829d5277ba3c3ec3ee52903720db388409b60ad4fc549741a90521290565b6116ce604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60208201527fbf876718d0d82eaa723a698e8e06378c9b2a50911c94765909d831e6fc5bccdb918101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260009060c00160405160208183030381529060405280519060200120905090565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0831115613309575060009050600361338d565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa15801561335d573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166133865760006001925092505061338d565b9150600090505b94509492505050565b60008160048111156133aa576133aa613a9d565b036133b25750565b60018160048111156133c6576133c6613a9d565b036134135760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e617475726500000000000000006044820152606401610a8b565b600281600481111561342757613427613a9d565b036134745760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152606401610a8b565b600381600481111561348857613488613a9d565b036134e05760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b6064820152608401610a8b565b50565b60008183116134f25781610f68565b5090919050565b8151156135095781518083602001fd5b8060405162461bcd60e51b8152600401610a8b919061359d565b60006020828403121561353557600080fd5b81356001600160e01b031981168114610f6857600080fd5b60005b83811015613568578181015183820152602001613550565b50506000910152565b6000815180845261358981602086016020860161354d565b601f01601f19169290920160200192915050565b602081526000610f686020830184613571565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b03811182821017156135ee576135ee6135b0565b604052919050565b60006001600160401b0382111561360f5761360f6135b0565b5060051b60200190565b6001600160a01b03811681146134e057600080fd5b600082601f83011261363f57600080fd5b8135602061365461364f836135f6565b6135c6565b82815260059290921b8401810191818101908684111561367357600080fd5b8286015b848110156110c357803561368a81613619565b8352918301918301613677565b600082601f8301126136a857600080fd5b813560206136b861364f836135f6565b82815260059290921b840181019181810190868411156136d757600080fd5b8286015b848110156110c357803583529183019183016136db565b60006001600160401b0382111561370b5761370b6135b0565b50601f01601f191660200190565b600061372761364f846136f2565b905082815283838301111561373b57600080fd5b828260208301376000602084830101529392505050565b600082601f83011261376357600080fd5b610f6883833560208501613719565b600082601f83011261378357600080fd5b8135602061379361364f836135f6565b82815260059290921b840181019181810190868411156137b257600080fd5b8286015b848110156110c35780356001600160401b038111156137d55760008081fd5b6137e38986838b0101613752565b8452509183019183016137b6565b600080600080600060a0868803121561380957600080fd5b8535945060208601356001600160401b038082111561382757600080fd5b61383389838a0161362e565b9550604088013591508082111561384957600080fd5b61385589838a01613697565b9450606088013591508082111561386b57600080fd5b61387789838a01613772565b9350608088013591508082111561388d57600080fd5b508601601f8101881361389f57600080fd5b6138ae88823560208401613719565b9150509295509295909350565b6000806000606084860312156138d057600080fd5b83356138db81613619565b95602085013595506040909401359392505050565b6000806000806080858703121561390657600080fd5b843561391181613619565b9350602085013561392181613619565b92506040850135915060608501356001600160401b0381111561394357600080fd5b61394f87828801613752565b91505092959194509250565b6000806000806080858703121561397157600080fd5b84356001600160401b038082111561398857600080fd5b6139948883890161362e565b955060208701359150808211156139aa57600080fd5b6139b688838901613697565b945060408701359150808211156139cc57600080fd5b506139d987828801613772565b949793965093946060013593505050565b6000602082840312156139fc57600080fd5b5035919050565b60008083601f840112613a1557600080fd5b5081356001600160401b03811115613a2c57600080fd5b602083019150836020828501011115613a4457600080fd5b9250929050565b60008060008060608587031215613a6157600080fd5b843593506020850135925060408501356001600160401b03811115613a8557600080fd5b613a9187828801613a03565b95989497509550505050565b634e487b7160e01b600052602160045260246000fd5b6020810160088310613ad557634e487b7160e01b600052602160045260246000fd5b91905290565b600060208284031215613aed57600080fd5b8135610f6881613619565b60008060408385031215613b0b57600080fd5b50508035926020909101359150565b600081518084526020808501945080840160005b83811015613b4a57815187529582019590820190600101613b2e565b509495945050505050565b60ff60f81b8816815260e060208201526000613b7460e0830189613571565b8281036040840152613b868189613571565b606084018890526001600160a01b038716608085015260a0840186905283810360c08501529050613bb78185613b1a565b9a9950505050505050505050565b600080600080600060a08688031215613bdd57600080fd5b8535613be881613619565b94506020860135613bf881613619565b935060408601356001600160401b0380821115613c1457600080fd5b613c2089838a01613697565b94506060880135915080821115613c3657600080fd5b613c4289838a01613697565b93506080880135915080821115613c5857600080fd5b506138ae88828901613752565b803560ff811681146115b857600080fd5b60008060008060008060a08789031215613c8f57600080fd5b8635955060208701359450613ca660408801613c65565b935060608701356001600160401b0380821115613cc257600080fd5b613cce8a838b01613a03565b90955093506080890135915080821115613ce757600080fd5b50613cf489828a01613752565b9150509295509295509295565b600080600080600060808688031215613d1957600080fd5b8535945060208601359350613d3060408701613c65565b925060608601356001600160401b03811115613d4b57600080fd5b613d5788828901613a03565b969995985093965092949392505050565b60008060008060808587031215613d7e57600080fd5b8435613d8981613619565b9350602085013592506040850135915060608501356001600160401b0381111561394357600080fd5b600080600060608486031215613dc757600080fd5b8335925060208401359150613dde60408501613c65565b90509250925092565b600080600080600060a08688031215613dff57600080fd5b8535613e0a81613619565b94506020860135613e1a81613619565b9350604086013592506060860135915060808601356001600160401b03811115613e4357600080fd5b6138ae88828901613752565b60008060008060008060008060006101008a8c031215613e6e57600080fd5b8935985060208a01359750613e8560408b01613c65565b965060608a01356001600160401b0380821115613ea157600080fd5b613ead8d838e01613a03565b909850965060808c0135915080821115613ec657600080fd5b50613ed38c828d01613752565b945050613ee260a08b01613c65565b925060c08a0135915060e08a013590509295985092959850929598565b60008060008060008060c08789031215613f1857600080fd5b8635955060208701359450613f2f60408801613c65565b9350613f3d60608801613c65565b92506080870135915060a087013590509295509295509295565b600181811c90821680613f6b57607f821691505b602082108103613f8b57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b8181038181111561095057610950613f91565b634e487b7160e01b600052603260045260246000fd5b805160208201516001600160e01b03198082169291906004831015613fff5780818460040360031b1b83161693505b505050919050565b8082018082111561095057610950613f91565b600081518084526020808501945080840160005b83811015613b4a5781516001600160a01b03168752958201959082019060010161402e565b600081518084526020808501808196508360051b8101915082860160005b8581101561409b578284038952614089848351613571565b98850198935090840190600101614071565b5091979650505050505050565b60006101208b8352602060018060a01b038c16818501528160408501526140d18285018c61401a565b915083820360608501526140e5828b613b1a565b915083820360808501528189518084528284019150828160051b850101838c0160005b8381101561413657601f19878403018552614124838351613571565b94860194925090850190600101614108565b505086810360a088015261414a818c614053565b9450505050508560c08401528460e084015282810361010084015261416f8185613571565b9c9b505050505050505050505050565b60006020828403121561419157600080fd5b8151610f6881613619565b6000602082840312156141ae57600080fd5b5051919050565b808202811582820484141761095057610950613f91565b634e487b7160e01b600052601260045260246000fd5b6000826141f1576141f16141cc565b500490565b60208152816020820152818360408301376000818301604090810191909152601f909201601f19160101919050565b60006020828403121561423757600080fd5b81516001600160401b0381111561424d57600080fd5b8201601f8101841361425e57600080fd5b805161426c61364f826136f2565b81815285602083850101111561428157600080fd5b61187f82602083016020860161354d565b6000602082840312156142a457600080fd5b815165ffffffffffff81168114610f6857600080fd5b6080815260006142cd608083018761401a565b82810360208401526142df8187613b1a565b905082810360408401526142f38186614053565b91505082606083015295945050505050565b8183823760009101908152919050565b60006020828403121561432757600080fd5b815160038110610f6857600080fd5b60006080828403121561434857600080fd5b604051608081018181106001600160401b038211171561436a5761436a6135b0565b60405282518152602083015161437f81613619565b6020820152604083810151908201526060928301519281019290925250919050565b6000600182016143b3576143b3613f91565b5060010190565b600082516143cc81846020870161354d565b9190910192915050565b84815260ff841660208201528260408201526080606082015260006114f16080830184613571565b85815260ff8516602082015283604082015260a06060820152600061442660a0830185613571565b82810360808401526117d08185613571565b65ffffffffffff82811682821603908082111561445757614457613f91565b5092915050565b600065ffffffffffff80841680614477576144776141cc565b92169190910492915050565b6000806040838503121561449657600080fd5b50508051602090910151909290915056fe476f7665726e6f723a2063616c6c20726576657274656420776974686f7574206d657373616765a2646970667358221220de5fbeae0865b340cd002d902c2bcbae7c1a17f105f3f25584f33913f9a1d04164736f6c63430008130033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000019f7c4cfa2cccfaff16f66fb92f4c5d1f3fa9a57000000000000000000000000c4e6a85630ca1d9b754518f653cb43c3f768215b000000000000000000000000ee75b6685611396359d339434b1df012f5c82ba7000000000000000000000000612c5dc0256b8da00bfd6b2b8f711e24b0509044
-----Decoded View---------------
Arg [0] : _forwarder (address): 0x19F7C4Cfa2CCCFAff16F66fb92F4C5d1F3FA9a57
Arg [1] : _ve (address): 0xC4E6a85630cA1d9B754518f653cb43C3F768215B
Arg [2] : _minter (address): 0xEe75b6685611396359d339434b1dF012f5c82BA7
Arg [3] : _voter (address): 0x612c5dc0256b8Da00BFd6B2B8F711E24b0509044
-----Encoded View---------------
4 Constructor Arguments found :
Arg [0] : 00000000000000000000000019f7c4cfa2cccfaff16f66fb92f4c5d1f3fa9a57
Arg [1] : 000000000000000000000000c4e6a85630ca1d9b754518f653cb43c3f768215b
Arg [2] : 000000000000000000000000ee75b6685611396359d339434b1df012f5c82ba7
Arg [3] : 000000000000000000000000612c5dc0256b8da00bfd6b2b8f711e24b0509044
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
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.