Overview
MNT Balance
More Info
ContractCreator
Multichain Info
Latest 7 from a total of 7 transactions
| Transaction Hash |
Method
|
Block
|
From
|
To
|
Amount
|
||||
|---|---|---|---|---|---|---|---|---|---|
| Request | 26989856 | 160 days ago | IN | 0 MNT | 0.02592057 | ||||
| Request | 26871431 | 163 days ago | IN | 0 MNT | 0.02661407 | ||||
| Request | 26870980 | 163 days ago | IN | 0 MNT | 0.02662219 | ||||
| Request | 26870747 | 163 days ago | IN | 0 MNT | 0.02661525 | ||||
| Request | 26860563 | 163 days ago | IN | 0 MNT | 0.0279592 | ||||
| Request | 26859276 | 163 days ago | IN | 0 MNT | 0.0315815 | ||||
| Constitute | 26858974 | 163 days ago | IN | 0 MNT | 0.02210439 |
View more zero value Internal Transactions in Advanced View mode
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
///////////////////////////////////////////////////////////////////////////////
/// This program is free software: you can redistribute it and/or modify ///
/// it under the terms of the MIT Public License. ///
/// ///
/// This is a Proof Of Concept and is not intended for production use. ///
/// Tests are incomplete and it contracts have not been audited. ///
/// ///
/// It is distributed in the hope that it will be useful and insightful, ///
/// but WITHOUT ANY WARRANTY; without even the implied warranty of ///
/// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ///
///////////////////////////////////////////////////////////////////////////////
/// @title Powers Protocol v.0.3
/// @notice Powers is a Role Restricted Governance Protocol. It provides a modular, flexible, decentralised and efficient governance engine for DAOs.
///
/// @dev This contract is the core engine of the protocol. It is meant to be used in combination with implementations of {Law.sol}. The contract should be used as is, making changes to this contract should be avoided.
/// @dev Code is derived from OpenZeppelin's Governor.sol and AccessManager contracts, in addition to Haberdasher Labs Hats protocol.
/// @dev Compatibility with Governor.sol, AccessManager and the Hats protocol is high on the priority list.
///
/// Note several key differences from openzeppelin's {Governor.sol}.
/// 1 - Any DAO action needs to be encoded in role restricted external contracts, or laws, that follow the {ILaw} interface.
/// 2 - Proposing, voting, cancelling and executing actions are role restricted along the target law that is called.
/// 3 - All DAO actions need to run through the governance flow provided by Powers.sol. Calls to laws that do not need a proposedAction vote, for instance, still need to be executed through the {execute} function.
/// 4 - The core protocol uses a non-weighted voting mechanism: one account has one vote. Accounts vote with their roles, not with their tokens.
/// 5 - The core protocol is intentionally minimalistic. Any complexity (timelocks, delayed execution, guardian roles, weighted votes, staking, etc.) has to be integrated through laws.
///
/// For example implementations of DAOs, see the `Deploy...` files in the /script folder.
///
/// Note This protocol is a work in progress. A number of features are planned to be added in the future.
/// - Integration with, or support for OpenZeppelin's {Governor.sol} and Compound's {GovernorBravo.sol}. The same holds for the Hats Protocol.
/// - Native support for multi-chain governance.
/// - Gas efficiency improvements.
/// - Improved time management, including support for EIP-6372 {clock()} for timestamping governance processes.
/// - And more.
///
/// @author 7Cedars
pragma solidity 0.8.26;
import { Law } from "./Law.sol";
import { ILaw } from "./interfaces/ILaw.sol";
import { IPowers } from "./interfaces/IPowers.sol";
import { ERC165Checker } from "../lib/openzeppelin-contracts/contracts/utils/introspection/ERC165Checker.sol";
import { Address } from "../lib/openzeppelin-contracts/contracts/utils/Address.sol";
import { EIP712 } from "../lib/openzeppelin-contracts/contracts/utils/cryptography/EIP712.sol";
// import { console2 } from "forge-std/console2.sol"; // remove before deploying.
contract Powers is EIP712, IPowers {
//////////////////////////////////////////////////////////////
// STORAGE //
/////////////////////////////////////////////////////////////
mapping(uint256 actionId => Action) internal _actions; // mapping actionId to Action struct
mapping(uint16 lawId => ActiveLaw) internal laws; // mapping law address to Law struct
mapping(uint256 roleId => Role) internal roles; // mapping roleId to Role struct
// two roles are preset: ADMIN_ROLE == 0 and PUBLIC_ROLE == type(uint256).max.
uint256 public constant ADMIN_ROLE = type(uint256).min; // == 0
uint256 public constant PUBLIC_ROLE = type(uint256).max; // == a lot
uint256 public constant DENOMINATOR = 100; // == 100%
string public name; // name of the DAO.
string public uri; // a uri to metadata of the DAO.
bool private _constituteExecuted; // has the constitute function been called before?
// NB! this is a gotcha: laws start counting a 1, NOT 0!. 0 is used as a default 'false' value.
uint16 public lawCount = 1; // number of laws that have been initiated throughout the life of the organisation.
//////////////////////////////////////////////////////////////
// MODIFIERS //
//////////////////////////////////////////////////////////////
/// @notice A modifier that sets a function to only be callable by the {Powers} contract.
modifier onlyPowers() {
if (msg.sender != address(this)) revert Powers__OnlyPowers();
_;
}
/// @notice A modifier that sets a function to only be callable by the {Powers} contract.
modifier onlyActiveLaw(uint16 lawId) {
if (laws[lawId].active == false) revert Powers__LawNotActive();
_;
}
//////////////////////////////////////////////////////////////
// CONSTRUCTOR & RECEIVE //
//////////////////////////////////////////////////////////////
/// @notice Sets the value for {name} at the time of construction.
///
/// @param name_ name of the contract
constructor(string memory name_, string memory uri_) EIP712(name_, version()) {
if (bytes(name_).length == 0) revert Powers__InvalidName();
name = name_;
uri = uri_;
_setRole(ADMIN_ROLE, msg.sender, true); // the account that initiates a Powerscontract is set to its admin.
roles[ADMIN_ROLE].amountMembers = 1; // the number of admins at set up is 1.
roles[PUBLIC_ROLE].amountMembers = type(uint256).max; // the number for holders of the PUBLIC_ROLE is type(uint256).max. As in, everyone has this role.
emit Powers__Initialized(address(this), name, uri);
}
/// @notice receive function enabling ETH deposits.
///
/// @dev This is a virtual function, and can be overridden in the DAO implementation.
/// @dev No access control on this function: anyone can send funds in native currency into the contract.
receive() external payable virtual {
emit FundsReceived(msg.value, msg.sender);
}
//////////////////////////////////////////////////////////////
// GOVERNANCE LOGIC //
//////////////////////////////////////////////////////////////
/// @inheritdoc IPowers
/// @dev The execute function follows a call-and-return mechanism. This allows for async execution of laws.
function request(uint16 lawId, bytes calldata lawCalldata, uint256 nonce, string memory uriAction)
external
payable
virtual
onlyActiveLaw(lawId)
{
uint256 actionId = _hashAction(lawId, lawCalldata, nonce);
ActiveLaw memory law = laws[lawId];
// check 1: does executioner have access to law being executed?
if (!canCallLaw(msg.sender, lawId)) revert Powers__AccessDenied();
// check 2: has action already been set as requested?
if (_actions[actionId].requested == true) revert Powers__ActionAlreadyInitiated();
// check 3: is proposedAction cancelled?
// if law did not need a proposedAction proposedAction vote to start with, check will pass.
if (_actions[actionId].cancelled == true) revert Powers__ActionCancelled();
// If checks passed, set action as requested.
_actions[actionId].caller = msg.sender; // note if caller had been set during proposedAction, it will be overwritten.
_actions[actionId].lawId = lawId;
_actions[actionId].requested = true;
_actions[actionId].lawCalldata = lawCalldata;
_actions[actionId].uri = uriAction;
_actions[actionId].nonce = nonce;
// execute law.
(bool success) = ILaw(law.targetLaw).executeLaw(msg.sender, lawId, lawCalldata, nonce);
if (!success) revert Powers__LawDidNotPassChecks();
// emit event.
emit ActionRequested(msg.sender, lawId, lawCalldata, nonce, uriAction);
}
/// @inheritdoc IPowers
function fulfill(
uint16 lawId,
uint256 actionId,
address[] calldata targets,
uint256[] calldata values,
bytes[] calldata calldatas
) external payable virtual onlyActiveLaw(lawId) {
ActiveLaw memory law = laws[lawId];
// check 1: is msg.sender a targetLaw?
if (!law.active) revert Powers__LawNotActive();
// check 2: is msg.sender the targetLaw?
if (law.targetLaw != msg.sender) revert Powers__AccessDenied();
// check 3: has action already been set as requested?
if (_actions[actionId].requested != true) revert Powers__ActionNotRequested();
// check 4: are the lengths of targets, values and calldatas equal?
if (targets.length != values.length || targets.length != calldatas.length) revert Powers__InvalidCallData();
// set action as fulfilled.
_actions[actionId].fulfilled = true;
// execute targets[], values[], calldatas[] received from law.
for (uint256 i = 0; i < targets.length; ++i) {
(bool success, bytes memory returndata) = targets[i].call{ value: values[i] }(calldatas[i]);
Address.verifyCallResult(success, returndata);
}
// emit event.
emit ActionExecuted(lawId, actionId, targets, values, calldatas);
}
/// @inheritdoc IPowers
function propose(uint16 lawId, bytes calldata lawCalldata, uint256 nonce, string memory uriAction)
external
virtual
onlyActiveLaw(lawId)
returns (uint256)
{
ActiveLaw memory law = laws[lawId];
// check 1: is targetLaw is an active law?
if (!law.active) revert Powers__LawNotActive();
// check 2: does msg.sender have access to targetLaw?
if (!canCallLaw(msg.sender, lawId)) revert Powers__AccessDenied();
// if checks pass: propose.
return _propose(msg.sender, lawId, lawCalldata, nonce, uriAction);
}
/// @notice Internal propose mechanism. Can be overridden to add more logic on proposedAction creation.
///
/// @dev The mechanism checks for the length of targets and calldatas.
///
/// Emits a {SeperatedPowersEvents::proposedActionCreated} event.
function _propose(
address caller,
uint16 lawId,
bytes calldata lawCalldata,
uint256 nonce,
string memory uriAction
) internal virtual returns (uint256 actionId) {
ActiveLaw memory law = laws[lawId];
// (uint8 quorum,, uint32 votingPeriod,,,,,) = Law(targetLaw).conditions();
ILaw.Conditions memory conditions = Law(law.targetLaw).getConditions(address(this), lawId);
actionId = _hashAction(lawId, lawCalldata, nonce);
// check 1: does target law need proposedAction vote to pass?
if (conditions.quorum == 0) revert Powers__NoVoteNeeded();
// check 2: do we have a proposedAction with the same targetLaw and lawCalldata?
if (_actions[actionId].voteStart != 0) revert Powers__UnexpectedActionState();
// check 3: do proposedAction checks of the law pass?
Law(law.targetLaw).checksAtPropose(caller, conditions, lawCalldata, nonce, address(this));
// if checks pass: create proposedAction
Action storage proposedAction = _actions[actionId];
proposedAction.lawCalldata = lawCalldata;
proposedAction.lawId = lawId;
proposedAction.voteStart = uint48(block.number); // note that the moment proposedAction is made, voting start. Delay functionality has to be implemeted at the law level.
proposedAction.voteDuration = conditions.votingPeriod;
proposedAction.caller = caller;
proposedAction.uri = uriAction;
proposedAction.nonce = nonce;
emit ProposedActionCreated(
actionId,
caller,
lawId,
"",
lawCalldata,
block.number,
block.number + conditions.votingPeriod,
nonce,
uriAction
);
}
/// @inheritdoc IPowers
/// @dev the account to cancel must be the account that created the proposedAction.
function cancel(uint16 lawId, bytes calldata lawCalldata, uint256 nonce)
public
virtual
onlyActiveLaw(lawId)
returns (uint256)
{
uint256 actionId = _hashAction(lawId, lawCalldata, nonce);
// only caller can cancel a proposedAction, also checks if proposedAction exists (otherwise _actions[actionId].caller == address(0))
if (msg.sender != _actions[actionId].caller) revert Powers__AccessDenied();
return _cancel(lawId, lawCalldata, nonce);
}
/// @notice Internal cancel mechanism with minimal restrictions. A proposedAction can be cancelled in any state other than
/// Cancelled or Executed. Once cancelled a proposedAction cannot be re-submitted.
/// Emits a {SeperatedPowersEvents::proposedActionCanceled} event.
function _cancel(uint16 lawId, bytes calldata lawCalldata, uint256 nonce) internal virtual returns (uint256) {
uint256 actionId = _hashAction(lawId, lawCalldata, nonce);
// check 1: is action already fulfilled or cancelled?
if (_actions[actionId].fulfilled || _actions[actionId].cancelled) revert Powers__UnexpectedActionState();
// set action as cancelled.
_actions[actionId].cancelled = true;
// emit event.
emit ProposedActionCancelled(actionId);
return actionId;
}
/// @inheritdoc IPowers
function castVote(uint256 actionId, uint8 support) external virtual {
address voter = msg.sender;
return _castVote(actionId, voter, support, "");
}
/// @inheritdoc IPowers
function castVoteWithReason(uint256 actionId, uint8 support, string calldata reason) public virtual {
address voter = msg.sender;
return _castVote(actionId, voter, support, reason);
}
/// @notice Internal vote casting mechanism.
/// Check that the proposedAction is active, and that account is has access to targetLaw.
///
/// Emits a {SeperatedPowersEvents::VoteCast} event.
function _castVote(uint256 actionId, address account, uint8 support, string memory reason) internal virtual {
// Check that the proposedAction is active, that it has not been paused, cancelled or ended yet.
if (Powers(payable(address(this))).state(actionId) != ActionState.Active) {
revert Powers__ProposedActionNotActive();
}
// Note that we check if account has access to the law targetted in the proposedAction.
uint16 lawId = _actions[actionId].lawId;
if (!canCallLaw(account, lawId)) revert Powers__AccessDenied();
// if all this passes: cast vote.
_countVote(actionId, account, support);
emit VoteCast(account, actionId, support, reason);
}
//////////////////////////////////////////////////////////////
// ROLE AND LAW ADMIN //
//////////////////////////////////////////////////////////////
/// @inheritdoc IPowers
function constitute(LawInitData[] memory constituentLaws) external virtual {
// check 1: only admin can call this function
if (roles[ADMIN_ROLE].members[msg.sender] == 0) revert Powers__AccessDenied();
// check 2: this function can only be called once.
if (_constituteExecuted) revert Powers__ConstitutionAlreadyExecuted();
// if checks pass, set _constituentLawsExecuted to true...
_constituteExecuted = true;
// ...and set laws as active.
for (uint256 i = 0; i < constituentLaws.length; i++) {
// note: ignore empty slots in LawInitData array.
if (constituentLaws[i].targetLaw != address(0)) {
_adoptLaw(constituentLaws[i]);
}
}
}
/// @inheritdoc IPowers
function adoptLaw(LawInitData memory lawInitData) public onlyPowers {
_adoptLaw(lawInitData);
}
/// @inheritdoc IPowers
function revokeLaw(uint16 lawId) public onlyPowers {
if (laws[lawId].active == false) revert Powers__LawNotActive();
laws[lawId].active = false;
emit LawRevoked(lawId);
}
/// @notice internal function to set a law or revoke it.
///
/// @param lawInitData data of the law.
///
/// Emits a {SeperatedPowersEvents::LawAdopted} event.
function _adoptLaw(LawInitData memory lawInitData) internal virtual {
// check if added address is indeed a law. Note that this will also revert with address(0).
if (!ERC165Checker.supportsInterface(lawInitData.targetLaw, type(ILaw).interfaceId)) {
revert Powers__IncorrectInterface();
}
laws[lawCount].active = true;
laws[lawCount].targetLaw = lawInitData.targetLaw;
lawCount++;
Law(lawInitData.targetLaw).initializeLaw(
lawCount - 1,
lawInitData.nameDescription,
"",
lawInitData.conditions,
lawInitData.config
);
// emit event.
emit LawAdopted(lawCount - 1);
}
/// @inheritdoc IPowers
function assignRole(uint256 roleId, address account) public virtual onlyPowers {
_setRole(roleId, account, true);
}
/// @inheritdoc IPowers
function revokeRole(uint256 roleId, address account) public virtual onlyPowers {
_setRole(roleId, account, false);
}
/// @inheritdoc IPowers
function labelRole(uint256 roleId, string memory label) public virtual onlyPowers {
if (roleId == ADMIN_ROLE || roleId == PUBLIC_ROLE) revert Powers__LockedRole();
roles[roleId].label = label;
emit RoleLabel(roleId, label);
}
/// @notice Internal version of {setRole} without access control.
/// @dev This function is used to set a role for a given account. Public role is locked as everyone has it.
/// @dev Note that it does allow Admin role to be assigned and revoked.
///
/// Emits a {SeperatedPowersEvents::RolSet} event.
function _setRole(uint256 roleId, address account, bool access) internal virtual {
bool newMember = roles[roleId].members[account] == 0;
// check 1: Public role is locked.
if (roleId == PUBLIC_ROLE) revert Powers__CannotAddToPublicRole();
// check 2: Zero address is not allowed.
if (account == address(0)) revert Powers__CannotAddZeroAddress();
if (access) {
roles[roleId].members[account] = uint48(block.number); // 'since' is set at current block.number
if (newMember) {
roles[roleId].amountMembers++;
}
} else {
roles[roleId].members[account] = 0;
if (!newMember) {
roles[roleId].amountMembers--;
}
}
emit RoleSet(roleId, account, access);
}
//////////////////////////////////////////////////////////////
// HELPER FUNCTIONS //
//////////////////////////////////////////////////////////////
function _hashAction(uint16 lawId, bytes calldata lawCalldata, uint256 nonce)
internal
view
virtual
returns (uint256)
{
return uint256(keccak256(abi.encode(lawId, lawCalldata, nonce)));
}
/// @notice internal function {quorumReached} that checks if the quorum for a given proposedAction has been reached.
///
/// @param actionId id of the proposedAction.
///
function _quorumReached(uint256 actionId) internal view virtual returns (bool) {
// retrieve quorum and allowedRole from law.
Action storage proposedAction = _actions[actionId];
ActiveLaw memory law = laws[proposedAction.lawId];
ILaw.Conditions memory conditions = Law(law.targetLaw).getConditions(address(this), proposedAction.lawId);
uint256 amountMembers = _countMembersRole(conditions.allowedRole);
// check if quorum is set to 0 in a Law, it will automatically return true. Otherwise, check if quorum has been reached.
return (
conditions.quorum == 0
|| amountMembers * conditions.quorum
<= (proposedAction.forVotes + proposedAction.abstainVotes) * DENOMINATOR
);
}
/// @notice internal function {voteSucceeded} that checks if a vote for a given proposedAction has succeeded.
///
/// @param actionId id of the proposedAction.
function _voteSucceeded(uint256 actionId) internal view virtual returns (bool) {
// retrieve quorum and success threshold from law.
Action storage proposedAction = _actions[actionId];
ActiveLaw memory law = laws[proposedAction.lawId];
ILaw.Conditions memory conditions = Law(law.targetLaw).getConditions(address(this), proposedAction.lawId);
uint256 amountMembers = _countMembersRole(conditions.allowedRole);
// note if quorum is set to 0 in a Law, it will automatically return true. Otherwise, check if success threshold has been reached.
return conditions.quorum == 0 || amountMembers * conditions.succeedAt <= proposedAction.forVotes * DENOMINATOR;
}
/// @notice internal function {countVote} that counts against, for, and abstain votes for a given proposedAction.
///
/// @dev In this module, the support follows the `VoteType` enum (from Governor Bravo).
/// @dev It does not check if account has roleId referenced in actionId. This has to be done by {Powers.castVote} function.
function _countVote(uint256 actionId, address account, uint8 support) internal virtual {
Action storage proposedAction = _actions[actionId];
// check 1: has account already voted?
if (proposedAction.hasVoted[account]) revert Powers__AlreadyCastVote();
// set account as voted.
proposedAction.hasVoted[account] = true;
// add vote to tally.
if (support == uint8(VoteType.Against)) {
proposedAction.againstVotes++;
} else if (support == uint8(VoteType.For)) {
proposedAction.forVotes++;
} else if (support == uint8(VoteType.Abstain)) {
proposedAction.abstainVotes++;
} else {
revert Powers__InvalidVoteType();
}
}
/// @notice internal function {countMembersRole} that counts the number of members in a given role.
/// @dev If needed, this function can be overridden with bespoke logic.
///
/// @param roleId id of the role.
///
/// @return amountMembers number of members in the role.
function _countMembersRole(uint256 roleId) internal view virtual returns (uint256 amountMembers) {
return roles[roleId].amountMembers;
}
/// @inheritdoc IPowers
function setUri(string memory newUri) public virtual onlyPowers {
uri = newUri;
}
//////////////////////////////////////////////////////////////
// VIEW / GETTER FUNCTIONS //
//////////////////////////////////////////////////////////////
/// @inheritdoc IPowers
function state(uint256 actionId) public view virtual returns (ActionState) {
// We read the struct fields into the stack at once so Solidity emits a single SLOAD
Action storage proposedAction = _actions[actionId];
bool ActionFulfilled = proposedAction.fulfilled;
bool proposedActionCancelled = proposedAction.cancelled;
if (ActionFulfilled) {
return ActionState.Fulfilled;
}
if (proposedActionCancelled) {
return ActionState.Cancelled;
}
uint256 start = _actions[actionId].voteStart; // = startDate
if (start == 0) {
return ActionState.NonExistent;
}
uint256 deadline = getProposedActionDeadline(actionId);
if (deadline >= block.number) {
return ActionState.Active;
} else if (!_quorumReached(actionId) || !_voteSucceeded(actionId)) {
return ActionState.Defeated;
} else {
return ActionState.Succeeded;
}
}
/// @notice saves the version of the Powersimplementation.
function version() public pure returns (string memory) {
return "0.3";
}
/// @inheritdoc IPowers
function canCallLaw(address caller, uint16 lawId) public view virtual returns (bool) {
uint256 allowedRole = Law(laws[lawId].targetLaw).getConditions(address(this), lawId).allowedRole;
uint48 since = hasRoleSince(caller, allowedRole);
return since != 0 || allowedRole == PUBLIC_ROLE;
}
/// @inheritdoc IPowers
function hasRoleSince(address account, uint256 roleId) public view returns (uint48 since) {
return roles[roleId].members[account];
}
/// @inheritdoc IPowers
function hasVoted(uint256 actionId, address account) public view virtual returns (bool) {
return _actions[actionId].hasVoted[account];
}
/// @inheritdoc IPowers
function getActionData(uint256 actionId)
public
view
virtual
returns (
bool cancelled,
bool requested,
bool fulfilled,
uint16 lawId,
uint48 voteStart,
uint32 voteDuration,
uint256 voteEnd,
address caller,
uint32 againstVotes,
uint32 forVotes,
uint32 abstainVotes,
uint256 nonce
)
{
Action storage action = _actions[actionId];
return (
action.cancelled,
action.requested,
action.fulfilled,
action.lawId,
action.voteStart,
action.voteDuration,
action.voteStart + action.voteDuration,
action.caller,
action.againstVotes,
action.forVotes,
action.abstainVotes,
action.nonce
);
}
function getActionCalldata(uint256 actionId)
public
view
virtual
returns (bytes memory callData)
{
return _actions[actionId].lawCalldata;
}
function getActionUri(uint256 actionId)
public
view
virtual
returns (string memory _uri)
{
_uri = _actions[actionId].uri;
}
function getActionNonce(uint256 actionId)
public
view
virtual
returns (uint256 nonce)
{
return _actions[actionId].nonce;
}
/// @inheritdoc IPowers
function getAmountRoleHolders(uint256 roleId) public view returns (uint256 amountMembers) {
return roles[roleId].amountMembers;
}
function getRoleLabel(uint256 roleId) public view returns (string memory label) {
return roles[roleId].label;
}
/// @inheritdoc IPowers
function getProposedActionDeadline(uint256 actionId) public view virtual returns (uint256) {
// uint48 + uint32 => uint256. £test if this works properly.
return _actions[actionId].voteStart + _actions[actionId].voteDuration;
}
/// @inheritdoc IPowers
function getActiveLaw(uint16 lawId)
external
view
returns (address law, bytes32 lawHash, bool active)
{
law = laws[lawId].targetLaw;
active = laws[lawId].active;
lawHash = keccak256(abi.encode(address(this), lawId));
return (law, lawHash, active);
}
//////////////////////////////////////////////////////////////
// COMPLIANCE //
//////////////////////////////////////////////////////////////
/// @notice implements ERC721Receiver
function onERC721Received(address, address, uint256, bytes memory) public virtual returns (bytes4) {
return this.onERC721Received.selector;
}
/// @notice implements ERC1155Receiver
function onERC1155Received(address, address, uint256, uint256, bytes memory) public virtual returns (bytes4) {
return this.onERC1155Received.selector;
}
/// @notice implements ERC1155BatchReceiver
function onERC1155BatchReceived(address, address, uint256[] memory, uint256[] memory, bytes memory)
public
virtual
returns (bytes4)
{
return this.onERC1155BatchReceived.selector;
}
}// SPDX-License-Identifier: MIT
///////////////////////////////////////////////////////////////////////////////
/// This program is free software: you can redistribute it and/or modify ///
/// it under the terms of the MIT Public License. ///
/// ///
/// This is a Proof Of Concept and is not intended for production use. ///
/// Tests are incomplete and its contracts have not been audited. ///
/// ///
/// It is distributed in the hope that it will be useful and insightful, ///
/// but WITHOUT ANY WARRANTY; without even the implied warranty of ///
/// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ///
///////////////////////////////////////////////////////////////////////////////
/// @title Law - Base Implementation for Powers Protocol Laws. v0.3.
/// @notice Base contract for implementing role-restricted governance actions
/// @dev Provides core functionality for creating governance laws in the Powers protocol
///
/// Laws serve five key functions:
/// 1. Role restriction of community actions
/// 2. Transformation of input data into executable calls
/// 3. State management for the community
/// 4. Validation of proposal and execution conditions
/// 5. Returning of data to the Powers protocol
///
/// Laws can be customized through:
/// - conditionsuring checks in the constructor
/// - Inheriting and implementing bespoke logic in the {handleRequest} {_replyPowers} and {_changeState} functions.
///
/// @author 7Cedars
pragma solidity 0.8.26;
import { IPowers } from "./interfaces/IPowers.sol";
import { LawUtilities } from "./LawUtilities.sol";
import { ILaw } from "./interfaces/ILaw.sol";
import { ERC165 } from "../lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol";
import { IERC165 } from "../lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol";
// import { console2 } from "forge-std/console2.sol"; // remove before deploying
abstract contract Law is ERC165, ILaw {
//////////////////////////////////////////////////////////////
// STORAGE //
//////////////////////////////////////////////////////////////
struct LawData {
string nameDescription;
bytes inputParams;
Conditions conditions;
Executions executions;
}
mapping(bytes32 lawHash => LawData) public laws;
//////////////////////////////////////////////////////////////
// LAW EXECUTION //
//////////////////////////////////////////////////////////////
// note this is an unrestricted function. Anyone can initialize a law.
function initializeLaw(
uint16 index,
string memory nameDescription,
bytes memory inputParams,
Conditions memory conditions,
bytes memory config
) public virtual {
bytes32 lawHash = LawUtilities.hashLaw(msg.sender, index);
LawUtilities.checkStringLength(nameDescription, 1, 255);
laws[lawHash] = LawData({
nameDescription: nameDescription,
inputParams: inputParams,
conditions: conditions,
executions: Executions({
powers: msg.sender,
config: config,
actionsIds: new uint256[](0),
executions: new uint48[](0)
})
});
emit Law__Initialized(msg.sender, index, nameDescription, inputParams, conditions, config);
}
/// @notice Executes the law's logic: validation -> handling request -> changing state -> replying to Powers
/// @dev Called by the Powers protocol during action execution
/// @param caller Address that initiated the action
/// @param lawCalldata Encoded function call data
/// @param nonce The nonce for the action
/// @return success True if execution succeeded
function executeLaw(address caller, uint16 lawId, bytes calldata lawCalldata, uint256 nonce)
public
returns (bool success)
{
bytes32 lawHash = LawUtilities.hashLaw(msg.sender, lawId);
if (laws[lawHash].executions.powers != msg.sender) {
revert Law__OnlyPowers();
}
// Run all validation checks
checksAtPropose(
caller, laws[lawHash].conditions, lawCalldata, nonce, msg.sender);
checksAtExecute(
caller, laws[lawHash].conditions, lawCalldata, nonce, laws[lawHash].executions.executions, msg.sender, lawId
);
// Simulate and execute the law's logic
(
uint256 actionId,
address[] memory targets,
uint256[] memory values,
bytes[] memory calldatas,
bytes memory stateChange
) = handleRequest(caller, msg.sender, lawId, lawCalldata, nonce);
// execute the law's logic conditional on data returned by handleRequest
if (stateChange.length > 0) {
_changeState(lawHash, stateChange);
}
if (targets.length > 0) {
_replyPowers(lawId, actionId, targets, values, calldatas); // this is where the law's logic is executed. I should check if call is successful. It will revert if not succesful, right?
}
// save execution data
laws[lawHash].executions.executions.push(uint48(block.number)); //
laws[lawHash].executions.actionsIds.push(actionId);
return true;
}
/// @notice Handles requests from the Powers protocol and returns data _replyPowers and _changeState can use.
/// @dev Must be overridden by implementing contracts
/// @param caller Address that initiated the action
/// @param lawId The id of the law
/// @param lawCalldata Encoded function call data
/// @param nonce The nonce for the action
/// @return actionId The action ID
/// @return targets Target contract addresses for calls
/// @return values ETH values to send with calls
/// @return calldatas Encoded function calls
/// @return stateChange Encoded state changes to apply
function handleRequest(address caller, address powers, uint16 lawId, bytes memory lawCalldata, uint256 nonce)
public
view
virtual
returns (
uint256 actionId,
address[] memory targets,
uint256[] memory values,
bytes[] memory calldatas,
bytes memory stateChange
)
{
// Empty implementation - must be overridden
}
/// @notice Applies state changes from law execution
/// @dev Must be overridden by implementing contracts
/// @param stateChange Encoded state changes to apply
function _changeState(bytes32 lawHash, bytes memory stateChange) internal virtual {
// Empty implementation - must be overridden
}
/// @notice Sends execution data back to Powers protocol
/// @dev cannot be overridden by implementing contracts.
/// @param lawId The law id of the proposal
/// @param actionId The action id of the proposal
/// @param targets Target contract addresses for calls
/// @param values ETH values to send with calls
/// @param calldatas Encoded function calls
function _replyPowers(
uint16 lawId,
uint256 actionId,
address[] memory targets,
uint256[] memory values,
bytes[] memory calldatas
) internal virtual {
// Base implementation: send data back to Powers protocol
bytes32 lawHash = LawUtilities.hashLaw(msg.sender, lawId);
IPowers(payable(laws[lawHash].executions.powers)).fulfill(lawId, actionId, targets, values, calldatas);
}
//////////////////////////////////////////////////////////////
// VALIDATION //
//////////////////////////////////////////////////////////////
/// @notice Validates conditions required to propose an action
/// @dev Called during both proposal and execution
/// @param lawCalldata Encoded function call data
/// @param nonce The nonce for the action
function checksAtPropose(
address, /*caller*/
Conditions memory conditions,
bytes memory lawCalldata,
uint256 nonce,
address powers
) public view virtual {
LawUtilities.baseChecksAtPropose(conditions, lawCalldata, powers, nonce);
}
/// @notice Validates conditions required to execute an action
/// @dev Called during execution after proposal checks
/// @param lawCalldata Encoded function call data
/// @param nonce The nonce for the action
function checksAtExecute(
address, /*caller*/
Conditions memory conditions,
bytes memory lawCalldata,
uint256 nonce,
uint48[] memory executions,
address powers,
uint16 lawId
) public view virtual {
LawUtilities.baseChecksAtExecute(conditions, lawCalldata, powers, nonce, executions, lawId);
}
//////////////////////////////////////////////////////////////
// HELPER FUNCTIONS //
//////////////////////////////////////////////////////////////
// Place these in lawUtilities library?
function getConditions(address powers, uint16 lawId) public view returns (Conditions memory conditions) {
return laws[LawUtilities.hashLaw(powers, lawId)].conditions;
}
function getExecutions(address powers, uint16 lawId) public view returns (Executions memory executions) {
return laws[LawUtilities.hashLaw(powers, lawId)].executions;
}
function getInputParams(address powers, uint16 lawId) public view returns (bytes memory inputParams) {
return laws[LawUtilities.hashLaw(powers, lawId)].inputParams;
}
function getNameDescription(address powers, uint16 lawId) public view returns (string memory nameDescription) {
return laws[LawUtilities.hashLaw(powers, lawId)].nameDescription;
}
//////////////////////////////////////////////////////////////
// UTILITIES //
//////////////////////////////////////////////////////////////
/// @notice Checks if contract implements required interfaces
/// @dev Implements IERC165
/// @param interfaceId Interface identifier to check
/// @return True if interface is supported
function supportsInterface(bytes4 interfaceId) public view override(ERC165, IERC165) virtual returns (bool) {
return interfaceId == type(ILaw).interfaceId || super.supportsInterface(interfaceId);
}
}// SPDX-License-Identifier: MIT
///////////////////////////////////////////////////////////////////////////////
/// This program is free software: you can redistribute it and/or modify ///
/// it under the terms of the MIT Public License. ///
/// ///
/// This is a Proof Of Concept and is not intended for production use. ///
/// Tests are incomplete and its contracts have not been audited. ///
/// ///
/// It is distributed in the hope that it will be useful and insightful, ///
/// but WITHOUT ANY WARRANTY; without even the implied warranty of ///
/// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ///
///////////////////////////////////////////////////////////////////////////////
/// @title Law Interface - Contract Interface for Powers Protocol Laws
/// @notice Defines the interface for implementing role-restricted governance actions
/// @dev Interface for the Law contract, which provides core functionality for governance laws
/// @author 7Cedars
pragma solidity 0.8.26;
import { IERC165 } from "../../lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol";
import { LawErrors } from "./LawErrors.sol";
interface ILaw is IERC165, LawErrors {
//////////////////////////////////////////////////////////////
// TYPES //
//////////////////////////////////////////////////////////////
struct Executions {
address powers;
bytes config;
uint256[] actionsIds;
uint48[] executions;
}
struct Conditions {
// Slot 0
uint256 allowedRole; // 32 bytes
// Slot 1
uint16 needCompleted; // 2 bytes - index of law that must be completed before this one
uint48 delayExecution; // 6 bytes - Blocks to wait after proposal success before execution
uint48 throttleExecution; // 6 bytes - Minimum blocks between executions
uint16 readStateFrom; // 2 bytes - index of law to read state from (for law dependencies)
uint32 votingPeriod; // 4 bytes - Number of blocks for voting period
uint8 quorum; // 1 byte - Required participation percentage
uint8 succeedAt; // 1 byte - Required success percentage
uint16 needNotCompleted; // 2 bytes - index of law that must NOT be completed
}
//////////////////////////////////////////////////////////////
// EVENTS //
//////////////////////////////////////////////////////////////
/// @notice Emitted when a law is deployed
/// @param configParams Configuration parameters for the law
event Law__Deployed(bytes configParams);
/// @notice Emitted when a law is initialized
/// @param powers Address of the Powers protocol
/// @param index Index of the law
/// @param nameDescription Name of the law
/// @param conditions Conditions for the law
/// @param inputParams Input parameters for the law
event Law__Initialized(
address indexed powers, uint16 indexed index, string nameDescription, bytes inputParams, Conditions conditions, bytes config
);
//////////////////////////////////////////////////////////////
// LAW EXECUTION //
//////////////////////////////////////////////////////////////
/// @notice Initializes the law
/// @param index Index of the law
/// @param nameDescription Name of the law
/// @param inputParams Input parameters for the law
/// @param conditions Conditions for the law
/// @param config Configuration parameters for the law
function initializeLaw(
uint16 index,
string memory nameDescription,
bytes memory inputParams,
Conditions memory conditions,
bytes memory config
) external;
/// @notice Executes the law's logic after validation
/// @dev Called by the Powers protocol during action execution
/// @param caller Address that initiated the action
/// @param lawId The id of the law
/// @param lawCalldata Encoded function call data
/// @param nonce The nonce for the action
/// @return success True if execution succeeded
function executeLaw(address caller, uint16 lawId, bytes calldata lawCalldata, uint256 nonce)
external
returns (bool success);
/// @notice Simulates the law's execution logic
/// @dev Must be overridden by implementing contracts
/// @param caller Address that initiated the action
/// @param lawId The id of the law
/// @param lawCalldata Encoded function call data
/// @param nonce The nonce for the action
/// @return actionId The action ID
/// @return targets Target contract addresses for calls
/// @return values ETH values to send with calls
/// @return calldatas Encoded function calls
/// @return stateChange Encoded state changes to apply
function handleRequest(address caller, address powers, uint16 lawId, bytes memory lawCalldata, uint256 nonce)
external
view
returns (
uint256 actionId,
address[] memory targets,
uint256[] memory values,
bytes[] memory calldatas,
bytes memory stateChange
);
//////////////////////////////////////////////////////////////
// VALIDATION //
//////////////////////////////////////////////////////////////
/// @notice Validates conditions required to propose an action
/// @dev Called during both proposal and execution
/// @param caller Address attempting to propose
/// @param conditions The conditions for the law
/// @param lawCalldata Encoded function call data
/// @param nonce The nonce for the action
function checksAtPropose(
address caller,
Conditions memory conditions,
bytes memory lawCalldata,
uint256 nonce,
address powers
) external view;
/// @notice Validates conditions required to execute an action
/// @dev Called during execution after proposal checks
/// @param caller Address attempting to execute
/// @param conditions The conditions for the law
/// @param lawCalldata Encoded function call data
/// @param nonce The nonce for the action
function checksAtExecute(
address caller,
Conditions memory conditions,
bytes memory lawCalldata,
uint256 nonce,
uint48[] memory executions,
address powers,
uint16 lawId
) external view;
/// @notice Gets the conditions for a law
/// @param powers The address of the Powers protocol
/// @param lawId The id of the law
/// @return conditions The conditions for the law
function getConditions(address powers, uint16 lawId) external view returns (Conditions memory conditions);
}// SPDX-License-Identifier: MIT
///////////////////////////////////////////////////////////////////////////////
/// This program is free software: you can redistribute it and/or modify ///
/// it under the terms of the MIT Public License. ///
/// ///
/// This is a Proof Of Concept and is not intended for production use. ///
/// Tests are incomplete and it contracts have not been audited. ///
/// ///
/// It is distributed in the hope that it will be useful and insightful, ///
/// but WITHOUT ANY WARRANTY; without even the implied warranty of ///
/// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ///
///////////////////////////////////////////////////////////////////////////////
/// @title Powers Protocol Interface
/// @notice Interface for the Powers protocol, a Role Restricted Governance Protocol
/// @dev Derived from OpenZeppelin's Governor.sol contract
/// @author 7Cedars
pragma solidity 0.8.26;
import { PowersErrors } from "./PowersErrors.sol";
import { PowersEvents } from "./PowersEvents.sol";
import { PowersTypes } from "./PowersTypes.sol";
import { ILaw } from "./ILaw.sol";
interface IPowers is PowersErrors, PowersEvents, PowersTypes {
//////////////////////////////////////////////////////////////
// GOVERNANCE FUNCTIONS //
//////////////////////////////////////////////////////////////
/// @notice Initiates an action to be executed through a law
/// @dev This is the entry point for all actions in the protocol, whether they require voting or not
/// @param lawId The id of the law
/// @param lawCalldata The encoded function call data for the law
/// @param uriDescription A human-readable description of the action
/// @param nonce The nonce for the action
function request(uint16 lawId, bytes calldata lawCalldata, uint256 nonce, string memory uriDescription)
external
payable;
/// @notice Completes an action by executing the actual calls
/// @dev Can only be called by an active law contract
/// @param lawId The id of the law
/// @param actionId The unique identifier of the action
/// @param targets The list of contract addresses to call
/// @param values The list of ETH values to send with each call
/// @param calldatas The list of encoded function calls
function fulfill(
uint16 lawId,
uint256 actionId,
address[] calldata targets,
uint256[] calldata values,
bytes[] calldata calldatas
) external payable;
/// @notice Creates a new proposal for an action that requires voting
/// @dev Only callable if the law requires voting (quorum > 0)
/// @param lawId The id of the law
/// @param lawCalldata The encoded function call data for the law
/// @param nonce The nonce for the action
/// @param uriDescription A human-readable description of the proposal
/// @return The unique identifier of the created proposal
function propose(uint16 lawId, bytes calldata lawCalldata, uint256 nonce, string memory uriDescription)
external
returns (uint256);
/// @notice Cancels an existing proposal
/// @dev Can only be called by the original proposer
/// @param lawId The id of the law
/// @param lawCalldata The original encoded function call data
/// @param nonce The nonce for the action
/// @return The unique identifier of the cancelled proposal
function cancel(uint16 lawId, bytes calldata lawCalldata, uint256 nonce) external returns (uint256);
/// @notice Casts a vote on an active proposal
/// @dev Vote types: 0=Against, 1=For, 2=Abstain
/// @param actionId The unique identifier of the proposal
/// @param support The type of vote to cast
function castVote(uint256 actionId, uint8 support) external;
/// @notice Casts a vote on an active proposal with an explanation
/// @dev Same as castVote but includes a reason string
/// @param actionId The unique identifier of the proposal
/// @param support The type of vote to cast
/// @param reason A human-readable explanation for the vote
function castVoteWithReason(uint256 actionId, uint8 support, string calldata reason) external;
//////////////////////////////////////////////////////////////
// ROLE AND LAW ADMIN //
//////////////////////////////////////////////////////////////
/// @notice Initializes the DAO by activating its founding laws
/// @dev Can only be called once by an admin account
/// @param laws The list of law contracts to activate
function constitute(LawInitData[] calldata laws) external;
/// @notice Activates a new law in the protocol
/// @dev Can only be called through the protocol itself
/// @param lawInitData The data of the law
function adoptLaw(LawInitData calldata lawInitData) external;
/// @notice Deactivates an existing law
/// @dev Can only be called through the protocol itself
/// @param lawId The id of the law
function revokeLaw(uint16 lawId) external;
/// @notice Grants a role to an account
/// @dev Can only be called through the protocol itself
/// @param roleId The identifier of the role to assign
/// @param account The address to grant the role to
function assignRole(uint256 roleId, address account) external;
/// @notice Removes a role from an account
/// @dev Can only be called through the protocol itself
/// @param roleId The identifier of the role to remove
/// @param account The address to remove the role from
function revokeRole(uint256 roleId, address account) external;
/// @notice Assigns a human-readable label to a role
/// @dev Optional. Can only be called through the protocol itself
/// @param roleId The identifier of the role to label
/// @param label The human-readable label for the role
function labelRole(uint256 roleId, string calldata label) external;
//////////////////////////////////////////////////////////////
// VIEW FUNCTIONS //
//////////////////////////////////////////////////////////////
/// @notice Gets the current state of a proposal
/// @param actionId The unique identifier of the proposal
/// @return state the current state of the proposal
function state(uint256 actionId) external view returns (ActionState state);
/// @notice Checks if an account has voted on a specific proposal
/// @param actionId The unique identifier of the proposal
/// @param account The address to check
/// @return hasVoted True if the account has voted, false otherwise
function hasVoted(uint256 actionId, address account) external view returns (bool hasVoted);
/// @notice Gets the deadline for voting on a proposal
/// @param actionId The unique identifier of the proposal
/// @return deadline the block number at which voting ends
function getProposedActionDeadline(uint256 actionId) external view returns (uint256 deadline);
/// @notice gets the data of an actionId that are not an array.
/// @param actionId The unique identifier of the proposal
/// @return cancelled - whether the action has been cancelled
/// @return requested - whether the action has been requested
/// @return fulfilled - whether the action has been fulfilled
/// @return lawId - the id of the law that the action is associated with
/// @return voteStart - the block number at which voting starts
/// @return voteDuration - the duration of the voting period
/// @return voteEnd - the block number at which voting ends
/// @return caller - the address of the caller
/// @return againstVotes - the number of votes against the action
/// @return forVotes - the number of votes for the action
/// @return abstainVotes - the number of abstain votes
/// @return nonce - the nonce of the action
function getActionData(uint256 actionId)
external
view
returns (
bool cancelled,
bool requested,
bool fulfilled,
uint16 lawId,
uint48 voteStart,
uint32 voteDuration,
uint256 voteEnd,
address caller,
uint32 againstVotes,
uint32 forVotes,
uint32 abstainVotes,
uint256 nonce
);
/// @notice Gets the block number since which an account has held a role
/// @param account The address to check
/// @param roleId The identifier of the role
/// @return since the block number since holding the role, 0 if never held
function hasRoleSince(address account, uint256 roleId) external view returns (uint48 since);
/// @notice Gets the total number of accounts holding a specific role
/// @param roleId The identifier of the role
/// @return amountMembers the number of role holders
function getAmountRoleHolders(uint256 roleId) external view returns (uint256 amountMembers);
/// @notice Gets the label of a role
/// @param roleId The identifier of the role
/// @return label The label of the role
function getRoleLabel(uint256 roleId) external view returns (string memory label);
/// @notice Checks if a law is currently active
/// @param lawId The id of the law
/// @return law The address of the law
/// @return lawHash The hash of the law
/// @return active The active status of the law
function getActiveLaw(uint16 lawId)
external
view
returns (address law, bytes32 lawHash, bool active);
/// @notice Checks if an account has permission to call a law
/// @param caller The address attempting to call the law
/// @param lawId The law id to check
/// @return canCall True if the caller has permission, false otherwise
function canCallLaw(address caller, uint16 lawId) external view returns (bool canCall);
/// @notice Gets the protocol version
/// @return version the version string
function version() external pure returns (string memory version);
/// @notice Updates the protocol's metadata URI
/// @dev Can only be called through the protocol itself
/// @param newUri The new URI string
function setUri(string memory newUri) external;
//////////////////////////////////////////////////////////////
// TOKEN HANDLING //
//////////////////////////////////////////////////////////////
/// @notice Handles the receipt of a single ERC721 token
/// @dev Implements IERC721Receiver
function onERC721Received(address, address, uint256, bytes memory) external returns (bytes4);
/// @notice Handles the receipt of a single ERC1155 token
/// @dev Implements IERC1155Receiver
function onERC1155Received(address, address, uint256, uint256, bytes memory) external returns (bytes4);
/// @notice Handles the receipt of multiple ERC1155 tokens
/// @dev Implements IERC1155Receiver
function onERC1155BatchReceived(address, address, uint256[] memory, uint256[] memory, bytes memory)
external
returns (bytes4);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/ERC165Checker.sol)
pragma solidity ^0.8.20;
import {IERC165} from "./IERC165.sol";
/**
* @dev Library used to query support of an interface declared via {IERC165}.
*
* Note that these functions return the actual result of the query: they do not
* `revert` if an interface is not supported. It is up to the caller to decide
* what to do in these cases.
*/
library ERC165Checker {
// As per the ERC-165 spec, no interface should ever match 0xffffffff
bytes4 private constant INTERFACE_ID_INVALID = 0xffffffff;
/**
* @dev Returns true if `account` supports the {IERC165} interface.
*/
function supportsERC165(address account) internal view returns (bool) {
// Any contract that implements ERC-165 must explicitly indicate support of
// InterfaceId_ERC165 and explicitly indicate non-support of InterfaceId_Invalid
return
supportsERC165InterfaceUnchecked(account, type(IERC165).interfaceId) &&
!supportsERC165InterfaceUnchecked(account, INTERFACE_ID_INVALID);
}
/**
* @dev Returns true if `account` supports the interface defined by
* `interfaceId`. Support for {IERC165} itself is queried automatically.
*
* See {IERC165-supportsInterface}.
*/
function supportsInterface(address account, bytes4 interfaceId) internal view returns (bool) {
// query support of both ERC-165 as per the spec and support of _interfaceId
return supportsERC165(account) && supportsERC165InterfaceUnchecked(account, interfaceId);
}
/**
* @dev Returns a boolean array where each value corresponds to the
* interfaces passed in and whether they're supported or not. This allows
* you to batch check interfaces for a contract where your expectation
* is that some interfaces may not be supported.
*
* See {IERC165-supportsInterface}.
*/
function getSupportedInterfaces(
address account,
bytes4[] memory interfaceIds
) internal view returns (bool[] memory) {
// an array of booleans corresponding to interfaceIds and whether they're supported or not
bool[] memory interfaceIdsSupported = new bool[](interfaceIds.length);
// query support of ERC-165 itself
if (supportsERC165(account)) {
// query support of each interface in interfaceIds
for (uint256 i = 0; i < interfaceIds.length; i++) {
interfaceIdsSupported[i] = supportsERC165InterfaceUnchecked(account, interfaceIds[i]);
}
}
return interfaceIdsSupported;
}
/**
* @dev Returns true if `account` supports all the interfaces defined in
* `interfaceIds`. Support for {IERC165} itself is queried automatically.
*
* Batch-querying can lead to gas savings by skipping repeated checks for
* {IERC165} support.
*
* See {IERC165-supportsInterface}.
*/
function supportsAllInterfaces(address account, bytes4[] memory interfaceIds) internal view returns (bool) {
// query support of ERC-165 itself
if (!supportsERC165(account)) {
return false;
}
// query support of each interface in interfaceIds
for (uint256 i = 0; i < interfaceIds.length; i++) {
if (!supportsERC165InterfaceUnchecked(account, interfaceIds[i])) {
return false;
}
}
// all interfaces supported
return true;
}
/**
* @notice Query if a contract implements an interface, does not check ERC-165 support
* @param account The address of the contract to query for support of an interface
* @param interfaceId The interface identifier, as specified in ERC-165
* @return true if the contract at account indicates support of the interface with
* identifier interfaceId, false otherwise
* @dev Assumes that account contains a contract that supports ERC-165, otherwise
* the behavior of this method is undefined. This precondition can be checked
* with {supportsERC165}.
*
* Some precompiled contracts will falsely indicate support for a given interface, so caution
* should be exercised when using this function.
*
* Interface identification is specified in ERC-165.
*/
function supportsERC165InterfaceUnchecked(address account, bytes4 interfaceId) internal view returns (bool) {
// prepare call
bytes memory encodedParams = abi.encodeCall(IERC165.supportsInterface, (interfaceId));
// perform static call
bool success;
uint256 returnSize;
uint256 returnValue;
assembly ("memory-safe") {
success := staticcall(30000, account, add(encodedParams, 0x20), mload(encodedParams), 0x00, 0x20)
returnSize := returndatasize()
returnValue := mload(0x00)
}
return success && returnSize >= 0x20 && returnValue > 0;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.2.0) (utils/Address.sol)
pragma solidity ^0.8.20;
import {Errors} from "./Errors.sol";
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev There's no code at `target` (it is not a contract).
*/
error AddressEmptyCode(address target);
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
if (address(this).balance < amount) {
revert Errors.InsufficientBalance(address(this).balance, amount);
}
(bool success, bytes memory returndata) = recipient.call{value: amount}("");
if (!success) {
_revert(returndata);
}
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason or custom error, it is bubbled
* up by this function (like regular Solidity function calls). However, if
* the call reverted with no returned reason, this function reverts with a
* {Errors.FailedCall} error.
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*/
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
if (address(this).balance < value) {
revert Errors.InsufficientBalance(address(this).balance, value);
}
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata);
}
/**
* @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target
* was not a contract or bubbling up the revert reason (falling back to {Errors.FailedCall}) in case
* of an unsuccessful call.
*/
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata
) internal view returns (bytes memory) {
if (!success) {
_revert(returndata);
} else {
// only check if target is a contract if the call was successful and the return data is empty
// otherwise we already know that it was a contract
if (returndata.length == 0 && target.code.length == 0) {
revert AddressEmptyCode(target);
}
return returndata;
}
}
/**
* @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the
* revert reason or with a default {Errors.FailedCall} error.
*/
function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {
if (!success) {
_revert(returndata);
} else {
return returndata;
}
}
/**
* @dev Reverts with returndata if present. Otherwise reverts with {Errors.FailedCall}.
*/
function _revert(bytes memory returndata) private pure {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
assembly ("memory-safe") {
revert(add(returndata, 0x20), mload(returndata))
}
} else {
revert Errors.FailedCall();
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.3.0) (utils/cryptography/EIP712.sol)
pragma solidity ^0.8.20;
import {MessageHashUtils} from "./MessageHashUtils.sol";
import {ShortStrings, ShortString} from "../ShortStrings.sol";
import {IERC5267} from "../../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 scheme specified in the EIP requires a domain separator and a hash of the typed structured data, whose
* encoding is very generic and therefore its implementation in Solidity is not feasible, thus this contract
* does not implement the encoding itself. Protocols need to implement the type-specific encoding they need in order to
* produce the hash of their typed data using a combination of `abi.encode` and `keccak256`.
*
* This contract implements the EIP-712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding
* scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA
* ({_hashTypedDataV4}).
*
* The implementation of the domain separator was designed to be as efficient as possible while still properly updating
* the chain id to protect against replay attacks on an eventual fork of the chain.
*
* NOTE: This contract implements the version of the encoding known as "v4", as implemented by the JSON RPC method
* https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].
*
* NOTE: 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.
*
* @custom:oz-upgrades-unsafe-allow state-variable-immutable
*/
abstract contract EIP712 is IERC5267 {
using ShortStrings for *;
bytes32 private constant TYPE_HASH =
keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)");
// 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;
bytes32 private immutable _hashedName;
bytes32 private immutable _hashedVersion;
ShortString private immutable _name;
ShortString private immutable _version;
// slither-disable-next-line constable-states
string private _nameFallback;
// slither-disable-next-line constable-states
string private _versionFallback;
/**
* @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 MessageHashUtils.toTypedDataHash(_domainSeparatorV4(), structHash);
}
/// @inheritdoc IERC5267
function eip712Domain()
public
view
virtual
returns (
bytes1 fields,
string memory name,
string memory version,
uint256 chainId,
address verifyingContract,
bytes32 salt,
uint256[] memory extensions
)
{
return (
hex"0f", // 01111
_EIP712Name(),
_EIP712Version(),
block.chainid,
address(this),
bytes32(0),
new uint256[](0)
);
}
/**
* @dev The name parameter for the EIP712 domain.
*
* NOTE: By default this function reads _name which is an immutable value.
* It only reads from storage if necessary (in case the value is too large to fit in a ShortString).
*/
// solhint-disable-next-line func-name-mixedcase
function _EIP712Name() internal view returns (string memory) {
return _name.toStringWithFallback(_nameFallback);
}
/**
* @dev The version parameter for the EIP712 domain.
*
* NOTE: By default this function reads _version which is an immutable value.
* It only reads from storage if necessary (in case the value is too large to fit in a ShortString).
*/
// solhint-disable-next-line func-name-mixedcase
function _EIP712Version() internal view returns (string memory) {
return _version.toStringWithFallback(_versionFallback);
}
}// SPDX-License-Identifier: MIT
///////////////////////////////////////////////////////////////////////////////
/// This program is free software: you can redistribute it and/or modify ///
/// it under the terms of the MIT Public License. ///
/// ///
/// This is a Proof Of Concept and is not intended for production use. ///
/// Tests are incomplete and it contracts have not been audited. ///
/// ///
/// It is distributed in the hope that it will be useful and insightful, ///
/// but WITHOUT ANY WARRANTY; without even the implied warranty of ///
/// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ///
///////////////////////////////////////////////////////////////////////////////
/// NB: This library will soon be depricated.
/// @title LawUtilities - Utility Functions for Powers Protocol Laws
/// @notice A library of helper functions used across Law contracts
/// @dev Provides common functionality for law implementation and validation
/// @author 7Cedars
// Regarding decoding calldata.
// Note that validating calldata is not possible at the moment.
// See this feature request: https://github.com/ethereum/solidity/issues/10381#issuecomment-1285986476
// The feature request has been open for almost five years(!) at time of writing.
pragma solidity 0.8.26;
import { ERC721 } from "../lib/openzeppelin-contracts/contracts/token/ERC721/ERC721.sol";
import { Powers } from "./Powers.sol";
import { ILaw } from "./interfaces/ILaw.sol";
import { PowersTypes } from "./interfaces/PowersTypes.sol";
// import "forge-std/Test.sol"; // for testing only. remove before deployment.
library LawUtilities {
//////////////////////////////////////////////////////////////
// ERRORS //
//////////////////////////////////////////////////////////////
error LawUtilities__ParentNotCompleted();
error LawUtilities__ParentBlocksCompletion();
error LawUtilities__ExecutionGapTooSmall();
error LawUtilities__ProposalNotSucceeded();
error LawUtilities__DeadlineNotPassed();
error LawUtilities__StringTooShort();
error LawUtilities__StringTooLong();
//////////////////////////////////////////////////////////////
// STORAGE POINTERS //
//////////////////////////////////////////////////////////////
/// @notice Structure to track transactions by account address
/// @dev Uses a mapping to store arrays of block numbers for each account
struct TransactionsByAccount {
mapping(address account => uint48[] blockNumber) transactions;
}
/////////////////////////////////////////////////////////////
// CHECKS //
/////////////////////////////////////////////////////////////
function checkStringLength(string memory name_, uint256 minLength, uint256 maxLength) external pure {
if (bytes(name_).length < minLength) {
revert LawUtilities__StringTooShort();
}
if (bytes(name_).length > maxLength) {
revert LawUtilities__StringTooLong();
}
}
/// @notice Checks if a parent law has been completed
/// @dev Checks if a parent law has been completed
/// @param conditions The conditionsuration parameters for the law
/// @param lawCalldata The calldata of the law
/// @param nonce The nonce of the law
function baseChecksAtPropose(
ILaw.Conditions memory conditions,
bytes memory lawCalldata,
address powers,
uint256 nonce
) external view {
// Check if parent law completion is required
if (conditions.needCompleted != 0) {
uint256 parentActionId = hashActionId(conditions.needCompleted, lawCalldata, nonce);
// console2.log("parentActionId", parentActionId);
uint8 stateLog = uint8(Powers(payable(powers)).state(parentActionId));
// console2.log("state", stateLog);
if (Powers(payable(powers)).state(parentActionId) != PowersTypes.ActionState.Fulfilled) {
revert LawUtilities__ParentNotCompleted();
}
}
// Check if parent law must not be completed
if (conditions.needNotCompleted != 0) {
uint256 parentActionId = hashActionId(conditions.needNotCompleted, lawCalldata, nonce);
if (Powers(payable(powers)).state(parentActionId) == PowersTypes.ActionState.Fulfilled) {
revert LawUtilities__ParentBlocksCompletion();
}
}
}
/// @notice Checks if a parent law has been completed
/// @dev Checks if a parent law has been completed
/// @param conditions The conditionsuration parameters for the law
/// @param lawCalldata The calldata of the law
/// @param nonce The nonce of the law
function baseChecksAtExecute(
ILaw.Conditions memory conditions,
bytes memory lawCalldata,
address powers,
uint256 nonce,
uint48[] memory executions,
uint16 lawId
) external view {
// Check execution throttling
if (conditions.throttleExecution != 0) {
if (
executions.length > 0 && block.number - executions[executions.length - 1] < conditions.throttleExecution
) {
revert LawUtilities__ExecutionGapTooSmall();
}
}
// Check if proposal vote succeeded
if (conditions.quorum != 0) {
uint256 actionId = hashActionId(lawId, lawCalldata, nonce);
if (Powers(payable(powers)).state(actionId) != PowersTypes.ActionState.Succeeded) {
revert LawUtilities__ProposalNotSucceeded();
}
}
// Check execution delay after proposal
if (conditions.delayExecution != 0) {
uint256 actionId = hashActionId(lawId, lawCalldata, nonce);
uint256 deadline = Powers(payable(powers)).getProposedActionDeadline(actionId);
if (deadline + conditions.delayExecution > block.number) {
revert LawUtilities__DeadlineNotPassed();
}
}
}
/////////////////////////////////////////////////////////////
// FUNCTIONS //
/////////////////////////////////////////////////////////////
/// @notice Verifies if an address owns any tokens from a specific NFT contract
/// @dev Checks the balance of the given address in the specified ERC721 contract
/// @param caller Address to check token ownership for
/// @param nftCheckAddress Address of the ERC721 contract
/// @return hasToken True if the caller owns at least one token
function nftCheck(address caller, address nftCheckAddress) external view returns (bool hasToken) {
hasToken = ERC721(nftCheckAddress).balanceOf(caller) > 0;
if (!hasToken) {
revert("Does not own token.");
}
}
/// @notice Checks if an address is blacklisted
/// @dev Queries a mapping contract to check if the address is blacklisted
/// @param caller Address to check blacklist status for
/// @param blacklistAddress Address of the blacklist contract
/// @return isBlacklisted True if the address is blacklisted
// function blacklistCheck(address caller, address blacklistAddress)
// internal
// pure
// returns (bool isBlacklisted)
// {
// isBlacklisted = AddressesMapping(blacklistAddress).addresses(caller);
// if (isBlacklisted) {
// revert ("Is blacklisted.");
// }
// }
/// @notice Verifies if an address has all specified roles
/// @dev Checks each role against the Powers contract's role system
/// @param caller Address to check roles for
/// @param roles Array of role IDs to check
function hasRoleCheck(address caller, uint32[] memory roles, address powers) external view {
for (uint32 i = 0; i < roles.length; i++) {
uint48 since = Powers(payable(powers)).hasRoleSince(caller, roles[i]);
if (since == 0) {
revert("Does not have role.");
}
}
}
/// @notice Verifies if an address does not have any of the specified roles
/// @dev Checks each role against the Powers contract's role system
/// @param caller Address to check roles for
/// @param roles Array of role IDs to check
function hasNotRoleCheck(address caller, uint32[] memory roles, address powers) external view {
for (uint32 i = 0; i < roles.length; i++) {
uint48 since = Powers(payable(powers)).hasRoleSince(caller, roles[i]);
if (since != 0) {
revert("Has role.");
}
}
}
/// @notice Logs a transaction for an account at a specific block
/// @dev Adds a block number to the account's transaction history
/// @param self The TransactionsByAccount storage structure
/// @param account The address of the account
/// @param blockNumber The block number to log
/// @return True if the transaction was successfully logged
/// see for explanation: https://docs.soliditylang.org/en/v0.8.29/contracts.html#libraries
function logTransaction(TransactionsByAccount storage self, address account, uint48 blockNumber)
external
returns (bool)
{
self.transactions[account].push(blockNumber);
return true;
}
/// @notice Checks if enough time has passed since the last transaction
/// @dev Verifies if the delay between transactions meets the minimum requirement
/// @param self The TransactionsByAccount storage structure
/// @param account The address of the account
/// @param delay The minimum number of blocks required between transactions
/// @return True if the delay requirement is met
function checkThrottle(TransactionsByAccount storage self, address account, uint48 delay)
external
view
returns (bool)
{
if (self.transactions[account].length == 0) {
return true;
}
uint48 lastTransaction = self.transactions[account][self.transactions[account].length - 1];
if (uint48(block.number) - lastTransaction < delay) {
revert("Delay not passed");
}
return true;
}
/// @notice Counts the number of transactions within a block range
/// @dev Iterates through transaction history to count transactions in the specified range
/// @param self The TransactionsByAccount storage structure
/// @param account The address of the account
/// @param start The starting block number
/// @param end The ending block number
/// @return numberOfTransactions The count of transactions within the range
function checkNumberOfTransactions(TransactionsByAccount storage self, address account, uint48 start, uint48 end)
external
view
returns (uint256 numberOfTransactions)
{
for (uint256 i = 0; i < self.transactions[account].length; i++) {
if (self.transactions[account][i] >= start && self.transactions[account][i] <= end) {
numberOfTransactions++;
}
}
return numberOfTransactions;
}
//////////////////////////////////////////////////////////////
// HELPER FUNCTIONS //
//////////////////////////////////////////////////////////////
/// @notice Creates a unique identifier for an action
/// @dev Hashes the combination of law address, calldata, and nonce
/// @param lawId Address of the law contract being called
/// @param lawCalldata Encoded function call data
/// @param nonce The nonce for the action
/// @return actionId Unique identifier for the action
function hashActionId(uint16 lawId, bytes memory lawCalldata, uint256 nonce)
public
pure
returns (uint256 actionId)
{
actionId = uint256(keccak256(abi.encode(lawId, lawCalldata, nonce)));
}
/// @notice Creates a unique identifier for a law, used for sandboxing executions of laws.
/// @dev Hashes the combination of law address and index
/// @param powers Address of the Powers contract
/// @param index Index of the law
/// @return lawHash Unique identifier for the law
function hashLaw(address powers, uint16 index) public pure returns (bytes32 lawHash) {
lawHash = keccak256(abi.encode(powers, index));
}
/// @notice Creates empty arrays for storing transaction data
/// @dev Initializes three arrays of the same length for targets, values, and calldata
/// @param length The desired length of the arrays
/// @return targets Array of target addresses
/// @return values Array of ETH values
/// @return calldatas Array of encoded function calls
function createEmptyArrays(uint256 length)
public
pure
returns (address[] memory targets, uint256[] memory values, bytes[] memory calldatas)
{
targets = new address[](length);
values = new uint256[](length);
calldatas = new bytes[](length);
}
/// @notice Converts a boolean array from calldata to a memory array
/// @dev Uses assembly to efficiently decode the boolean array from calldata
/// @param numBools The number of booleans to decode
/// @return boolArray The decoded boolean array
/// Note: written by Cursor AI.
function arrayifyBools(uint256 numBools) public pure returns (bool[] memory boolArray) {
assembly {
// Allocate memory for the array
boolArray := mload(0x40)
mstore(boolArray, numBools) // set array length
let dataOffset := 0x24 // skip 4 bytes selector, start at 0x04, but arrays start at 0x20
for { let i := 0 } lt(i, numBools) { i := add(i, 1) } {
// Each bool is 32 bytes
let value := calldataload(add(4, mul(i, 32)))
mstore(add(add(boolArray, 0x20), mul(i, 0x20)), iszero(iszero(value)))
}
// Update free memory pointer
mstore(0x40, add(add(boolArray, 0x20), mul(numBools, 0x20)))
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/ERC165.sol)
pragma solidity ^0.8.20;
import {IERC165} from "./IERC165.sol";
/**
* @dev Implementation of the {IERC165} interface.
*
* Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check
* for the additional interface id that will be supported. For example:
*
* ```solidity
* function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
* return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
* }
* ```
*/
abstract contract ERC165 is IERC165 {
/// @inheritdoc IERC165
function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {
return interfaceId == type(IERC165).interfaceId;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol)
pragma solidity >=0.4.16;
/**
* @dev Interface of the ERC-165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[ERC].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/
interface IERC165 {
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}// SPDX-License-Identifier: MIT
///////////////////////////////////////////////////////////////////////////////
/// This program is free software: you can redistribute it and/or modify ///
/// it under the terms of the MIT Public License. ///
/// ///
/// This is a Proof Of Concept and is not intended for production use. ///
/// Tests are incomplete and it contracts have not been audited. ///
/// ///
/// It is distributed in the hope that it will be useful and insightful, ///
/// but WITHOUT ANY WARRANTY; without even the implied warranty of ///
/// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ///
///////////////////////////////////////////////////////////////////////////////
/// @notice Errors used in {Law.sol}.
///
/// @dev Errors in implementations of law.sol have to use strings (as in revert("this is an error") instead of using custom function, to allow errors to bubble up.)
/// @author 7Cedars
///
pragma solidity 0.8.26;
interface LawErrors {
/// @notice Emitted when a law is called by a non-powers account.
error Law__OnlyPowers();
/// @notice Emitted when a zero address is used.
error Law__NoZeroAddress();
/// @notice Emitted when a proposal is not succeeded.
error Law__ProposalNotSucceeded();
/// @notice Emitted when a parent law is not set.
error Law__ParentLawNotSet();
/// @notice Emitted when a deadline is not set.
error Law__NoDeadlineSet();
/// @notice Emitted when a powers contract address is invalid.
error Law__InvalidPowersContractAddress();
/// @notice Emitted when a parent law is not completed.
error Law__ParentNotCompleted();
/// @notice Emitted when a parent law is not completed.
error Law__ParentBlocksCompletion();
/// @notice Emitted when a execution gap is too small.
error Law__ExecutionGapTooSmall();
/// @notice Emitted when a deadline is not passed.
error Law__DeadlineNotPassed();
}// SPDX-License-Identifier: MIT
///////////////////////////////////////////////////////////////////////////////
/// This program is free software: you can redistribute it and/or modify ///
/// it under the terms of the MIT Public License. ///
/// ///
/// This is a Proof Of Concept and is not intended for production use. ///
/// Tests are incomplete and it contracts have not been audited. ///
/// ///
/// It is distributed in the hope that it will be useful and insightful, ///
/// but WITHOUT ANY WARRANTY; without even the implied warranty of ///
/// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ///
///////////////////////////////////////////////////////////////////////////////
/// @notice Errors used in the Powers protocol.
/// Code derived from OpenZeppelin's Governor.sol contract and Haberdasher Labs Hats protocol.
///
/// @author 7Cedars
pragma solidity 0.8.26;
interface PowersErrors {
/// @notice Emitted when a function is called by an account that lacks the correct roleId.
error Powers__AccessDenied();
/// @notice Emitted when an action has already been initiated.
error Powers__ActionAlreadyInitiated();
/// @notice Emitted when an action has been cancelled.
error Powers__ActionCancelled();
/// @notice Emitted when an action has not been initiated yet.
error Powers__ActionNotRequested();
/// @notice Emitted when a callData is invalid.
error Powers__InvalidCallData();
/// @notice Emitted when a law did not pass its checks.
error Powers__LawDidNotPassChecks();
/// @notice Emitted when a law is not active.
error Powers__LawNotActive();
/// @notice Emitted when a function is called that does not need a vote.
error Powers__NoVoteNeeded();
/// @notice Emitted when a function is called from a contract that is not Powers.
error Powers__OnlyPowers();
/// @notice Emitted when an action is in an unexpected state.
error Powers__UnexpectedActionState();
/// @notice Emitted when a role is locked.
error Powers__LockedRole();
/// @notice Emitted when an incorrect interface is called.
error Powers__IncorrectInterface();
/// @notice Emitted when a proposed action is not active.
error Powers__ProposedActionNotActive();
/// @notice Emitted when a constitution has already been executed.
error Powers__ConstitutionAlreadyExecuted();
/// @notice Emitted when a law is already active.
error Powers__LawAlreadyActive();
/// @notice Emitted when a law is not adopted.
error Powers__AlreadyCastVote();
/// @notice Emitted when a vote type is invalid.
error Powers__InvalidVoteType();
/// @notice Emitted when a role is locked.
error Powers__CannotAddToPublicRole();
/// @notice Emitted when a zero address is added.
error Powers__CannotAddZeroAddress();
/// @notice Emitted when a name is invalid.
error Powers__InvalidName();
/// @notice Emitted when a law does not exist.
error Powers__LawDoesNotExist();
}// SPDX-License-Identifier: MIT
///////////////////////////////////////////////////////////////////////////////
/// This program is free software: you can redistribute it and/or modify ///
/// it under the terms of the MIT Public License. ///
/// ///
/// This is a Proof Of Concept and is not intended for production use. ///
/// Tests are incomplete and it contracts have not been audited. ///
/// ///
/// It is distributed in the hope that it will be useful and insightful, ///
/// but WITHOUT ANY WARRANTY; without even the implied warranty of ///
/// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ///
///////////////////////////////////////////////////////////////////////////////
///
/// @notice Events used in the Powers protocol.
/// Code derived from OpenZeppelin's Governor.sol contract and Haberdasher Labs Hats protocol.
///
/// @author 7Cedars
pragma solidity 0.8.26;
interface PowersEvents {
/// @notice Emitted when protocol is initialized.
/// @param contractAddress the address of the contract
/// @param name the name of the contract
/// @param uri the uri of the contract
event Powers__Initialized(address contractAddress, string name, string uri);
/// @notice Emitted when protocol receives funds.
/// @param value the amount of funds received
/// @param sender the address of the sender
event FundsReceived(uint256 value, address sender);
/// @notice Emitted when executive action is requested.
/// @param caller the address of the caller
/// @param lawId the id of the law
/// @param lawCalldata the calldata of the law
/// @param description the description of the law action
/// @param nonce the nonce of the action
event ActionRequested(
address indexed caller, uint16 indexed lawId, bytes lawCalldata, uint256 nonce, string description
);
/// @notice Emitted when an executive action has been executed.
/// @param lawId the id of the law
/// @param actionId the id of the action
/// @param targets the targets of the action
/// @param values the values of the action
/// @param calldatas the calldatas of the action
event ActionExecuted(uint16 indexed lawId, uint256 indexed actionId, address[] targets, uint256[] values, bytes[] calldatas);
/// @notice Emitted when a proposal is created.
/// @param actionId the id of the proposal
/// @param caller the address of the caller
/// @param lawId the id of the law
/// @param signature the signature of the proposal
/// @param executeCalldata the calldata to be passed to the law
/// @param voteStart the start of the voting period
/// @param voteEnd the end of the voting period
/// @param description the description of the proposal
event ProposedActionCreated(
uint256 indexed actionId,
address indexed caller,
uint16 indexed lawId,
string signature,
bytes executeCalldata,
uint256 voteStart,
uint256 voteEnd,
uint256 nonce,
string description
);
/// @notice Emitted when a proposal is cancelled.
/// @param actionId the id of the proposal
event ProposedActionCancelled(uint256 indexed actionId);
/// @notice Emitted when a vote is cast.
/// @param account the address of the account that cast the vote
/// @param actionId the id of the proposal
/// @param support support of the vote: Against, For or Abstain.
/// @param reason the reason for the vote
event VoteCast(address indexed account, uint256 indexed actionId, uint8 indexed support, string reason);
/// @notice Emitted when a role is set.
/// @param roleId the id of the role
/// @param account the address of the account that has the role
/// @param access whether the account has access to the role
event RoleSet(uint256 indexed roleId, address indexed account, bool indexed access);
/// @notice Emitted when a role is labelled.
/// @param roleId the id of the role
/// @param label the label assigned to the role
event RoleLabel(uint256 indexed roleId, string label);
/// @notice Emitted when a law is adopted.
/// @param lawId the id of the law
event LawAdopted(uint16 indexed lawId);
/// @notice Emitted when a law is revoked.
/// @param lawId the id of the law
event LawRevoked(uint16 indexed lawId);
/// @notice Emitted when a law is revived.
/// @param lawId the id of the law
event LawRevived(uint16 indexed lawId);
}// SPDX-License-Identifier: MIT
///////////////////////////////////////////////////////////////////////////////
/// This program is free software: you can redistribute it and/or modify ///
/// it under the terms of the MIT Public License. ///
/// ///
/// This is a Proof Of Concept and is not intended for production use. ///
/// Tests are incomplete and it contracts have not been audited. ///
/// ///
/// It is distributed in the hope that it will be useful and insightful, ///
/// but WITHOUT ANY WARRANTY; without even the implied warranty of ///
/// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ///
///////////////////////////////////////////////////////////////////////////////
///
/// @notice Types used in the Powers protocol. Code derived from OpenZeppelin's Governor.sol contract.
///
/// @author 7Cedars
pragma solidity 0.8.26;
import { ILaw } from "./ILaw.sol";
interface PowersTypes {
struct ActiveLaw {
address targetLaw; // 20 bytes
bool active; // 1
}
struct LawInitData {
string nameDescription; // 32 bytes
address targetLaw; // 20 bytes
bytes config; // 32 bytes
ILaw.Conditions conditions; // 104 bytes
}
/// @notice struct to keep track of a proposal.
///
/// @dev in contrast to other Governance protocols, a proposal in {Powers} always includes a reference to a law.
/// This enables the role restriction of governance processes in {Powers}.
///
/// @dev in contrast to other Governance protocols, votes are not weighted and can hence be a uint32, not a uint256.
/// @dev votes are logged at the proposal. In on struct. This is in contrast to other governance protocols where ProposalVote is a separate struct.
struct Action {
// slot 1. -- just does not fit, optmise later. £todo/
bool cancelled; // 1
bool requested; // 1
bool fulfilled; // 1
uint16 lawId; // 2
uint48 voteStart; // 6
uint32 voteDuration; // 4
// slot 2
address caller; // 20
uint32 againstVotes; // 4 as votes are not weighted, uint32 is sufficient to count number of votes. -- this is a big gas saver. As such, combining the proposalCore and ProposalVote is (I think) okay
uint32 forVotes; // 4
uint32 abstainVotes; // 4
// slots 3.. £check: have to check this out.
mapping(address voter => bool) hasVoted; // 20 ?
// note: We save lawCalldata ONCHAIN when executed. -- this will be mroe expensive, but it decreases dependence on external services.
bytes lawCalldata; // 32 ... and more.
string uri; // 32 bytes ... and more. uri to metadata (description, etc) of action. Markdown file supported by frontend, but in theory can be anything.
uint256 nonce; // 32 bytes
}
/// @notice enum for the state of a proposal.
///
/// @dev that a proposal cannot be set as 'executed' as in Governor.sol. It can only be set as 'completed'.
/// This is because execution logic in {Powers} is separated from the proposal logic.
enum ActionState {
Active,
Cancelled,
Defeated,
Succeeded,
Requested,
Fulfilled,
NonExistent
}
/// @notice Supported vote types. Matches Governor Bravo ordering.
enum VoteType {
Against,
For,
Abstain
}
/// @notice struct keeping track of
/// - an account's access to roleId
/// - the total amount of members of role (this enables role based voting).
struct Role {
mapping(address account => uint48 since) members;
uint256 amountMembers;
string label;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/Errors.sol)
pragma solidity ^0.8.20;
/**
* @dev Collection of common custom errors used in multiple contracts
*
* IMPORTANT: Backwards compatibility is not guaranteed in future versions of the library.
* It is recommended to avoid relying on the error API for critical functionality.
*
* _Available since v5.1._
*/
library Errors {
/**
* @dev The ETH balance of the account is not enough to perform the operation.
*/
error InsufficientBalance(uint256 balance, uint256 needed);
/**
* @dev A call to an address target failed. The target may have reverted.
*/
error FailedCall();
/**
* @dev The deployment failed.
*/
error FailedDeployment();
/**
* @dev A necessary precompile is missing.
*/
error MissingPrecompile(address);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.3.0) (utils/cryptography/MessageHashUtils.sol)
pragma solidity ^0.8.20;
import {Strings} from "../Strings.sol";
/**
* @dev Signature message hash utilities for producing digests to be consumed by {ECDSA} recovery or signing.
*
* The library provides methods for generating a hash of a message that conforms to the
* https://eips.ethereum.org/EIPS/eip-191[ERC-191] and https://eips.ethereum.org/EIPS/eip-712[EIP 712]
* specifications.
*/
library MessageHashUtils {
/**
* @dev Returns the keccak256 digest of an ERC-191 signed data with version
* `0x45` (`personal_sign` messages).
*
* The digest is calculated by prefixing a bytes32 `messageHash` with
* `"\x19Ethereum Signed Message:\n32"` and hashing the result. It corresponds with the
* hash signed when using the https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_sign[`eth_sign`] JSON-RPC method.
*
* NOTE: The `messageHash` parameter is intended to be the result of hashing a raw message with
* keccak256, although any bytes32 value can be safely used because the final digest will
* be re-hashed.
*
* See {ECDSA-recover}.
*/
function toEthSignedMessageHash(bytes32 messageHash) internal pure returns (bytes32 digest) {
assembly ("memory-safe") {
mstore(0x00, "\x19Ethereum Signed Message:\n32") // 32 is the bytes-length of messageHash
mstore(0x1c, messageHash) // 0x1c (28) is the length of the prefix
digest := keccak256(0x00, 0x3c) // 0x3c is the length of the prefix (0x1c) + messageHash (0x20)
}
}
/**
* @dev Returns the keccak256 digest of an ERC-191 signed data with version
* `0x45` (`personal_sign` messages).
*
* The digest is calculated by prefixing an arbitrary `message` with
* `"\x19Ethereum Signed Message:\n" + len(message)` and hashing the result. It corresponds with the
* hash signed when using the https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_sign[`eth_sign`] JSON-RPC method.
*
* See {ECDSA-recover}.
*/
function toEthSignedMessageHash(bytes memory message) internal pure returns (bytes32) {
return
keccak256(bytes.concat("\x19Ethereum Signed Message:\n", bytes(Strings.toString(message.length)), message));
}
/**
* @dev Returns the keccak256 digest of an ERC-191 signed data with version
* `0x00` (data with intended validator).
*
* The digest is calculated by prefixing an arbitrary `data` with `"\x19\x00"` and the intended
* `validator` address. Then hashing the result.
*
* See {ECDSA-recover}.
*/
function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) {
return keccak256(abi.encodePacked(hex"19_00", validator, data));
}
/**
* @dev Variant of {toDataWithIntendedValidatorHash-address-bytes} optimized for cases where `data` is a bytes32.
*/
function toDataWithIntendedValidatorHash(
address validator,
bytes32 messageHash
) internal pure returns (bytes32 digest) {
assembly ("memory-safe") {
mstore(0x00, hex"19_00")
mstore(0x02, shl(96, validator))
mstore(0x16, messageHash)
digest := keccak256(0x00, 0x36)
}
}
/**
* @dev Returns the keccak256 digest of an EIP-712 typed data (ERC-191 version `0x01`).
*
* The digest is calculated from a `domainSeparator` and a `structHash`, by prefixing them with
* `\x19\x01` and hashing the result. It corresponds to the hash signed by the
* https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`] JSON-RPC method as part of EIP-712.
*
* See {ECDSA-recover}.
*/
function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 digest) {
assembly ("memory-safe") {
let ptr := mload(0x40)
mstore(ptr, hex"19_01")
mstore(add(ptr, 0x02), domainSeparator)
mstore(add(ptr, 0x22), structHash)
digest := keccak256(ptr, 0x42)
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.3.0) (utils/ShortStrings.sol)
pragma solidity ^0.8.20;
import {StorageSlot} from "./StorageSlot.sol";
// | string | 0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA |
// | length | 0x BB |
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 using this library if
* they are short enough (up to 31 bytes) by packing them with their
* length (1 byte) in a single EVM word (32 bytes). Additionally, a
* fallback mechanism can be used for every other case.
*
* 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 {
// Used as an identifier for strings longer than 31 bytes.
bytes32 private constant FALLBACK_SENTINEL = 0x00000000000000000000000000000000000000000000000000000000000000FF;
error StringTooLong(string str);
error InvalidShortString();
/**
* @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 = byteLength(sstr);
// using `new string(len)` would work locally but is not memory safe.
string memory str = new string(32);
assembly ("memory-safe") {
mstore(str, len)
mstore(add(str, 0x20), sstr)
}
return str;
}
/**
* @dev Return the length of a `ShortString`.
*/
function byteLength(ShortString sstr) internal pure returns (uint256) {
uint256 result = uint256(ShortString.unwrap(sstr)) & 0xFF;
if (result > 31) {
revert InvalidShortString();
}
return result;
}
/**
* @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(FALLBACK_SENTINEL);
}
}
/**
* @dev Decode a string that was encoded to `ShortString` or written to storage using {toShortStringWithFallback}.
*/
function toStringWithFallback(ShortString value, string storage store) internal pure returns (string memory) {
if (ShortString.unwrap(value) != FALLBACK_SENTINEL) {
return toString(value);
} else {
return store;
}
}
/**
* @dev Return the length of a string that was encoded to `ShortString` or written to storage using
* {toShortStringWithFallback}.
*
* WARNING: This will return the "byte length" of the string. This may not reflect the actual length in terms of
* actual characters as the UTF-8 encoding of a single character can span over multiple bytes.
*/
function byteLengthWithFallback(ShortString value, string storage store) internal view returns (uint256) {
if (ShortString.unwrap(value) != FALLBACK_SENTINEL) {
return byteLength(value);
} else {
return bytes(store).length;
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC5267.sol)
pragma solidity >=0.4.16;
interface IERC5267 {
/**
* @dev MAY be emitted to signal that the domain could have changed.
*/
event EIP712DomainChanged();
/**
* @dev returns the fields and values that describe the domain separator used by this contract for EIP-712
* signature.
*/
function eip712Domain()
external
view
returns (
bytes1 fields,
string memory name,
string memory version,
uint256 chainId,
address verifyingContract,
bytes32 salt,
uint256[] memory extensions
);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC721/ERC721.sol)
pragma solidity ^0.8.20;
import {IERC721} from "./IERC721.sol";
import {IERC721Metadata} from "./extensions/IERC721Metadata.sol";
import {ERC721Utils} from "./utils/ERC721Utils.sol";
import {Context} from "../../utils/Context.sol";
import {Strings} from "../../utils/Strings.sol";
import {IERC165, ERC165} from "../../utils/introspection/ERC165.sol";
import {IERC721Errors} from "../../interfaces/draft-IERC6093.sol";
/**
* @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC-721] Non-Fungible Token Standard, including
* the Metadata extension, but not including the Enumerable extension, which is available separately as
* {ERC721Enumerable}.
*/
abstract contract ERC721 is Context, ERC165, IERC721, IERC721Metadata, IERC721Errors {
using Strings for uint256;
// Token name
string private _name;
// Token symbol
string private _symbol;
mapping(uint256 tokenId => address) private _owners;
mapping(address owner => uint256) private _balances;
mapping(uint256 tokenId => address) private _tokenApprovals;
mapping(address owner => mapping(address operator => bool)) private _operatorApprovals;
/**
* @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.
*/
constructor(string memory name_, string memory symbol_) {
_name = name_;
_symbol = symbol_;
}
/// @inheritdoc IERC165
function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {
return
interfaceId == type(IERC721).interfaceId ||
interfaceId == type(IERC721Metadata).interfaceId ||
super.supportsInterface(interfaceId);
}
/// @inheritdoc IERC721
function balanceOf(address owner) public view virtual returns (uint256) {
if (owner == address(0)) {
revert ERC721InvalidOwner(address(0));
}
return _balances[owner];
}
/// @inheritdoc IERC721
function ownerOf(uint256 tokenId) public view virtual returns (address) {
return _requireOwned(tokenId);
}
/// @inheritdoc IERC721Metadata
function name() public view virtual returns (string memory) {
return _name;
}
/// @inheritdoc IERC721Metadata
function symbol() public view virtual returns (string memory) {
return _symbol;
}
/// @inheritdoc IERC721Metadata
function tokenURI(uint256 tokenId) public view virtual returns (string memory) {
_requireOwned(tokenId);
string memory baseURI = _baseURI();
return bytes(baseURI).length > 0 ? string.concat(baseURI, tokenId.toString()) : "";
}
/**
* @dev Base URI for computing {tokenURI}. If set, the resulting URI for each
* token will be the concatenation of the `baseURI` and the `tokenId`. Empty
* by default, can be overridden in child contracts.
*/
function _baseURI() internal view virtual returns (string memory) {
return "";
}
/// @inheritdoc IERC721
function approve(address to, uint256 tokenId) public virtual {
_approve(to, tokenId, _msgSender());
}
/// @inheritdoc IERC721
function getApproved(uint256 tokenId) public view virtual returns (address) {
_requireOwned(tokenId);
return _getApproved(tokenId);
}
/// @inheritdoc IERC721
function setApprovalForAll(address operator, bool approved) public virtual {
_setApprovalForAll(_msgSender(), operator, approved);
}
/// @inheritdoc IERC721
function isApprovedForAll(address owner, address operator) public view virtual returns (bool) {
return _operatorApprovals[owner][operator];
}
/// @inheritdoc IERC721
function transferFrom(address from, address to, uint256 tokenId) public virtual {
if (to == address(0)) {
revert ERC721InvalidReceiver(address(0));
}
// Setting an "auth" arguments enables the `_isAuthorized` check which verifies that the token exists
// (from != 0). Therefore, it is not needed to verify that the return value is not 0 here.
address previousOwner = _update(to, tokenId, _msgSender());
if (previousOwner != from) {
revert ERC721IncorrectOwner(from, tokenId, previousOwner);
}
}
/// @inheritdoc IERC721
function safeTransferFrom(address from, address to, uint256 tokenId) public {
safeTransferFrom(from, to, tokenId, "");
}
/// @inheritdoc IERC721
function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory data) public virtual {
transferFrom(from, to, tokenId);
ERC721Utils.checkOnERC721Received(_msgSender(), from, to, tokenId, data);
}
/**
* @dev Returns the owner of the `tokenId`. Does NOT revert if token doesn't exist
*
* IMPORTANT: Any overrides to this function that add ownership of tokens not tracked by the
* core ERC-721 logic MUST be matched with the use of {_increaseBalance} to keep balances
* consistent with ownership. The invariant to preserve is that for any address `a` the value returned by
* `balanceOf(a)` must be equal to the number of tokens such that `_ownerOf(tokenId)` is `a`.
*/
function _ownerOf(uint256 tokenId) internal view virtual returns (address) {
return _owners[tokenId];
}
/**
* @dev Returns the approved address for `tokenId`. Returns 0 if `tokenId` is not minted.
*/
function _getApproved(uint256 tokenId) internal view virtual returns (address) {
return _tokenApprovals[tokenId];
}
/**
* @dev Returns whether `spender` is allowed to manage `owner`'s tokens, or `tokenId` in
* particular (ignoring whether it is owned by `owner`).
*
* WARNING: This function assumes that `owner` is the actual owner of `tokenId` and does not verify this
* assumption.
*/
function _isAuthorized(address owner, address spender, uint256 tokenId) internal view virtual returns (bool) {
return
spender != address(0) &&
(owner == spender || isApprovedForAll(owner, spender) || _getApproved(tokenId) == spender);
}
/**
* @dev Checks if `spender` can operate on `tokenId`, assuming the provided `owner` is the actual owner.
* Reverts if:
* - `spender` does not have approval from `owner` for `tokenId`.
* - `spender` does not have approval to manage all of `owner`'s assets.
*
* WARNING: This function assumes that `owner` is the actual owner of `tokenId` and does not verify this
* assumption.
*/
function _checkAuthorized(address owner, address spender, uint256 tokenId) internal view virtual {
if (!_isAuthorized(owner, spender, tokenId)) {
if (owner == address(0)) {
revert ERC721NonexistentToken(tokenId);
} else {
revert ERC721InsufficientApproval(spender, tokenId);
}
}
}
/**
* @dev Unsafe write access to the balances, used by extensions that "mint" tokens using an {ownerOf} override.
*
* NOTE: the value is limited to type(uint128).max. This protect against _balance overflow. It is unrealistic that
* a uint256 would ever overflow from increments when these increments are bounded to uint128 values.
*
* WARNING: Increasing an account's balance using this function tends to be paired with an override of the
* {_ownerOf} function to resolve the ownership of the corresponding tokens so that balances and ownership
* remain consistent with one another.
*/
function _increaseBalance(address account, uint128 value) internal virtual {
unchecked {
_balances[account] += value;
}
}
/**
* @dev Transfers `tokenId` from its current owner to `to`, or alternatively mints (or burns) if the current owner
* (or `to`) is the zero address. Returns the owner of the `tokenId` before the update.
*
* The `auth` argument is optional. If the value passed is non 0, then this function will check that
* `auth` is either the owner of the token, or approved to operate on the token (by the owner).
*
* Emits a {Transfer} event.
*
* NOTE: If overriding this function in a way that tracks balances, see also {_increaseBalance}.
*/
function _update(address to, uint256 tokenId, address auth) internal virtual returns (address) {
address from = _ownerOf(tokenId);
// Perform (optional) operator check
if (auth != address(0)) {
_checkAuthorized(from, auth, tokenId);
}
// Execute the update
if (from != address(0)) {
// Clear approval. No need to re-authorize or emit the Approval event
_approve(address(0), tokenId, address(0), false);
unchecked {
_balances[from] -= 1;
}
}
if (to != address(0)) {
unchecked {
_balances[to] += 1;
}
}
_owners[tokenId] = to;
emit Transfer(from, to, tokenId);
return from;
}
/**
* @dev Mints `tokenId` and transfers it to `to`.
*
* WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible
*
* Requirements:
*
* - `tokenId` must not exist.
* - `to` cannot be the zero address.
*
* Emits a {Transfer} event.
*/
function _mint(address to, uint256 tokenId) internal {
if (to == address(0)) {
revert ERC721InvalidReceiver(address(0));
}
address previousOwner = _update(to, tokenId, address(0));
if (previousOwner != address(0)) {
revert ERC721InvalidSender(address(0));
}
}
/**
* @dev Mints `tokenId`, transfers it to `to` and checks for `to` acceptance.
*
* Requirements:
*
* - `tokenId` must not exist.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function _safeMint(address to, uint256 tokenId) internal {
_safeMint(to, tokenId, "");
}
/**
* @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is
* forwarded in {IERC721Receiver-onERC721Received} to contract recipients.
*/
function _safeMint(address to, uint256 tokenId, bytes memory data) internal virtual {
_mint(to, tokenId);
ERC721Utils.checkOnERC721Received(_msgSender(), address(0), to, tokenId, data);
}
/**
* @dev Destroys `tokenId`.
* The approval is cleared when the token is burned.
* This is an internal function that does not check if the sender is authorized to operate on the token.
*
* Requirements:
*
* - `tokenId` must exist.
*
* Emits a {Transfer} event.
*/
function _burn(uint256 tokenId) internal {
address previousOwner = _update(address(0), tokenId, address(0));
if (previousOwner == address(0)) {
revert ERC721NonexistentToken(tokenId);
}
}
/**
* @dev Transfers `tokenId` from `from` to `to`.
* As opposed to {transferFrom}, this imposes no restrictions on msg.sender.
*
* Requirements:
*
* - `to` cannot be the zero address.
* - `tokenId` token must be owned by `from`.
*
* Emits a {Transfer} event.
*/
function _transfer(address from, address to, uint256 tokenId) internal {
if (to == address(0)) {
revert ERC721InvalidReceiver(address(0));
}
address previousOwner = _update(to, tokenId, address(0));
if (previousOwner == address(0)) {
revert ERC721NonexistentToken(tokenId);
} else if (previousOwner != from) {
revert ERC721IncorrectOwner(from, tokenId, previousOwner);
}
}
/**
* @dev Safely transfers `tokenId` token from `from` to `to`, checking that contract recipients
* are aware of the ERC-721 standard to prevent tokens from being forever locked.
*
* `data` is additional data, it has no specified format and it is sent in call to `to`.
*
* This internal function is like {safeTransferFrom} in the sense that it invokes
* {IERC721Receiver-onERC721Received} on the receiver, and can be used to e.g.
* implement alternative mechanisms to perform token transfer, such as signature-based.
*
* Requirements:
*
* - `tokenId` token must exist and be owned by `from`.
* - `to` cannot be the zero address.
* - `from` cannot be the zero address.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function _safeTransfer(address from, address to, uint256 tokenId) internal {
_safeTransfer(from, to, tokenId, "");
}
/**
* @dev Same as {xref-ERC721-_safeTransfer-address-address-uint256-}[`_safeTransfer`], with an additional `data` parameter which is
* forwarded in {IERC721Receiver-onERC721Received} to contract recipients.
*/
function _safeTransfer(address from, address to, uint256 tokenId, bytes memory data) internal virtual {
_transfer(from, to, tokenId);
ERC721Utils.checkOnERC721Received(_msgSender(), from, to, tokenId, data);
}
/**
* @dev Approve `to` to operate on `tokenId`
*
* The `auth` argument is optional. If the value passed is non 0, then this function will check that `auth` is
* either the owner of the token, or approved to operate on all tokens held by this owner.
*
* Emits an {Approval} event.
*
* Overrides to this logic should be done to the variant with an additional `bool emitEvent` argument.
*/
function _approve(address to, uint256 tokenId, address auth) internal {
_approve(to, tokenId, auth, true);
}
/**
* @dev Variant of `_approve` with an optional flag to enable or disable the {Approval} event. The event is not
* emitted in the context of transfers.
*/
function _approve(address to, uint256 tokenId, address auth, bool emitEvent) internal virtual {
// Avoid reading the owner unless necessary
if (emitEvent || auth != address(0)) {
address owner = _requireOwned(tokenId);
// We do not use _isAuthorized because single-token approvals should not be able to call approve
if (auth != address(0) && owner != auth && !isApprovedForAll(owner, auth)) {
revert ERC721InvalidApprover(auth);
}
if (emitEvent) {
emit Approval(owner, to, tokenId);
}
}
_tokenApprovals[tokenId] = to;
}
/**
* @dev Approve `operator` to operate on all of `owner` tokens
*
* Requirements:
* - operator can't be the address zero.
*
* Emits an {ApprovalForAll} event.
*/
function _setApprovalForAll(address owner, address operator, bool approved) internal virtual {
if (operator == address(0)) {
revert ERC721InvalidOperator(operator);
}
_operatorApprovals[owner][operator] = approved;
emit ApprovalForAll(owner, operator, approved);
}
/**
* @dev Reverts if the `tokenId` doesn't have a current owner (it hasn't been minted, or it has been burned).
* Returns the owner.
*
* Overrides to ownership logic should be done to {_ownerOf}.
*/
function _requireOwned(uint256 tokenId) internal view returns (address) {
address owner = _ownerOf(tokenId);
if (owner == address(0)) {
revert ERC721NonexistentToken(tokenId);
}
return owner;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.3.0) (utils/Strings.sol)
pragma solidity ^0.8.20;
import {Math} from "./math/Math.sol";
import {SafeCast} from "./math/SafeCast.sol";
import {SignedMath} from "./math/SignedMath.sol";
/**
* @dev String operations.
*/
library Strings {
using SafeCast for *;
bytes16 private constant HEX_DIGITS = "0123456789abcdef";
uint8 private constant ADDRESS_LENGTH = 20;
uint256 private constant SPECIAL_CHARS_LOOKUP =
(1 << 0x08) | // backspace
(1 << 0x09) | // tab
(1 << 0x0a) | // newline
(1 << 0x0c) | // form feed
(1 << 0x0d) | // carriage return
(1 << 0x22) | // double quote
(1 << 0x5c); // backslash
/**
* @dev The `value` string doesn't fit in the specified `length`.
*/
error StringsInsufficientHexLength(uint256 value, uint256 length);
/**
* @dev The string being parsed contains characters that are not in scope of the given base.
*/
error StringsInvalidChar();
/**
* @dev The string being parsed is not a properly formatted address.
*/
error StringsInvalidAddressFormat();
/**
* @dev Converts a `uint256` to its ASCII `string` decimal representation.
*/
function toString(uint256 value) internal pure returns (string memory) {
unchecked {
uint256 length = Math.log10(value) + 1;
string memory buffer = new string(length);
uint256 ptr;
assembly ("memory-safe") {
ptr := add(add(buffer, 0x20), length)
}
while (true) {
ptr--;
assembly ("memory-safe") {
mstore8(ptr, byte(mod(value, 10), HEX_DIGITS))
}
value /= 10;
if (value == 0) break;
}
return buffer;
}
}
/**
* @dev Converts a `int256` to its ASCII `string` decimal representation.
*/
function toStringSigned(int256 value) internal pure returns (string memory) {
return string.concat(value < 0 ? "-" : "", toString(SignedMath.abs(value)));
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
*/
function toHexString(uint256 value) internal pure returns (string memory) {
unchecked {
return toHexString(value, Math.log256(value) + 1);
}
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
*/
function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
uint256 localValue = value;
bytes memory buffer = new bytes(2 * length + 2);
buffer[0] = "0";
buffer[1] = "x";
for (uint256 i = 2 * length + 1; i > 1; --i) {
buffer[i] = HEX_DIGITS[localValue & 0xf];
localValue >>= 4;
}
if (localValue != 0) {
revert StringsInsufficientHexLength(value, length);
}
return string(buffer);
}
/**
* @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal
* representation.
*/
function toHexString(address addr) internal pure returns (string memory) {
return toHexString(uint256(uint160(addr)), ADDRESS_LENGTH);
}
/**
* @dev Converts an `address` with fixed length of 20 bytes to its checksummed ASCII `string` hexadecimal
* representation, according to EIP-55.
*/
function toChecksumHexString(address addr) internal pure returns (string memory) {
bytes memory buffer = bytes(toHexString(addr));
// hash the hex part of buffer (skip length + 2 bytes, length 40)
uint256 hashValue;
assembly ("memory-safe") {
hashValue := shr(96, keccak256(add(buffer, 0x22), 40))
}
for (uint256 i = 41; i > 1; --i) {
// possible values for buffer[i] are 48 (0) to 57 (9) and 97 (a) to 102 (f)
if (hashValue & 0xf > 7 && uint8(buffer[i]) > 96) {
// case shift by xoring with 0x20
buffer[i] ^= 0x20;
}
hashValue >>= 4;
}
return string(buffer);
}
/**
* @dev Returns true if the two strings are equal.
*/
function equal(string memory a, string memory b) internal pure returns (bool) {
return bytes(a).length == bytes(b).length && keccak256(bytes(a)) == keccak256(bytes(b));
}
/**
* @dev Parse a decimal string and returns the value as a `uint256`.
*
* Requirements:
* - The string must be formatted as `[0-9]*`
* - The result must fit into an `uint256` type
*/
function parseUint(string memory input) internal pure returns (uint256) {
return parseUint(input, 0, bytes(input).length);
}
/**
* @dev Variant of {parseUint-string} that parses a substring of `input` located between position `begin` (included) and
* `end` (excluded).
*
* Requirements:
* - The substring must be formatted as `[0-9]*`
* - The result must fit into an `uint256` type
*/
function parseUint(string memory input, uint256 begin, uint256 end) internal pure returns (uint256) {
(bool success, uint256 value) = tryParseUint(input, begin, end);
if (!success) revert StringsInvalidChar();
return value;
}
/**
* @dev Variant of {parseUint-string} that returns false if the parsing fails because of an invalid character.
*
* NOTE: This function will revert if the result does not fit in a `uint256`.
*/
function tryParseUint(string memory input) internal pure returns (bool success, uint256 value) {
return _tryParseUintUncheckedBounds(input, 0, bytes(input).length);
}
/**
* @dev Variant of {parseUint-string-uint256-uint256} that returns false if the parsing fails because of an invalid
* character.
*
* NOTE: This function will revert if the result does not fit in a `uint256`.
*/
function tryParseUint(
string memory input,
uint256 begin,
uint256 end
) internal pure returns (bool success, uint256 value) {
if (end > bytes(input).length || begin > end) return (false, 0);
return _tryParseUintUncheckedBounds(input, begin, end);
}
/**
* @dev Implementation of {tryParseUint-string-uint256-uint256} that does not check bounds. Caller should make sure that
* `begin <= end <= input.length`. Other inputs would result in undefined behavior.
*/
function _tryParseUintUncheckedBounds(
string memory input,
uint256 begin,
uint256 end
) private pure returns (bool success, uint256 value) {
bytes memory buffer = bytes(input);
uint256 result = 0;
for (uint256 i = begin; i < end; ++i) {
uint8 chr = _tryParseChr(bytes1(_unsafeReadBytesOffset(buffer, i)));
if (chr > 9) return (false, 0);
result *= 10;
result += chr;
}
return (true, result);
}
/**
* @dev Parse a decimal string and returns the value as a `int256`.
*
* Requirements:
* - The string must be formatted as `[-+]?[0-9]*`
* - The result must fit in an `int256` type.
*/
function parseInt(string memory input) internal pure returns (int256) {
return parseInt(input, 0, bytes(input).length);
}
/**
* @dev Variant of {parseInt-string} that parses a substring of `input` located between position `begin` (included) and
* `end` (excluded).
*
* Requirements:
* - The substring must be formatted as `[-+]?[0-9]*`
* - The result must fit in an `int256` type.
*/
function parseInt(string memory input, uint256 begin, uint256 end) internal pure returns (int256) {
(bool success, int256 value) = tryParseInt(input, begin, end);
if (!success) revert StringsInvalidChar();
return value;
}
/**
* @dev Variant of {parseInt-string} that returns false if the parsing fails because of an invalid character or if
* the result does not fit in a `int256`.
*
* NOTE: This function will revert if the absolute value of the result does not fit in a `uint256`.
*/
function tryParseInt(string memory input) internal pure returns (bool success, int256 value) {
return _tryParseIntUncheckedBounds(input, 0, bytes(input).length);
}
uint256 private constant ABS_MIN_INT256 = 2 ** 255;
/**
* @dev Variant of {parseInt-string-uint256-uint256} that returns false if the parsing fails because of an invalid
* character or if the result does not fit in a `int256`.
*
* NOTE: This function will revert if the absolute value of the result does not fit in a `uint256`.
*/
function tryParseInt(
string memory input,
uint256 begin,
uint256 end
) internal pure returns (bool success, int256 value) {
if (end > bytes(input).length || begin > end) return (false, 0);
return _tryParseIntUncheckedBounds(input, begin, end);
}
/**
* @dev Implementation of {tryParseInt-string-uint256-uint256} that does not check bounds. Caller should make sure that
* `begin <= end <= input.length`. Other inputs would result in undefined behavior.
*/
function _tryParseIntUncheckedBounds(
string memory input,
uint256 begin,
uint256 end
) private pure returns (bool success, int256 value) {
bytes memory buffer = bytes(input);
// Check presence of a negative sign.
bytes1 sign = begin == end ? bytes1(0) : bytes1(_unsafeReadBytesOffset(buffer, begin)); // don't do out-of-bound (possibly unsafe) read if sub-string is empty
bool positiveSign = sign == bytes1("+");
bool negativeSign = sign == bytes1("-");
uint256 offset = (positiveSign || negativeSign).toUint();
(bool absSuccess, uint256 absValue) = tryParseUint(input, begin + offset, end);
if (absSuccess && absValue < ABS_MIN_INT256) {
return (true, negativeSign ? -int256(absValue) : int256(absValue));
} else if (absSuccess && negativeSign && absValue == ABS_MIN_INT256) {
return (true, type(int256).min);
} else return (false, 0);
}
/**
* @dev Parse a hexadecimal string (with or without "0x" prefix), and returns the value as a `uint256`.
*
* Requirements:
* - The string must be formatted as `(0x)?[0-9a-fA-F]*`
* - The result must fit in an `uint256` type.
*/
function parseHexUint(string memory input) internal pure returns (uint256) {
return parseHexUint(input, 0, bytes(input).length);
}
/**
* @dev Variant of {parseHexUint-string} that parses a substring of `input` located between position `begin` (included) and
* `end` (excluded).
*
* Requirements:
* - The substring must be formatted as `(0x)?[0-9a-fA-F]*`
* - The result must fit in an `uint256` type.
*/
function parseHexUint(string memory input, uint256 begin, uint256 end) internal pure returns (uint256) {
(bool success, uint256 value) = tryParseHexUint(input, begin, end);
if (!success) revert StringsInvalidChar();
return value;
}
/**
* @dev Variant of {parseHexUint-string} that returns false if the parsing fails because of an invalid character.
*
* NOTE: This function will revert if the result does not fit in a `uint256`.
*/
function tryParseHexUint(string memory input) internal pure returns (bool success, uint256 value) {
return _tryParseHexUintUncheckedBounds(input, 0, bytes(input).length);
}
/**
* @dev Variant of {parseHexUint-string-uint256-uint256} that returns false if the parsing fails because of an
* invalid character.
*
* NOTE: This function will revert if the result does not fit in a `uint256`.
*/
function tryParseHexUint(
string memory input,
uint256 begin,
uint256 end
) internal pure returns (bool success, uint256 value) {
if (end > bytes(input).length || begin > end) return (false, 0);
return _tryParseHexUintUncheckedBounds(input, begin, end);
}
/**
* @dev Implementation of {tryParseHexUint-string-uint256-uint256} that does not check bounds. Caller should make sure that
* `begin <= end <= input.length`. Other inputs would result in undefined behavior.
*/
function _tryParseHexUintUncheckedBounds(
string memory input,
uint256 begin,
uint256 end
) private pure returns (bool success, uint256 value) {
bytes memory buffer = bytes(input);
// skip 0x prefix if present
bool hasPrefix = (end > begin + 1) && bytes2(_unsafeReadBytesOffset(buffer, begin)) == bytes2("0x"); // don't do out-of-bound (possibly unsafe) read if sub-string is empty
uint256 offset = hasPrefix.toUint() * 2;
uint256 result = 0;
for (uint256 i = begin + offset; i < end; ++i) {
uint8 chr = _tryParseChr(bytes1(_unsafeReadBytesOffset(buffer, i)));
if (chr > 15) return (false, 0);
result *= 16;
unchecked {
// Multiplying by 16 is equivalent to a shift of 4 bits (with additional overflow check).
// This guarantees that adding a value < 16 will not cause an overflow, hence the unchecked.
result += chr;
}
}
return (true, result);
}
/**
* @dev Parse a hexadecimal string (with or without "0x" prefix), and returns the value as an `address`.
*
* Requirements:
* - The string must be formatted as `(0x)?[0-9a-fA-F]{40}`
*/
function parseAddress(string memory input) internal pure returns (address) {
return parseAddress(input, 0, bytes(input).length);
}
/**
* @dev Variant of {parseAddress-string} that parses a substring of `input` located between position `begin` (included) and
* `end` (excluded).
*
* Requirements:
* - The substring must be formatted as `(0x)?[0-9a-fA-F]{40}`
*/
function parseAddress(string memory input, uint256 begin, uint256 end) internal pure returns (address) {
(bool success, address value) = tryParseAddress(input, begin, end);
if (!success) revert StringsInvalidAddressFormat();
return value;
}
/**
* @dev Variant of {parseAddress-string} that returns false if the parsing fails because the input is not a properly
* formatted address. See {parseAddress-string} requirements.
*/
function tryParseAddress(string memory input) internal pure returns (bool success, address value) {
return tryParseAddress(input, 0, bytes(input).length);
}
/**
* @dev Variant of {parseAddress-string-uint256-uint256} that returns false if the parsing fails because input is not a properly
* formatted address. See {parseAddress-string-uint256-uint256} requirements.
*/
function tryParseAddress(
string memory input,
uint256 begin,
uint256 end
) internal pure returns (bool success, address value) {
if (end > bytes(input).length || begin > end) return (false, address(0));
bool hasPrefix = (end > begin + 1) && bytes2(_unsafeReadBytesOffset(bytes(input), begin)) == bytes2("0x"); // don't do out-of-bound (possibly unsafe) read if sub-string is empty
uint256 expectedLength = 40 + hasPrefix.toUint() * 2;
// check that input is the correct length
if (end - begin == expectedLength) {
// length guarantees that this does not overflow, and value is at most type(uint160).max
(bool s, uint256 v) = _tryParseHexUintUncheckedBounds(input, begin, end);
return (s, address(uint160(v)));
} else {
return (false, address(0));
}
}
function _tryParseChr(bytes1 chr) private pure returns (uint8) {
uint8 value = uint8(chr);
// Try to parse `chr`:
// - Case 1: [0-9]
// - Case 2: [a-f]
// - Case 3: [A-F]
// - otherwise not supported
unchecked {
if (value > 47 && value < 58) value -= 48;
else if (value > 96 && value < 103) value -= 87;
else if (value > 64 && value < 71) value -= 55;
else return type(uint8).max;
}
return value;
}
/**
* @dev Escape special characters in JSON strings. This can be useful to prevent JSON injection in NFT metadata.
*
* WARNING: This function should only be used in double quoted JSON strings. Single quotes are not escaped.
*
* NOTE: This function escapes all unicode characters, and not just the ones in ranges defined in section 2.5 of
* RFC-4627 (U+0000 to U+001F, U+0022 and U+005C). ECMAScript's `JSON.parse` does recover escaped unicode
* characters that are not in this range, but other tooling may provide different results.
*/
function escapeJSON(string memory input) internal pure returns (string memory) {
bytes memory buffer = bytes(input);
bytes memory output = new bytes(2 * buffer.length); // worst case scenario
uint256 outputLength = 0;
for (uint256 i; i < buffer.length; ++i) {
bytes1 char = bytes1(_unsafeReadBytesOffset(buffer, i));
if (((SPECIAL_CHARS_LOOKUP & (1 << uint8(char))) != 0)) {
output[outputLength++] = "\\";
if (char == 0x08) output[outputLength++] = "b";
else if (char == 0x09) output[outputLength++] = "t";
else if (char == 0x0a) output[outputLength++] = "n";
else if (char == 0x0c) output[outputLength++] = "f";
else if (char == 0x0d) output[outputLength++] = "r";
else if (char == 0x5c) output[outputLength++] = "\\";
else if (char == 0x22) {
// solhint-disable-next-line quotes
output[outputLength++] = '"';
}
} else {
output[outputLength++] = char;
}
}
// write the actual length and deallocate unused memory
assembly ("memory-safe") {
mstore(output, outputLength)
mstore(0x40, add(output, shl(5, shr(5, add(outputLength, 63)))))
}
return string(output);
}
/**
* @dev Reads a bytes32 from a bytes array without bounds checking.
*
* NOTE: making this function internal would mean it could be used with memory unsafe offset, and marking the
* assembly block as such would prevent some optimizations.
*/
function _unsafeReadBytesOffset(bytes memory buffer, uint256 offset) private pure returns (bytes32 value) {
// This is not memory safe in the general case, but all calls to this private function are within bounds.
assembly ("memory-safe") {
value := mload(add(add(buffer, 0x20), offset))
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/StorageSlot.sol)
// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.
pragma solidity ^0.8.20;
/**
* @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 ERC-1967 implementation slot:
* ```solidity
* contract ERC1967 {
* // Define the slot. Alternatively, use the SlotDerivation library to derive the slot.
* bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
*
* function _getImplementation() internal view returns (address) {
* return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;
* }
*
* function _setImplementation(address newImplementation) internal {
* require(newImplementation.code.length > 0);
* StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
* }
* }
* ```
*
* TIP: Consider using this library along with {SlotDerivation}.
*/
library StorageSlot {
struct AddressSlot {
address value;
}
struct BooleanSlot {
bool value;
}
struct Bytes32Slot {
bytes32 value;
}
struct Uint256Slot {
uint256 value;
}
struct Int256Slot {
int256 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) {
assembly ("memory-safe") {
r.slot := slot
}
}
/**
* @dev Returns a `BooleanSlot` with member `value` located at `slot`.
*/
function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {
assembly ("memory-safe") {
r.slot := slot
}
}
/**
* @dev Returns a `Bytes32Slot` with member `value` located at `slot`.
*/
function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {
assembly ("memory-safe") {
r.slot := slot
}
}
/**
* @dev Returns a `Uint256Slot` with member `value` located at `slot`.
*/
function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {
assembly ("memory-safe") {
r.slot := slot
}
}
/**
* @dev Returns a `Int256Slot` with member `value` located at `slot`.
*/
function getInt256Slot(bytes32 slot) internal pure returns (Int256Slot storage r) {
assembly ("memory-safe") {
r.slot := slot
}
}
/**
* @dev Returns a `StringSlot` with member `value` located at `slot`.
*/
function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {
assembly ("memory-safe") {
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) {
assembly ("memory-safe") {
r.slot := store.slot
}
}
/**
* @dev Returns a `BytesSlot` with member `value` located at `slot`.
*/
function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {
assembly ("memory-safe") {
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) {
assembly ("memory-safe") {
r.slot := store.slot
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC721/IERC721.sol)
pragma solidity >=0.6.2;
import {IERC165} from "../../utils/introspection/IERC165.sol";
/**
* @dev Required interface of an ERC-721 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 ERC-721 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 ERC-721
* 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 address zero.
*
* 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 v5.0.0) (token/ERC721/extensions/IERC721Metadata.sol)
pragma solidity >=0.6.2;
import {IERC721} from "../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 v5.3.0) (token/ERC721/utils/ERC721Utils.sol)
pragma solidity ^0.8.20;
import {IERC721Receiver} from "../IERC721Receiver.sol";
import {IERC721Errors} from "../../../interfaces/draft-IERC6093.sol";
/**
* @dev Library that provide common ERC-721 utility functions.
*
* See https://eips.ethereum.org/EIPS/eip-721[ERC-721].
*
* _Available since v5.1._
*/
library ERC721Utils {
/**
* @dev Performs an acceptance check for the provided `operator` by calling {IERC721Receiver-onERC721Received}
* on the `to` address. The `operator` is generally the address that initiated the token transfer (i.e. `msg.sender`).
*
* The acceptance call is not executed and treated as a no-op if the target address doesn't contain code (i.e. an EOA).
* Otherwise, the recipient must implement {IERC721Receiver-onERC721Received} and return the acceptance magic value to accept
* the transfer.
*/
function checkOnERC721Received(
address operator,
address from,
address to,
uint256 tokenId,
bytes memory data
) internal {
if (to.code.length > 0) {
try IERC721Receiver(to).onERC721Received(operator, from, tokenId, data) returns (bytes4 retval) {
if (retval != IERC721Receiver.onERC721Received.selector) {
// Token rejected
revert IERC721Errors.ERC721InvalidReceiver(to);
}
} catch (bytes memory reason) {
if (reason.length == 0) {
// non-IERC721Receiver implementer
revert IERC721Errors.ERC721InvalidReceiver(to);
} else {
assembly ("memory-safe") {
revert(add(reason, 0x20), mload(reason))
}
}
}
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)
pragma solidity ^0.8.20;
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
function _contextSuffixLength() internal view virtual returns (uint256) {
return 0;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (interfaces/draft-IERC6093.sol)
pragma solidity >=0.8.4;
/**
* @dev Standard ERC-20 Errors
* Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-20 tokens.
*/
interface IERC20Errors {
/**
* @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.
* @param sender Address whose tokens are being transferred.
* @param balance Current balance for the interacting account.
* @param needed Minimum amount required to perform a transfer.
*/
error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed);
/**
* @dev Indicates a failure with the token `sender`. Used in transfers.
* @param sender Address whose tokens are being transferred.
*/
error ERC20InvalidSender(address sender);
/**
* @dev Indicates a failure with the token `receiver`. Used in transfers.
* @param receiver Address to which tokens are being transferred.
*/
error ERC20InvalidReceiver(address receiver);
/**
* @dev Indicates a failure with the `spender`’s `allowance`. Used in transfers.
* @param spender Address that may be allowed to operate on tokens without being their owner.
* @param allowance Amount of tokens a `spender` is allowed to operate with.
* @param needed Minimum amount required to perform a transfer.
*/
error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed);
/**
* @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
* @param approver Address initiating an approval operation.
*/
error ERC20InvalidApprover(address approver);
/**
* @dev Indicates a failure with the `spender` to be approved. Used in approvals.
* @param spender Address that may be allowed to operate on tokens without being their owner.
*/
error ERC20InvalidSpender(address spender);
}
/**
* @dev Standard ERC-721 Errors
* Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-721 tokens.
*/
interface IERC721Errors {
/**
* @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in ERC-20.
* Used in balance queries.
* @param owner Address of the current owner of a token.
*/
error ERC721InvalidOwner(address owner);
/**
* @dev Indicates a `tokenId` whose `owner` is the zero address.
* @param tokenId Identifier number of a token.
*/
error ERC721NonexistentToken(uint256 tokenId);
/**
* @dev Indicates an error related to the ownership over a particular token. Used in transfers.
* @param sender Address whose tokens are being transferred.
* @param tokenId Identifier number of a token.
* @param owner Address of the current owner of a token.
*/
error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner);
/**
* @dev Indicates a failure with the token `sender`. Used in transfers.
* @param sender Address whose tokens are being transferred.
*/
error ERC721InvalidSender(address sender);
/**
* @dev Indicates a failure with the token `receiver`. Used in transfers.
* @param receiver Address to which tokens are being transferred.
*/
error ERC721InvalidReceiver(address receiver);
/**
* @dev Indicates a failure with the `operator`’s approval. Used in transfers.
* @param operator Address that may be allowed to operate on tokens without being their owner.
* @param tokenId Identifier number of a token.
*/
error ERC721InsufficientApproval(address operator, uint256 tokenId);
/**
* @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
* @param approver Address initiating an approval operation.
*/
error ERC721InvalidApprover(address approver);
/**
* @dev Indicates a failure with the `operator` to be approved. Used in approvals.
* @param operator Address that may be allowed to operate on tokens without being their owner.
*/
error ERC721InvalidOperator(address operator);
}
/**
* @dev Standard ERC-1155 Errors
* Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-1155 tokens.
*/
interface IERC1155Errors {
/**
* @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.
* @param sender Address whose tokens are being transferred.
* @param balance Current balance for the interacting account.
* @param needed Minimum amount required to perform a transfer.
* @param tokenId Identifier number of a token.
*/
error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId);
/**
* @dev Indicates a failure with the token `sender`. Used in transfers.
* @param sender Address whose tokens are being transferred.
*/
error ERC1155InvalidSender(address sender);
/**
* @dev Indicates a failure with the token `receiver`. Used in transfers.
* @param receiver Address to which tokens are being transferred.
*/
error ERC1155InvalidReceiver(address receiver);
/**
* @dev Indicates a failure with the `operator`’s approval. Used in transfers.
* @param operator Address that may be allowed to operate on tokens without being their owner.
* @param owner Address of the current owner of a token.
*/
error ERC1155MissingApprovalForAll(address operator, address owner);
/**
* @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
* @param approver Address initiating an approval operation.
*/
error ERC1155InvalidApprover(address approver);
/**
* @dev Indicates a failure with the `operator` to be approved. Used in approvals.
* @param operator Address that may be allowed to operate on tokens without being their owner.
*/
error ERC1155InvalidOperator(address operator);
/**
* @dev Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation.
* Used in batch transfers.
* @param idsLength Length of the array of token identifiers
* @param valuesLength Length of the array of token amounts
*/
error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.3.0) (utils/math/Math.sol)
pragma solidity ^0.8.20;
import {Panic} from "../Panic.sol";
import {SafeCast} from "./SafeCast.sol";
/**
* @dev Standard math utilities missing in the Solidity language.
*/
library Math {
enum Rounding {
Floor, // Toward negative infinity
Ceil, // Toward positive infinity
Trunc, // Toward zero
Expand // Away from zero
}
/**
* @dev Return the 512-bit addition of two uint256.
*
* The result is stored in two 256 variables such that sum = high * 2²⁵⁶ + low.
*/
function add512(uint256 a, uint256 b) internal pure returns (uint256 high, uint256 low) {
assembly ("memory-safe") {
low := add(a, b)
high := lt(low, a)
}
}
/**
* @dev Return the 512-bit multiplication of two uint256.
*
* The result is stored in two 256 variables such that product = high * 2²⁵⁶ + low.
*/
function mul512(uint256 a, uint256 b) internal pure returns (uint256 high, uint256 low) {
// 512-bit multiply [high low] = x * y. Compute the product mod 2²⁵⁶ and mod 2²⁵⁶ - 1, then use
// the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
// variables such that product = high * 2²⁵⁶ + low.
assembly ("memory-safe") {
let mm := mulmod(a, b, not(0))
low := mul(a, b)
high := sub(sub(mm, low), lt(mm, low))
}
}
/**
* @dev Returns the addition of two unsigned integers, with a success flag (no overflow).
*/
function tryAdd(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {
unchecked {
uint256 c = a + b;
success = c >= a;
result = c * SafeCast.toUint(success);
}
}
/**
* @dev Returns the subtraction of two unsigned integers, with a success flag (no overflow).
*/
function trySub(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {
unchecked {
uint256 c = a - b;
success = c <= a;
result = c * SafeCast.toUint(success);
}
}
/**
* @dev Returns the multiplication of two unsigned integers, with a success flag (no overflow).
*/
function tryMul(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {
unchecked {
uint256 c = a * b;
assembly ("memory-safe") {
// Only true when the multiplication doesn't overflow
// (c / a == b) || (a == 0)
success := or(eq(div(c, a), b), iszero(a))
}
// equivalent to: success ? c : 0
result = c * SafeCast.toUint(success);
}
}
/**
* @dev Returns the division of two unsigned integers, with a success flag (no division by zero).
*/
function tryDiv(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {
unchecked {
success = b > 0;
assembly ("memory-safe") {
// The `DIV` opcode returns zero when the denominator is 0.
result := div(a, b)
}
}
}
/**
* @dev Returns the remainder of dividing two unsigned integers, with a success flag (no division by zero).
*/
function tryMod(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {
unchecked {
success = b > 0;
assembly ("memory-safe") {
// The `MOD` opcode returns zero when the denominator is 0.
result := mod(a, b)
}
}
}
/**
* @dev Unsigned saturating addition, bounds to `2²⁵⁶ - 1` instead of overflowing.
*/
function saturatingAdd(uint256 a, uint256 b) internal pure returns (uint256) {
(bool success, uint256 result) = tryAdd(a, b);
return ternary(success, result, type(uint256).max);
}
/**
* @dev Unsigned saturating subtraction, bounds to zero instead of overflowing.
*/
function saturatingSub(uint256 a, uint256 b) internal pure returns (uint256) {
(, uint256 result) = trySub(a, b);
return result;
}
/**
* @dev Unsigned saturating multiplication, bounds to `2²⁵⁶ - 1` instead of overflowing.
*/
function saturatingMul(uint256 a, uint256 b) internal pure returns (uint256) {
(bool success, uint256 result) = tryMul(a, b);
return ternary(success, result, type(uint256).max);
}
/**
* @dev Branchless ternary evaluation for `a ? b : c`. Gas costs are constant.
*
* IMPORTANT: This function may reduce bytecode size and consume less gas when used standalone.
* However, the compiler may optimize Solidity ternary operations (i.e. `a ? b : c`) to only compute
* one branch when needed, making this function more expensive.
*/
function ternary(bool condition, uint256 a, uint256 b) internal pure returns (uint256) {
unchecked {
// branchless ternary works because:
// b ^ (a ^ b) == a
// b ^ 0 == b
return b ^ ((a ^ b) * SafeCast.toUint(condition));
}
}
/**
* @dev Returns the largest of two numbers.
*/
function max(uint256 a, uint256 b) internal pure returns (uint256) {
return ternary(a > b, a, b);
}
/**
* @dev Returns the smallest of two numbers.
*/
function min(uint256 a, uint256 b) internal pure returns (uint256) {
return ternary(a < b, a, b);
}
/**
* @dev Returns the average of two numbers. The result is rounded towards
* zero.
*/
function average(uint256 a, uint256 b) internal pure returns (uint256) {
// (a + b) / 2 can overflow.
return (a & b) + (a ^ b) / 2;
}
/**
* @dev Returns the ceiling of the division of two numbers.
*
* This differs from standard division with `/` in that it rounds towards infinity instead
* of rounding towards zero.
*/
function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
if (b == 0) {
// Guarantee the same behavior as in a regular Solidity division.
Panic.panic(Panic.DIVISION_BY_ZERO);
}
// The following calculation ensures accurate ceiling division without overflow.
// Since a is non-zero, (a - 1) / b will not overflow.
// The largest possible result occurs when (a - 1) / b is type(uint256).max,
// but the largest value we can obtain is type(uint256).max - 1, which happens
// when a = type(uint256).max and b = 1.
unchecked {
return SafeCast.toUint(a > 0) * ((a - 1) / b + 1);
}
}
/**
* @dev Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or
* denominator == 0.
*
* Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) with further edits by
* Uniswap Labs also under MIT license.
*/
function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {
unchecked {
(uint256 high, uint256 low) = mul512(x, y);
// Handle non-overflow cases, 256 by 256 division.
if (high == 0) {
// Solidity will revert if denominator == 0, unlike the div opcode on its own.
// The surrounding unchecked block does not change this fact.
// See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.
return low / denominator;
}
// Make sure the result is less than 2²⁵⁶. Also prevents denominator == 0.
if (denominator <= high) {
Panic.panic(ternary(denominator == 0, Panic.DIVISION_BY_ZERO, Panic.UNDER_OVERFLOW));
}
///////////////////////////////////////////////
// 512 by 256 division.
///////////////////////////////////////////////
// Make division exact by subtracting the remainder from [high low].
uint256 remainder;
assembly ("memory-safe") {
// Compute remainder using mulmod.
remainder := mulmod(x, y, denominator)
// Subtract 256 bit number from 512 bit number.
high := sub(high, gt(remainder, low))
low := sub(low, remainder)
}
// Factor powers of two out of denominator and compute largest power of two divisor of denominator.
// Always >= 1. See https://cs.stackexchange.com/q/138556/92363.
uint256 twos = denominator & (0 - denominator);
assembly ("memory-safe") {
// Divide denominator by twos.
denominator := div(denominator, twos)
// Divide [high low] by twos.
low := div(low, twos)
// Flip twos such that it is 2²⁵⁶ / twos. If twos is zero, then it becomes one.
twos := add(div(sub(0, twos), twos), 1)
}
// Shift in bits from high into low.
low |= high * twos;
// Invert denominator mod 2²⁵⁶. Now that denominator is an odd number, it has an inverse modulo 2²⁵⁶ such
// that denominator * inv ≡ 1 mod 2²⁵⁶. Compute the inverse by starting with a seed that is correct for
// four bits. That is, denominator * inv ≡ 1 mod 2⁴.
uint256 inverse = (3 * denominator) ^ 2;
// Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also
// works in modular arithmetic, doubling the correct bits in each step.
inverse *= 2 - denominator * inverse; // inverse mod 2⁸
inverse *= 2 - denominator * inverse; // inverse mod 2¹⁶
inverse *= 2 - denominator * inverse; // inverse mod 2³²
inverse *= 2 - denominator * inverse; // inverse mod 2⁶⁴
inverse *= 2 - denominator * inverse; // inverse mod 2¹²⁸
inverse *= 2 - denominator * inverse; // inverse mod 2²⁵⁶
// Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
// This will give us the correct result modulo 2²⁵⁶. Since the preconditions guarantee that the outcome is
// less than 2²⁵⁶, this is the final result. We don't need to compute the high bits of the result and high
// is no longer required.
result = low * inverse;
return result;
}
}
/**
* @dev Calculates x * y / denominator with full precision, following the selected rounding direction.
*/
function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {
return mulDiv(x, y, denominator) + SafeCast.toUint(unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0);
}
/**
* @dev Calculates floor(x * y >> n) with full precision. Throws if result overflows a uint256.
*/
function mulShr(uint256 x, uint256 y, uint8 n) internal pure returns (uint256 result) {
unchecked {
(uint256 high, uint256 low) = mul512(x, y);
if (high >= 1 << n) {
Panic.panic(Panic.UNDER_OVERFLOW);
}
return (high << (256 - n)) | (low >> n);
}
}
/**
* @dev Calculates x * y >> n with full precision, following the selected rounding direction.
*/
function mulShr(uint256 x, uint256 y, uint8 n, Rounding rounding) internal pure returns (uint256) {
return mulShr(x, y, n) + SafeCast.toUint(unsignedRoundsUp(rounding) && mulmod(x, y, 1 << n) > 0);
}
/**
* @dev Calculate the modular multiplicative inverse of a number in Z/nZ.
*
* If n is a prime, then Z/nZ is a field. In that case all elements are inversible, except 0.
* If n is not a prime, then Z/nZ is not a field, and some elements might not be inversible.
*
* If the input value is not inversible, 0 is returned.
*
* NOTE: If you know for sure that n is (big) a prime, it may be cheaper to use Fermat's little theorem and get the
* inverse using `Math.modExp(a, n - 2, n)`. See {invModPrime}.
*/
function invMod(uint256 a, uint256 n) internal pure returns (uint256) {
unchecked {
if (n == 0) return 0;
// The inverse modulo is calculated using the Extended Euclidean Algorithm (iterative version)
// Used to compute integers x and y such that: ax + ny = gcd(a, n).
// When the gcd is 1, then the inverse of a modulo n exists and it's x.
// ax + ny = 1
// ax = 1 + (-y)n
// ax ≡ 1 (mod n) # x is the inverse of a modulo n
// If the remainder is 0 the gcd is n right away.
uint256 remainder = a % n;
uint256 gcd = n;
// Therefore the initial coefficients are:
// ax + ny = gcd(a, n) = n
// 0a + 1n = n
int256 x = 0;
int256 y = 1;
while (remainder != 0) {
uint256 quotient = gcd / remainder;
(gcd, remainder) = (
// The old remainder is the next gcd to try.
remainder,
// Compute the next remainder.
// Can't overflow given that (a % gcd) * (gcd // (a % gcd)) <= gcd
// where gcd is at most n (capped to type(uint256).max)
gcd - remainder * quotient
);
(x, y) = (
// Increment the coefficient of a.
y,
// Decrement the coefficient of n.
// Can overflow, but the result is casted to uint256 so that the
// next value of y is "wrapped around" to a value between 0 and n - 1.
x - y * int256(quotient)
);
}
if (gcd != 1) return 0; // No inverse exists.
return ternary(x < 0, n - uint256(-x), uint256(x)); // Wrap the result if it's negative.
}
}
/**
* @dev Variant of {invMod}. More efficient, but only works if `p` is known to be a prime greater than `2`.
*
* From https://en.wikipedia.org/wiki/Fermat%27s_little_theorem[Fermat's little theorem], we know that if p is
* prime, then `a**(p-1) ≡ 1 mod p`. As a consequence, we have `a * a**(p-2) ≡ 1 mod p`, which means that
* `a**(p-2)` is the modular multiplicative inverse of a in Fp.
*
* NOTE: this function does NOT check that `p` is a prime greater than `2`.
*/
function invModPrime(uint256 a, uint256 p) internal view returns (uint256) {
unchecked {
return Math.modExp(a, p - 2, p);
}
}
/**
* @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m)
*
* Requirements:
* - modulus can't be zero
* - underlying staticcall to precompile must succeed
*
* IMPORTANT: The result is only valid if the underlying call succeeds. When using this function, make
* sure the chain you're using it on supports the precompiled contract for modular exponentiation
* at address 0x05 as specified in https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise,
* the underlying function will succeed given the lack of a revert, but the result may be incorrectly
* interpreted as 0.
*/
function modExp(uint256 b, uint256 e, uint256 m) internal view returns (uint256) {
(bool success, uint256 result) = tryModExp(b, e, m);
if (!success) {
Panic.panic(Panic.DIVISION_BY_ZERO);
}
return result;
}
/**
* @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m).
* It includes a success flag indicating if the operation succeeded. Operation will be marked as failed if trying
* to operate modulo 0 or if the underlying precompile reverted.
*
* IMPORTANT: The result is only valid if the success flag is true. When using this function, make sure the chain
* you're using it on supports the precompiled contract for modular exponentiation at address 0x05 as specified in
* https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise, the underlying function will succeed given the lack
* of a revert, but the result may be incorrectly interpreted as 0.
*/
function tryModExp(uint256 b, uint256 e, uint256 m) internal view returns (bool success, uint256 result) {
if (m == 0) return (false, 0);
assembly ("memory-safe") {
let ptr := mload(0x40)
// | Offset | Content | Content (Hex) |
// |-----------|------------|--------------------------------------------------------------------|
// | 0x00:0x1f | size of b | 0x0000000000000000000000000000000000000000000000000000000000000020 |
// | 0x20:0x3f | size of e | 0x0000000000000000000000000000000000000000000000000000000000000020 |
// | 0x40:0x5f | size of m | 0x0000000000000000000000000000000000000000000000000000000000000020 |
// | 0x60:0x7f | value of b | 0x<.............................................................b> |
// | 0x80:0x9f | value of e | 0x<.............................................................e> |
// | 0xa0:0xbf | value of m | 0x<.............................................................m> |
mstore(ptr, 0x20)
mstore(add(ptr, 0x20), 0x20)
mstore(add(ptr, 0x40), 0x20)
mstore(add(ptr, 0x60), b)
mstore(add(ptr, 0x80), e)
mstore(add(ptr, 0xa0), m)
// Given the result < m, it's guaranteed to fit in 32 bytes,
// so we can use the memory scratch space located at offset 0.
success := staticcall(gas(), 0x05, ptr, 0xc0, 0x00, 0x20)
result := mload(0x00)
}
}
/**
* @dev Variant of {modExp} that supports inputs of arbitrary length.
*/
function modExp(bytes memory b, bytes memory e, bytes memory m) internal view returns (bytes memory) {
(bool success, bytes memory result) = tryModExp(b, e, m);
if (!success) {
Panic.panic(Panic.DIVISION_BY_ZERO);
}
return result;
}
/**
* @dev Variant of {tryModExp} that supports inputs of arbitrary length.
*/
function tryModExp(
bytes memory b,
bytes memory e,
bytes memory m
) internal view returns (bool success, bytes memory result) {
if (_zeroBytes(m)) return (false, new bytes(0));
uint256 mLen = m.length;
// Encode call args in result and move the free memory pointer
result = abi.encodePacked(b.length, e.length, mLen, b, e, m);
assembly ("memory-safe") {
let dataPtr := add(result, 0x20)
// Write result on top of args to avoid allocating extra memory.
success := staticcall(gas(), 0x05, dataPtr, mload(result), dataPtr, mLen)
// Overwrite the length.
// result.length > returndatasize() is guaranteed because returndatasize() == m.length
mstore(result, mLen)
// Set the memory pointer after the returned data.
mstore(0x40, add(dataPtr, mLen))
}
}
/**
* @dev Returns whether the provided byte array is zero.
*/
function _zeroBytes(bytes memory byteArray) private pure returns (bool) {
for (uint256 i = 0; i < byteArray.length; ++i) {
if (byteArray[i] != 0) {
return false;
}
}
return true;
}
/**
* @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded
* towards zero.
*
* This method is based on Newton's method for computing square roots; the algorithm is restricted to only
* using integer operations.
*/
function sqrt(uint256 a) internal pure returns (uint256) {
unchecked {
// Take care of easy edge cases when a == 0 or a == 1
if (a <= 1) {
return a;
}
// In this function, we use Newton's method to get a root of `f(x) := x² - a`. It involves building a
// sequence x_n that converges toward sqrt(a). For each iteration x_n, we also define the error between
// the current value as `ε_n = | x_n - sqrt(a) |`.
//
// For our first estimation, we consider `e` the smallest power of 2 which is bigger than the square root
// of the target. (i.e. `2**(e-1) ≤ sqrt(a) < 2**e`). We know that `e ≤ 128` because `(2¹²⁸)² = 2²⁵⁶` is
// bigger than any uint256.
//
// By noticing that
// `2**(e-1) ≤ sqrt(a) < 2**e → (2**(e-1))² ≤ a < (2**e)² → 2**(2*e-2) ≤ a < 2**(2*e)`
// we can deduce that `e - 1` is `log2(a) / 2`. We can thus compute `x_n = 2**(e-1)` using a method similar
// to the msb function.
uint256 aa = a;
uint256 xn = 1;
if (aa >= (1 << 128)) {
aa >>= 128;
xn <<= 64;
}
if (aa >= (1 << 64)) {
aa >>= 64;
xn <<= 32;
}
if (aa >= (1 << 32)) {
aa >>= 32;
xn <<= 16;
}
if (aa >= (1 << 16)) {
aa >>= 16;
xn <<= 8;
}
if (aa >= (1 << 8)) {
aa >>= 8;
xn <<= 4;
}
if (aa >= (1 << 4)) {
aa >>= 4;
xn <<= 2;
}
if (aa >= (1 << 2)) {
xn <<= 1;
}
// We now have x_n such that `x_n = 2**(e-1) ≤ sqrt(a) < 2**e = 2 * x_n`. This implies ε_n ≤ 2**(e-1).
//
// We can refine our estimation by noticing that the middle of that interval minimizes the error.
// If we move x_n to equal 2**(e-1) + 2**(e-2), then we reduce the error to ε_n ≤ 2**(e-2).
// This is going to be our x_0 (and ε_0)
xn = (3 * xn) >> 1; // ε_0 := | x_0 - sqrt(a) | ≤ 2**(e-2)
// From here, Newton's method give us:
// x_{n+1} = (x_n + a / x_n) / 2
//
// One should note that:
// x_{n+1}² - a = ((x_n + a / x_n) / 2)² - a
// = ((x_n² + a) / (2 * x_n))² - a
// = (x_n⁴ + 2 * a * x_n² + a²) / (4 * x_n²) - a
// = (x_n⁴ + 2 * a * x_n² + a² - 4 * a * x_n²) / (4 * x_n²)
// = (x_n⁴ - 2 * a * x_n² + a²) / (4 * x_n²)
// = (x_n² - a)² / (2 * x_n)²
// = ((x_n² - a) / (2 * x_n))²
// ≥ 0
// Which proves that for all n ≥ 1, sqrt(a) ≤ x_n
//
// This gives us the proof of quadratic convergence of the sequence:
// ε_{n+1} = | x_{n+1} - sqrt(a) |
// = | (x_n + a / x_n) / 2 - sqrt(a) |
// = | (x_n² + a - 2*x_n*sqrt(a)) / (2 * x_n) |
// = | (x_n - sqrt(a))² / (2 * x_n) |
// = | ε_n² / (2 * x_n) |
// = ε_n² / | (2 * x_n) |
//
// For the first iteration, we have a special case where x_0 is known:
// ε_1 = ε_0² / | (2 * x_0) |
// ≤ (2**(e-2))² / (2 * (2**(e-1) + 2**(e-2)))
// ≤ 2**(2*e-4) / (3 * 2**(e-1))
// ≤ 2**(e-3) / 3
// ≤ 2**(e-3-log2(3))
// ≤ 2**(e-4.5)
//
// For the following iterations, we use the fact that, 2**(e-1) ≤ sqrt(a) ≤ x_n:
// ε_{n+1} = ε_n² / | (2 * x_n) |
// ≤ (2**(e-k))² / (2 * 2**(e-1))
// ≤ 2**(2*e-2*k) / 2**e
// ≤ 2**(e-2*k)
xn = (xn + a / xn) >> 1; // ε_1 := | x_1 - sqrt(a) | ≤ 2**(e-4.5) -- special case, see above
xn = (xn + a / xn) >> 1; // ε_2 := | x_2 - sqrt(a) | ≤ 2**(e-9) -- general case with k = 4.5
xn = (xn + a / xn) >> 1; // ε_3 := | x_3 - sqrt(a) | ≤ 2**(e-18) -- general case with k = 9
xn = (xn + a / xn) >> 1; // ε_4 := | x_4 - sqrt(a) | ≤ 2**(e-36) -- general case with k = 18
xn = (xn + a / xn) >> 1; // ε_5 := | x_5 - sqrt(a) | ≤ 2**(e-72) -- general case with k = 36
xn = (xn + a / xn) >> 1; // ε_6 := | x_6 - sqrt(a) | ≤ 2**(e-144) -- general case with k = 72
// Because e ≤ 128 (as discussed during the first estimation phase), we know have reached a precision
// ε_6 ≤ 2**(e-144) < 1. Given we're operating on integers, then we can ensure that xn is now either
// sqrt(a) or sqrt(a) + 1.
return xn - SafeCast.toUint(xn > a / xn);
}
}
/**
* @dev Calculates sqrt(a), following the selected rounding direction.
*/
function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = sqrt(a);
return result + SafeCast.toUint(unsignedRoundsUp(rounding) && result * result < a);
}
}
/**
* @dev Return the log in base 2 of a positive value rounded towards zero.
* Returns 0 if given 0.
*/
function log2(uint256 x) internal pure returns (uint256 r) {
// If value has upper 128 bits set, log2 result is at least 128
r = SafeCast.toUint(x > 0xffffffffffffffffffffffffffffffff) << 7;
// If upper 64 bits of 128-bit half set, add 64 to result
r |= SafeCast.toUint((x >> r) > 0xffffffffffffffff) << 6;
// If upper 32 bits of 64-bit half set, add 32 to result
r |= SafeCast.toUint((x >> r) > 0xffffffff) << 5;
// If upper 16 bits of 32-bit half set, add 16 to result
r |= SafeCast.toUint((x >> r) > 0xffff) << 4;
// If upper 8 bits of 16-bit half set, add 8 to result
r |= SafeCast.toUint((x >> r) > 0xff) << 3;
// If upper 4 bits of 8-bit half set, add 4 to result
r |= SafeCast.toUint((x >> r) > 0xf) << 2;
// Shifts value right by the current result and use it as an index into this lookup table:
//
// | x (4 bits) | index | table[index] = MSB position |
// |------------|---------|-----------------------------|
// | 0000 | 0 | table[0] = 0 |
// | 0001 | 1 | table[1] = 0 |
// | 0010 | 2 | table[2] = 1 |
// | 0011 | 3 | table[3] = 1 |
// | 0100 | 4 | table[4] = 2 |
// | 0101 | 5 | table[5] = 2 |
// | 0110 | 6 | table[6] = 2 |
// | 0111 | 7 | table[7] = 2 |
// | 1000 | 8 | table[8] = 3 |
// | 1001 | 9 | table[9] = 3 |
// | 1010 | 10 | table[10] = 3 |
// | 1011 | 11 | table[11] = 3 |
// | 1100 | 12 | table[12] = 3 |
// | 1101 | 13 | table[13] = 3 |
// | 1110 | 14 | table[14] = 3 |
// | 1111 | 15 | table[15] = 3 |
//
// The lookup table is represented as a 32-byte value with the MSB positions for 0-15 in the last 16 bytes.
assembly ("memory-safe") {
r := or(r, byte(shr(r, x), 0x0000010102020202030303030303030300000000000000000000000000000000))
}
}
/**
* @dev Return the log in base 2, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log2(value);
return result + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << result < value);
}
}
/**
* @dev Return the log in base 10 of a positive value rounded towards zero.
* Returns 0 if given 0.
*/
function log10(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >= 10 ** 64) {
value /= 10 ** 64;
result += 64;
}
if (value >= 10 ** 32) {
value /= 10 ** 32;
result += 32;
}
if (value >= 10 ** 16) {
value /= 10 ** 16;
result += 16;
}
if (value >= 10 ** 8) {
value /= 10 ** 8;
result += 8;
}
if (value >= 10 ** 4) {
value /= 10 ** 4;
result += 4;
}
if (value >= 10 ** 2) {
value /= 10 ** 2;
result += 2;
}
if (value >= 10 ** 1) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 10, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log10(value);
return result + SafeCast.toUint(unsignedRoundsUp(rounding) && 10 ** result < value);
}
}
/**
* @dev Return the log in base 256 of a positive value rounded towards zero.
* Returns 0 if given 0.
*
* Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
*/
function log256(uint256 x) internal pure returns (uint256 r) {
// If value has upper 128 bits set, log2 result is at least 128
r = SafeCast.toUint(x > 0xffffffffffffffffffffffffffffffff) << 7;
// If upper 64 bits of 128-bit half set, add 64 to result
r |= SafeCast.toUint((x >> r) > 0xffffffffffffffff) << 6;
// If upper 32 bits of 64-bit half set, add 32 to result
r |= SafeCast.toUint((x >> r) > 0xffffffff) << 5;
// If upper 16 bits of 32-bit half set, add 16 to result
r |= SafeCast.toUint((x >> r) > 0xffff) << 4;
// Add 1 if upper 8 bits of 16-bit half set, and divide accumulated result by 8
return (r >> 3) | SafeCast.toUint((x >> r) > 0xff);
}
/**
* @dev Return the log in base 256, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log256(value);
return result + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << (result << 3) < value);
}
}
/**
* @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers.
*/
function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) {
return uint8(rounding) % 2 == 1;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/math/SafeCast.sol)
// This file was procedurally generated from scripts/generate/templates/SafeCast.js.
pragma solidity ^0.8.20;
/**
* @dev Wrappers over Solidity's uintXX/intXX/bool casting operators with added overflow
* checks.
*
* Downcasting from uint256/int256 in Solidity does not revert on overflow. This can
* easily result in undesired exploitation or bugs, since developers usually
* assume that overflows raise errors. `SafeCast` restores this intuition by
* reverting the transaction when such an operation overflows.
*
* Using this library instead of the unchecked operations eliminates an entire
* class of bugs, so it's recommended to use it always.
*/
library SafeCast {
/**
* @dev Value doesn't fit in an uint of `bits` size.
*/
error SafeCastOverflowedUintDowncast(uint8 bits, uint256 value);
/**
* @dev An int value doesn't fit in an uint of `bits` size.
*/
error SafeCastOverflowedIntToUint(int256 value);
/**
* @dev Value doesn't fit in an int of `bits` size.
*/
error SafeCastOverflowedIntDowncast(uint8 bits, int256 value);
/**
* @dev An uint value doesn't fit in an int of `bits` size.
*/
error SafeCastOverflowedUintToInt(uint256 value);
/**
* @dev Returns the downcasted uint248 from uint256, reverting on
* overflow (when the input is greater than largest uint248).
*
* Counterpart to Solidity's `uint248` operator.
*
* Requirements:
*
* - input must fit into 248 bits
*/
function toUint248(uint256 value) internal pure returns (uint248) {
if (value > type(uint248).max) {
revert SafeCastOverflowedUintDowncast(248, value);
}
return uint248(value);
}
/**
* @dev Returns the downcasted uint240 from uint256, reverting on
* overflow (when the input is greater than largest uint240).
*
* Counterpart to Solidity's `uint240` operator.
*
* Requirements:
*
* - input must fit into 240 bits
*/
function toUint240(uint256 value) internal pure returns (uint240) {
if (value > type(uint240).max) {
revert SafeCastOverflowedUintDowncast(240, value);
}
return uint240(value);
}
/**
* @dev Returns the downcasted uint232 from uint256, reverting on
* overflow (when the input is greater than largest uint232).
*
* Counterpart to Solidity's `uint232` operator.
*
* Requirements:
*
* - input must fit into 232 bits
*/
function toUint232(uint256 value) internal pure returns (uint232) {
if (value > type(uint232).max) {
revert SafeCastOverflowedUintDowncast(232, value);
}
return uint232(value);
}
/**
* @dev Returns the downcasted uint224 from uint256, reverting on
* overflow (when the input is greater than largest uint224).
*
* Counterpart to Solidity's `uint224` operator.
*
* Requirements:
*
* - input must fit into 224 bits
*/
function toUint224(uint256 value) internal pure returns (uint224) {
if (value > type(uint224).max) {
revert SafeCastOverflowedUintDowncast(224, value);
}
return uint224(value);
}
/**
* @dev Returns the downcasted uint216 from uint256, reverting on
* overflow (when the input is greater than largest uint216).
*
* Counterpart to Solidity's `uint216` operator.
*
* Requirements:
*
* - input must fit into 216 bits
*/
function toUint216(uint256 value) internal pure returns (uint216) {
if (value > type(uint216).max) {
revert SafeCastOverflowedUintDowncast(216, value);
}
return uint216(value);
}
/**
* @dev Returns the downcasted uint208 from uint256, reverting on
* overflow (when the input is greater than largest uint208).
*
* Counterpart to Solidity's `uint208` operator.
*
* Requirements:
*
* - input must fit into 208 bits
*/
function toUint208(uint256 value) internal pure returns (uint208) {
if (value > type(uint208).max) {
revert SafeCastOverflowedUintDowncast(208, value);
}
return uint208(value);
}
/**
* @dev Returns the downcasted uint200 from uint256, reverting on
* overflow (when the input is greater than largest uint200).
*
* Counterpart to Solidity's `uint200` operator.
*
* Requirements:
*
* - input must fit into 200 bits
*/
function toUint200(uint256 value) internal pure returns (uint200) {
if (value > type(uint200).max) {
revert SafeCastOverflowedUintDowncast(200, value);
}
return uint200(value);
}
/**
* @dev Returns the downcasted uint192 from uint256, reverting on
* overflow (when the input is greater than largest uint192).
*
* Counterpart to Solidity's `uint192` operator.
*
* Requirements:
*
* - input must fit into 192 bits
*/
function toUint192(uint256 value) internal pure returns (uint192) {
if (value > type(uint192).max) {
revert SafeCastOverflowedUintDowncast(192, value);
}
return uint192(value);
}
/**
* @dev Returns the downcasted uint184 from uint256, reverting on
* overflow (when the input is greater than largest uint184).
*
* Counterpart to Solidity's `uint184` operator.
*
* Requirements:
*
* - input must fit into 184 bits
*/
function toUint184(uint256 value) internal pure returns (uint184) {
if (value > type(uint184).max) {
revert SafeCastOverflowedUintDowncast(184, value);
}
return uint184(value);
}
/**
* @dev Returns the downcasted uint176 from uint256, reverting on
* overflow (when the input is greater than largest uint176).
*
* Counterpart to Solidity's `uint176` operator.
*
* Requirements:
*
* - input must fit into 176 bits
*/
function toUint176(uint256 value) internal pure returns (uint176) {
if (value > type(uint176).max) {
revert SafeCastOverflowedUintDowncast(176, value);
}
return uint176(value);
}
/**
* @dev Returns the downcasted uint168 from uint256, reverting on
* overflow (when the input is greater than largest uint168).
*
* Counterpart to Solidity's `uint168` operator.
*
* Requirements:
*
* - input must fit into 168 bits
*/
function toUint168(uint256 value) internal pure returns (uint168) {
if (value > type(uint168).max) {
revert SafeCastOverflowedUintDowncast(168, value);
}
return uint168(value);
}
/**
* @dev Returns the downcasted uint160 from uint256, reverting on
* overflow (when the input is greater than largest uint160).
*
* Counterpart to Solidity's `uint160` operator.
*
* Requirements:
*
* - input must fit into 160 bits
*/
function toUint160(uint256 value) internal pure returns (uint160) {
if (value > type(uint160).max) {
revert SafeCastOverflowedUintDowncast(160, value);
}
return uint160(value);
}
/**
* @dev Returns the downcasted uint152 from uint256, reverting on
* overflow (when the input is greater than largest uint152).
*
* Counterpart to Solidity's `uint152` operator.
*
* Requirements:
*
* - input must fit into 152 bits
*/
function toUint152(uint256 value) internal pure returns (uint152) {
if (value > type(uint152).max) {
revert SafeCastOverflowedUintDowncast(152, value);
}
return uint152(value);
}
/**
* @dev Returns the downcasted uint144 from uint256, reverting on
* overflow (when the input is greater than largest uint144).
*
* Counterpart to Solidity's `uint144` operator.
*
* Requirements:
*
* - input must fit into 144 bits
*/
function toUint144(uint256 value) internal pure returns (uint144) {
if (value > type(uint144).max) {
revert SafeCastOverflowedUintDowncast(144, value);
}
return uint144(value);
}
/**
* @dev Returns the downcasted uint136 from uint256, reverting on
* overflow (when the input is greater than largest uint136).
*
* Counterpart to Solidity's `uint136` operator.
*
* Requirements:
*
* - input must fit into 136 bits
*/
function toUint136(uint256 value) internal pure returns (uint136) {
if (value > type(uint136).max) {
revert SafeCastOverflowedUintDowncast(136, value);
}
return uint136(value);
}
/**
* @dev Returns the downcasted uint128 from uint256, reverting on
* overflow (when the input is greater than largest uint128).
*
* Counterpart to Solidity's `uint128` operator.
*
* Requirements:
*
* - input must fit into 128 bits
*/
function toUint128(uint256 value) internal pure returns (uint128) {
if (value > type(uint128).max) {
revert SafeCastOverflowedUintDowncast(128, value);
}
return uint128(value);
}
/**
* @dev Returns the downcasted uint120 from uint256, reverting on
* overflow (when the input is greater than largest uint120).
*
* Counterpart to Solidity's `uint120` operator.
*
* Requirements:
*
* - input must fit into 120 bits
*/
function toUint120(uint256 value) internal pure returns (uint120) {
if (value > type(uint120).max) {
revert SafeCastOverflowedUintDowncast(120, value);
}
return uint120(value);
}
/**
* @dev Returns the downcasted uint112 from uint256, reverting on
* overflow (when the input is greater than largest uint112).
*
* Counterpart to Solidity's `uint112` operator.
*
* Requirements:
*
* - input must fit into 112 bits
*/
function toUint112(uint256 value) internal pure returns (uint112) {
if (value > type(uint112).max) {
revert SafeCastOverflowedUintDowncast(112, value);
}
return uint112(value);
}
/**
* @dev Returns the downcasted uint104 from uint256, reverting on
* overflow (when the input is greater than largest uint104).
*
* Counterpart to Solidity's `uint104` operator.
*
* Requirements:
*
* - input must fit into 104 bits
*/
function toUint104(uint256 value) internal pure returns (uint104) {
if (value > type(uint104).max) {
revert SafeCastOverflowedUintDowncast(104, value);
}
return uint104(value);
}
/**
* @dev Returns the downcasted uint96 from uint256, reverting on
* overflow (when the input is greater than largest uint96).
*
* Counterpart to Solidity's `uint96` operator.
*
* Requirements:
*
* - input must fit into 96 bits
*/
function toUint96(uint256 value) internal pure returns (uint96) {
if (value > type(uint96).max) {
revert SafeCastOverflowedUintDowncast(96, value);
}
return uint96(value);
}
/**
* @dev Returns the downcasted uint88 from uint256, reverting on
* overflow (when the input is greater than largest uint88).
*
* Counterpart to Solidity's `uint88` operator.
*
* Requirements:
*
* - input must fit into 88 bits
*/
function toUint88(uint256 value) internal pure returns (uint88) {
if (value > type(uint88).max) {
revert SafeCastOverflowedUintDowncast(88, value);
}
return uint88(value);
}
/**
* @dev Returns the downcasted uint80 from uint256, reverting on
* overflow (when the input is greater than largest uint80).
*
* Counterpart to Solidity's `uint80` operator.
*
* Requirements:
*
* - input must fit into 80 bits
*/
function toUint80(uint256 value) internal pure returns (uint80) {
if (value > type(uint80).max) {
revert SafeCastOverflowedUintDowncast(80, value);
}
return uint80(value);
}
/**
* @dev Returns the downcasted uint72 from uint256, reverting on
* overflow (when the input is greater than largest uint72).
*
* Counterpart to Solidity's `uint72` operator.
*
* Requirements:
*
* - input must fit into 72 bits
*/
function toUint72(uint256 value) internal pure returns (uint72) {
if (value > type(uint72).max) {
revert SafeCastOverflowedUintDowncast(72, value);
}
return uint72(value);
}
/**
* @dev Returns the downcasted uint64 from uint256, reverting on
* overflow (when the input is greater than largest uint64).
*
* Counterpart to Solidity's `uint64` operator.
*
* Requirements:
*
* - input must fit into 64 bits
*/
function toUint64(uint256 value) internal pure returns (uint64) {
if (value > type(uint64).max) {
revert SafeCastOverflowedUintDowncast(64, value);
}
return uint64(value);
}
/**
* @dev Returns the downcasted uint56 from uint256, reverting on
* overflow (when the input is greater than largest uint56).
*
* Counterpart to Solidity's `uint56` operator.
*
* Requirements:
*
* - input must fit into 56 bits
*/
function toUint56(uint256 value) internal pure returns (uint56) {
if (value > type(uint56).max) {
revert SafeCastOverflowedUintDowncast(56, value);
}
return uint56(value);
}
/**
* @dev Returns the downcasted uint48 from uint256, reverting on
* overflow (when the input is greater than largest uint48).
*
* Counterpart to Solidity's `uint48` operator.
*
* Requirements:
*
* - input must fit into 48 bits
*/
function toUint48(uint256 value) internal pure returns (uint48) {
if (value > type(uint48).max) {
revert SafeCastOverflowedUintDowncast(48, value);
}
return uint48(value);
}
/**
* @dev Returns the downcasted uint40 from uint256, reverting on
* overflow (when the input is greater than largest uint40).
*
* Counterpart to Solidity's `uint40` operator.
*
* Requirements:
*
* - input must fit into 40 bits
*/
function toUint40(uint256 value) internal pure returns (uint40) {
if (value > type(uint40).max) {
revert SafeCastOverflowedUintDowncast(40, value);
}
return uint40(value);
}
/**
* @dev Returns the downcasted uint32 from uint256, reverting on
* overflow (when the input is greater than largest uint32).
*
* Counterpart to Solidity's `uint32` operator.
*
* Requirements:
*
* - input must fit into 32 bits
*/
function toUint32(uint256 value) internal pure returns (uint32) {
if (value > type(uint32).max) {
revert SafeCastOverflowedUintDowncast(32, value);
}
return uint32(value);
}
/**
* @dev Returns the downcasted uint24 from uint256, reverting on
* overflow (when the input is greater than largest uint24).
*
* Counterpart to Solidity's `uint24` operator.
*
* Requirements:
*
* - input must fit into 24 bits
*/
function toUint24(uint256 value) internal pure returns (uint24) {
if (value > type(uint24).max) {
revert SafeCastOverflowedUintDowncast(24, value);
}
return uint24(value);
}
/**
* @dev Returns the downcasted uint16 from uint256, reverting on
* overflow (when the input is greater than largest uint16).
*
* Counterpart to Solidity's `uint16` operator.
*
* Requirements:
*
* - input must fit into 16 bits
*/
function toUint16(uint256 value) internal pure returns (uint16) {
if (value > type(uint16).max) {
revert SafeCastOverflowedUintDowncast(16, value);
}
return uint16(value);
}
/**
* @dev Returns the downcasted uint8 from uint256, reverting on
* overflow (when the input is greater than largest uint8).
*
* Counterpart to Solidity's `uint8` operator.
*
* Requirements:
*
* - input must fit into 8 bits
*/
function toUint8(uint256 value) internal pure returns (uint8) {
if (value > type(uint8).max) {
revert SafeCastOverflowedUintDowncast(8, value);
}
return uint8(value);
}
/**
* @dev Converts a signed int256 into an unsigned uint256.
*
* Requirements:
*
* - input must be greater than or equal to 0.
*/
function toUint256(int256 value) internal pure returns (uint256) {
if (value < 0) {
revert SafeCastOverflowedIntToUint(value);
}
return uint256(value);
}
/**
* @dev Returns the downcasted int248 from int256, reverting on
* overflow (when the input is less than smallest int248 or
* greater than largest int248).
*
* Counterpart to Solidity's `int248` operator.
*
* Requirements:
*
* - input must fit into 248 bits
*/
function toInt248(int256 value) internal pure returns (int248 downcasted) {
downcasted = int248(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(248, value);
}
}
/**
* @dev Returns the downcasted int240 from int256, reverting on
* overflow (when the input is less than smallest int240 or
* greater than largest int240).
*
* Counterpart to Solidity's `int240` operator.
*
* Requirements:
*
* - input must fit into 240 bits
*/
function toInt240(int256 value) internal pure returns (int240 downcasted) {
downcasted = int240(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(240, value);
}
}
/**
* @dev Returns the downcasted int232 from int256, reverting on
* overflow (when the input is less than smallest int232 or
* greater than largest int232).
*
* Counterpart to Solidity's `int232` operator.
*
* Requirements:
*
* - input must fit into 232 bits
*/
function toInt232(int256 value) internal pure returns (int232 downcasted) {
downcasted = int232(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(232, value);
}
}
/**
* @dev Returns the downcasted int224 from int256, reverting on
* overflow (when the input is less than smallest int224 or
* greater than largest int224).
*
* Counterpart to Solidity's `int224` operator.
*
* Requirements:
*
* - input must fit into 224 bits
*/
function toInt224(int256 value) internal pure returns (int224 downcasted) {
downcasted = int224(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(224, value);
}
}
/**
* @dev Returns the downcasted int216 from int256, reverting on
* overflow (when the input is less than smallest int216 or
* greater than largest int216).
*
* Counterpart to Solidity's `int216` operator.
*
* Requirements:
*
* - input must fit into 216 bits
*/
function toInt216(int256 value) internal pure returns (int216 downcasted) {
downcasted = int216(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(216, value);
}
}
/**
* @dev Returns the downcasted int208 from int256, reverting on
* overflow (when the input is less than smallest int208 or
* greater than largest int208).
*
* Counterpart to Solidity's `int208` operator.
*
* Requirements:
*
* - input must fit into 208 bits
*/
function toInt208(int256 value) internal pure returns (int208 downcasted) {
downcasted = int208(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(208, value);
}
}
/**
* @dev Returns the downcasted int200 from int256, reverting on
* overflow (when the input is less than smallest int200 or
* greater than largest int200).
*
* Counterpart to Solidity's `int200` operator.
*
* Requirements:
*
* - input must fit into 200 bits
*/
function toInt200(int256 value) internal pure returns (int200 downcasted) {
downcasted = int200(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(200, value);
}
}
/**
* @dev Returns the downcasted int192 from int256, reverting on
* overflow (when the input is less than smallest int192 or
* greater than largest int192).
*
* Counterpart to Solidity's `int192` operator.
*
* Requirements:
*
* - input must fit into 192 bits
*/
function toInt192(int256 value) internal pure returns (int192 downcasted) {
downcasted = int192(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(192, value);
}
}
/**
* @dev Returns the downcasted int184 from int256, reverting on
* overflow (when the input is less than smallest int184 or
* greater than largest int184).
*
* Counterpart to Solidity's `int184` operator.
*
* Requirements:
*
* - input must fit into 184 bits
*/
function toInt184(int256 value) internal pure returns (int184 downcasted) {
downcasted = int184(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(184, value);
}
}
/**
* @dev Returns the downcasted int176 from int256, reverting on
* overflow (when the input is less than smallest int176 or
* greater than largest int176).
*
* Counterpart to Solidity's `int176` operator.
*
* Requirements:
*
* - input must fit into 176 bits
*/
function toInt176(int256 value) internal pure returns (int176 downcasted) {
downcasted = int176(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(176, value);
}
}
/**
* @dev Returns the downcasted int168 from int256, reverting on
* overflow (when the input is less than smallest int168 or
* greater than largest int168).
*
* Counterpart to Solidity's `int168` operator.
*
* Requirements:
*
* - input must fit into 168 bits
*/
function toInt168(int256 value) internal pure returns (int168 downcasted) {
downcasted = int168(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(168, value);
}
}
/**
* @dev Returns the downcasted int160 from int256, reverting on
* overflow (when the input is less than smallest int160 or
* greater than largest int160).
*
* Counterpart to Solidity's `int160` operator.
*
* Requirements:
*
* - input must fit into 160 bits
*/
function toInt160(int256 value) internal pure returns (int160 downcasted) {
downcasted = int160(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(160, value);
}
}
/**
* @dev Returns the downcasted int152 from int256, reverting on
* overflow (when the input is less than smallest int152 or
* greater than largest int152).
*
* Counterpart to Solidity's `int152` operator.
*
* Requirements:
*
* - input must fit into 152 bits
*/
function toInt152(int256 value) internal pure returns (int152 downcasted) {
downcasted = int152(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(152, value);
}
}
/**
* @dev Returns the downcasted int144 from int256, reverting on
* overflow (when the input is less than smallest int144 or
* greater than largest int144).
*
* Counterpart to Solidity's `int144` operator.
*
* Requirements:
*
* - input must fit into 144 bits
*/
function toInt144(int256 value) internal pure returns (int144 downcasted) {
downcasted = int144(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(144, value);
}
}
/**
* @dev Returns the downcasted int136 from int256, reverting on
* overflow (when the input is less than smallest int136 or
* greater than largest int136).
*
* Counterpart to Solidity's `int136` operator.
*
* Requirements:
*
* - input must fit into 136 bits
*/
function toInt136(int256 value) internal pure returns (int136 downcasted) {
downcasted = int136(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(136, value);
}
}
/**
* @dev Returns the downcasted int128 from int256, reverting on
* overflow (when the input is less than smallest int128 or
* greater than largest int128).
*
* Counterpart to Solidity's `int128` operator.
*
* Requirements:
*
* - input must fit into 128 bits
*/
function toInt128(int256 value) internal pure returns (int128 downcasted) {
downcasted = int128(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(128, value);
}
}
/**
* @dev Returns the downcasted int120 from int256, reverting on
* overflow (when the input is less than smallest int120 or
* greater than largest int120).
*
* Counterpart to Solidity's `int120` operator.
*
* Requirements:
*
* - input must fit into 120 bits
*/
function toInt120(int256 value) internal pure returns (int120 downcasted) {
downcasted = int120(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(120, value);
}
}
/**
* @dev Returns the downcasted int112 from int256, reverting on
* overflow (when the input is less than smallest int112 or
* greater than largest int112).
*
* Counterpart to Solidity's `int112` operator.
*
* Requirements:
*
* - input must fit into 112 bits
*/
function toInt112(int256 value) internal pure returns (int112 downcasted) {
downcasted = int112(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(112, value);
}
}
/**
* @dev Returns the downcasted int104 from int256, reverting on
* overflow (when the input is less than smallest int104 or
* greater than largest int104).
*
* Counterpart to Solidity's `int104` operator.
*
* Requirements:
*
* - input must fit into 104 bits
*/
function toInt104(int256 value) internal pure returns (int104 downcasted) {
downcasted = int104(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(104, value);
}
}
/**
* @dev Returns the downcasted int96 from int256, reverting on
* overflow (when the input is less than smallest int96 or
* greater than largest int96).
*
* Counterpart to Solidity's `int96` operator.
*
* Requirements:
*
* - input must fit into 96 bits
*/
function toInt96(int256 value) internal pure returns (int96 downcasted) {
downcasted = int96(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(96, value);
}
}
/**
* @dev Returns the downcasted int88 from int256, reverting on
* overflow (when the input is less than smallest int88 or
* greater than largest int88).
*
* Counterpart to Solidity's `int88` operator.
*
* Requirements:
*
* - input must fit into 88 bits
*/
function toInt88(int256 value) internal pure returns (int88 downcasted) {
downcasted = int88(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(88, value);
}
}
/**
* @dev Returns the downcasted int80 from int256, reverting on
* overflow (when the input is less than smallest int80 or
* greater than largest int80).
*
* Counterpart to Solidity's `int80` operator.
*
* Requirements:
*
* - input must fit into 80 bits
*/
function toInt80(int256 value) internal pure returns (int80 downcasted) {
downcasted = int80(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(80, value);
}
}
/**
* @dev Returns the downcasted int72 from int256, reverting on
* overflow (when the input is less than smallest int72 or
* greater than largest int72).
*
* Counterpart to Solidity's `int72` operator.
*
* Requirements:
*
* - input must fit into 72 bits
*/
function toInt72(int256 value) internal pure returns (int72 downcasted) {
downcasted = int72(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(72, value);
}
}
/**
* @dev Returns the downcasted int64 from int256, reverting on
* overflow (when the input is less than smallest int64 or
* greater than largest int64).
*
* Counterpart to Solidity's `int64` operator.
*
* Requirements:
*
* - input must fit into 64 bits
*/
function toInt64(int256 value) internal pure returns (int64 downcasted) {
downcasted = int64(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(64, value);
}
}
/**
* @dev Returns the downcasted int56 from int256, reverting on
* overflow (when the input is less than smallest int56 or
* greater than largest int56).
*
* Counterpart to Solidity's `int56` operator.
*
* Requirements:
*
* - input must fit into 56 bits
*/
function toInt56(int256 value) internal pure returns (int56 downcasted) {
downcasted = int56(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(56, value);
}
}
/**
* @dev Returns the downcasted int48 from int256, reverting on
* overflow (when the input is less than smallest int48 or
* greater than largest int48).
*
* Counterpart to Solidity's `int48` operator.
*
* Requirements:
*
* - input must fit into 48 bits
*/
function toInt48(int256 value) internal pure returns (int48 downcasted) {
downcasted = int48(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(48, value);
}
}
/**
* @dev Returns the downcasted int40 from int256, reverting on
* overflow (when the input is less than smallest int40 or
* greater than largest int40).
*
* Counterpart to Solidity's `int40` operator.
*
* Requirements:
*
* - input must fit into 40 bits
*/
function toInt40(int256 value) internal pure returns (int40 downcasted) {
downcasted = int40(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(40, value);
}
}
/**
* @dev Returns the downcasted int32 from int256, reverting on
* overflow (when the input is less than smallest int32 or
* greater than largest int32).
*
* Counterpart to Solidity's `int32` operator.
*
* Requirements:
*
* - input must fit into 32 bits
*/
function toInt32(int256 value) internal pure returns (int32 downcasted) {
downcasted = int32(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(32, value);
}
}
/**
* @dev Returns the downcasted int24 from int256, reverting on
* overflow (when the input is less than smallest int24 or
* greater than largest int24).
*
* Counterpart to Solidity's `int24` operator.
*
* Requirements:
*
* - input must fit into 24 bits
*/
function toInt24(int256 value) internal pure returns (int24 downcasted) {
downcasted = int24(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(24, value);
}
}
/**
* @dev Returns the downcasted int16 from int256, reverting on
* overflow (when the input is less than smallest int16 or
* greater than largest int16).
*
* Counterpart to Solidity's `int16` operator.
*
* Requirements:
*
* - input must fit into 16 bits
*/
function toInt16(int256 value) internal pure returns (int16 downcasted) {
downcasted = int16(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(16, value);
}
}
/**
* @dev Returns the downcasted int8 from int256, reverting on
* overflow (when the input is less than smallest int8 or
* greater than largest int8).
*
* Counterpart to Solidity's `int8` operator.
*
* Requirements:
*
* - input must fit into 8 bits
*/
function toInt8(int256 value) internal pure returns (int8 downcasted) {
downcasted = int8(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(8, value);
}
}
/**
* @dev Converts an unsigned uint256 into a signed int256.
*
* Requirements:
*
* - input must be less than or equal to maxInt256.
*/
function toInt256(uint256 value) internal pure returns (int256) {
// Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive
if (value > uint256(type(int256).max)) {
revert SafeCastOverflowedUintToInt(value);
}
return int256(value);
}
/**
* @dev Cast a boolean (false or true) to a uint256 (0 or 1) with no jump.
*/
function toUint(bool b) internal pure returns (uint256 u) {
assembly ("memory-safe") {
u := iszero(iszero(b))
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/math/SignedMath.sol)
pragma solidity ^0.8.20;
import {SafeCast} from "./SafeCast.sol";
/**
* @dev Standard signed math utilities missing in the Solidity language.
*/
library SignedMath {
/**
* @dev Branchless ternary evaluation for `a ? b : c`. Gas costs are constant.
*
* IMPORTANT: This function may reduce bytecode size and consume less gas when used standalone.
* However, the compiler may optimize Solidity ternary operations (i.e. `a ? b : c`) to only compute
* one branch when needed, making this function more expensive.
*/
function ternary(bool condition, int256 a, int256 b) internal pure returns (int256) {
unchecked {
// branchless ternary works because:
// b ^ (a ^ b) == a
// b ^ 0 == b
return b ^ ((a ^ b) * int256(SafeCast.toUint(condition)));
}
}
/**
* @dev Returns the largest of two signed numbers.
*/
function max(int256 a, int256 b) internal pure returns (int256) {
return ternary(a > b, a, b);
}
/**
* @dev Returns the smallest of two signed numbers.
*/
function min(int256 a, int256 b) internal pure returns (int256) {
return ternary(a < b, a, b);
}
/**
* @dev Returns the average of two signed numbers without overflow.
* The result is rounded towards zero.
*/
function average(int256 a, int256 b) internal pure returns (int256) {
// Formula from the book "Hacker's Delight"
int256 x = (a & b) + ((a ^ b) >> 1);
return x + (int256(uint256(x) >> 255) & (a ^ b));
}
/**
* @dev Returns the absolute unsigned value of a signed value.
*/
function abs(int256 n) internal pure returns (uint256) {
unchecked {
// Formula from the "Bit Twiddling Hacks" by Sean Eron Anderson.
// Since `n` is a signed integer, the generated bytecode will use the SAR opcode to perform the right shift,
// taking advantage of the most significant (or "sign" bit) in two's complement representation.
// This opcode adds new most significant bits set to the value of the previous most significant bit. As a result,
// the mask will either be `bytes32(0)` (if n is positive) or `~bytes32(0)` (if n is negative).
int256 mask = n >> 255;
// A `bytes32(0)` mask leaves the input unchanged, while a `~bytes32(0)` mask complements it.
return uint256((n + mask) ^ mask);
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC721/IERC721Receiver.sol)
pragma solidity >=0.5.0;
/**
* @title ERC-721 token receiver interface
* @dev Interface for any contract that wants to support safeTransfers
* from ERC-721 asset contracts.
*/
interface IERC721Receiver {
/**
* @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}
* by `operator` from `from`, this function is called.
*
* It must return its Solidity selector to confirm the token transfer.
* If any other value is returned or the interface is not implemented by the recipient, the transfer will be
* reverted.
*
* The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.
*/
function onERC721Received(
address operator,
address from,
uint256 tokenId,
bytes calldata data
) external returns (bytes4);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/Panic.sol)
pragma solidity ^0.8.20;
/**
* @dev Helper library for emitting standardized panic codes.
*
* ```solidity
* contract Example {
* using Panic for uint256;
*
* // Use any of the declared internal constants
* function foo() { Panic.GENERIC.panic(); }
*
* // Alternatively
* function foo() { Panic.panic(Panic.GENERIC); }
* }
* ```
*
* Follows the list from https://github.com/ethereum/solidity/blob/v0.8.24/libsolutil/ErrorCodes.h[libsolutil].
*
* _Available since v5.1._
*/
// slither-disable-next-line unused-state
library Panic {
/// @dev generic / unspecified error
uint256 internal constant GENERIC = 0x00;
/// @dev used by the assert() builtin
uint256 internal constant ASSERT = 0x01;
/// @dev arithmetic underflow or overflow
uint256 internal constant UNDER_OVERFLOW = 0x11;
/// @dev division or modulo by zero
uint256 internal constant DIVISION_BY_ZERO = 0x12;
/// @dev enum conversion error
uint256 internal constant ENUM_CONVERSION_ERROR = 0x21;
/// @dev invalid encoding in storage
uint256 internal constant STORAGE_ENCODING_ERROR = 0x22;
/// @dev empty array pop
uint256 internal constant EMPTY_ARRAY_POP = 0x31;
/// @dev array out of bounds access
uint256 internal constant ARRAY_OUT_OF_BOUNDS = 0x32;
/// @dev resource error (too large allocation or too large array)
uint256 internal constant RESOURCE_ERROR = 0x41;
/// @dev calling invalid internal function
uint256 internal constant INVALID_INTERNAL_FUNCTION = 0x51;
/// @dev Reverts with a panic code. Recommended to use with
/// the internal constants with predefined codes.
function panic(uint256 code) internal pure {
assembly ("memory-safe") {
mstore(0x00, 0x4e487b71)
mstore(0x20, code)
revert(0x1c, 0x24)
}
}
}{
"remappings": [
"@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/",
"@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/",
"@powers/=lib/powers/solidity/src/",
"@powers-test/=lib/powers/solidity/test/",
"@powers-script/=lib/powers/solidity/script/",
"@forge-std/=lib/forge-std/src/",
"@solady/=lib/solady/src/",
"@solbase/=lib/solbase/src/",
"@chainlink/contracts/=lib/chainlink-evm/contracts/",
"@chainlink/contracts-ccip/=lib/chainlink-ccip/chains/evm/contracts/",
"ERC1155/=lib/powers/solidity/lib/hats-protocol/lib/ERC1155/",
"chainlink-ccip/=lib/chainlink-ccip/",
"chainlink-evm/=lib/chainlink-evm/",
"ds-test/=lib/openzeppelin-contracts/lib/forge-std/lib/ds-test/src/",
"erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/",
"forge-std/=lib/forge-std/src/",
"halmos-cheatcodes/=lib/openzeppelin-contracts/lib/halmos-cheatcodes/src/",
"hats-protocol/=lib/powers/solidity/lib/hats-protocol/",
"openzeppelin-contracts/=lib/openzeppelin-contracts/",
"powers/=lib/powers/",
"solady/=lib/powers/solidity/lib/hats-protocol/lib/solady/",
"solbase/=lib/powers/solidity/lib/hats-protocol/lib/solbase/src/",
"utils/=lib/powers/solidity/lib/hats-protocol/lib/utils/"
],
"optimizer": {
"enabled": true,
"runs": 200
},
"metadata": {
"useLiteralContent": false,
"bytecodeHash": "ipfs",
"appendCBOR": true
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"evmVersion": "cancun",
"viaIR": false
}Contract ABI
API[{"inputs":[{"internalType":"string","name":"name_","type":"string"},{"internalType":"string","name":"uri_","type":"string"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"FailedCall","type":"error"},{"inputs":[],"name":"InvalidShortString","type":"error"},{"inputs":[],"name":"Powers__AccessDenied","type":"error"},{"inputs":[],"name":"Powers__ActionAlreadyInitiated","type":"error"},{"inputs":[],"name":"Powers__ActionCancelled","type":"error"},{"inputs":[],"name":"Powers__ActionNotRequested","type":"error"},{"inputs":[],"name":"Powers__AlreadyCastVote","type":"error"},{"inputs":[],"name":"Powers__CannotAddToPublicRole","type":"error"},{"inputs":[],"name":"Powers__CannotAddZeroAddress","type":"error"},{"inputs":[],"name":"Powers__ConstitutionAlreadyExecuted","type":"error"},{"inputs":[],"name":"Powers__IncorrectInterface","type":"error"},{"inputs":[],"name":"Powers__InvalidCallData","type":"error"},{"inputs":[],"name":"Powers__InvalidName","type":"error"},{"inputs":[],"name":"Powers__InvalidVoteType","type":"error"},{"inputs":[],"name":"Powers__LawAlreadyActive","type":"error"},{"inputs":[],"name":"Powers__LawDidNotPassChecks","type":"error"},{"inputs":[],"name":"Powers__LawDoesNotExist","type":"error"},{"inputs":[],"name":"Powers__LawNotActive","type":"error"},{"inputs":[],"name":"Powers__LockedRole","type":"error"},{"inputs":[],"name":"Powers__NoVoteNeeded","type":"error"},{"inputs":[],"name":"Powers__OnlyPowers","type":"error"},{"inputs":[],"name":"Powers__ProposedActionNotActive","type":"error"},{"inputs":[],"name":"Powers__UnexpectedActionState","type":"error"},{"inputs":[{"internalType":"string","name":"str","type":"string"}],"name":"StringTooLong","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint16","name":"lawId","type":"uint16"},{"indexed":true,"internalType":"uint256","name":"actionId","type":"uint256"},{"indexed":false,"internalType":"address[]","name":"targets","type":"address[]"},{"indexed":false,"internalType":"uint256[]","name":"values","type":"uint256[]"},{"indexed":false,"internalType":"bytes[]","name":"calldatas","type":"bytes[]"}],"name":"ActionExecuted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":true,"internalType":"uint16","name":"lawId","type":"uint16"},{"indexed":false,"internalType":"bytes","name":"lawCalldata","type":"bytes"},{"indexed":false,"internalType":"uint256","name":"nonce","type":"uint256"},{"indexed":false,"internalType":"string","name":"description","type":"string"}],"name":"ActionRequested","type":"event"},{"anonymous":false,"inputs":[],"name":"EIP712DomainChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"},{"indexed":false,"internalType":"address","name":"sender","type":"address"}],"name":"FundsReceived","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint16","name":"lawId","type":"uint16"}],"name":"LawAdopted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint16","name":"lawId","type":"uint16"}],"name":"LawRevived","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint16","name":"lawId","type":"uint16"}],"name":"LawRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"contractAddress","type":"address"},{"indexed":false,"internalType":"string","name":"name","type":"string"},{"indexed":false,"internalType":"string","name":"uri","type":"string"}],"name":"Powers__Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"actionId","type":"uint256"}],"name":"ProposedActionCancelled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"actionId","type":"uint256"},{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":true,"internalType":"uint16","name":"lawId","type":"uint16"},{"indexed":false,"internalType":"string","name":"signature","type":"string"},{"indexed":false,"internalType":"bytes","name":"executeCalldata","type":"bytes"},{"indexed":false,"internalType":"uint256","name":"voteStart","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"voteEnd","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"nonce","type":"uint256"},{"indexed":false,"internalType":"string","name":"description","type":"string"}],"name":"ProposedActionCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"roleId","type":"uint256"},{"indexed":false,"internalType":"string","name":"label","type":"string"}],"name":"RoleLabel","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"roleId","type":"uint256"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"bool","name":"access","type":"bool"}],"name":"RoleSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"uint256","name":"actionId","type":"uint256"},{"indexed":true,"internalType":"uint8","name":"support","type":"uint8"},{"indexed":false,"internalType":"string","name":"reason","type":"string"}],"name":"VoteCast","type":"event"},{"inputs":[],"name":"ADMIN_ROLE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DENOMINATOR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PUBLIC_ROLE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"string","name":"nameDescription","type":"string"},{"internalType":"address","name":"targetLaw","type":"address"},{"internalType":"bytes","name":"config","type":"bytes"},{"components":[{"internalType":"uint256","name":"allowedRole","type":"uint256"},{"internalType":"uint16","name":"needCompleted","type":"uint16"},{"internalType":"uint48","name":"delayExecution","type":"uint48"},{"internalType":"uint48","name":"throttleExecution","type":"uint48"},{"internalType":"uint16","name":"readStateFrom","type":"uint16"},{"internalType":"uint32","name":"votingPeriod","type":"uint32"},{"internalType":"uint8","name":"quorum","type":"uint8"},{"internalType":"uint8","name":"succeedAt","type":"uint8"},{"internalType":"uint16","name":"needNotCompleted","type":"uint16"}],"internalType":"struct ILaw.Conditions","name":"conditions","type":"tuple"}],"internalType":"struct PowersTypes.LawInitData","name":"lawInitData","type":"tuple"}],"name":"adoptLaw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"roleId","type":"uint256"},{"internalType":"address","name":"account","type":"address"}],"name":"assignRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"caller","type":"address"},{"internalType":"uint16","name":"lawId","type":"uint16"}],"name":"canCallLaw","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"lawId","type":"uint16"},{"internalType":"bytes","name":"lawCalldata","type":"bytes"},{"internalType":"uint256","name":"nonce","type":"uint256"}],"name":"cancel","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"actionId","type":"uint256"},{"internalType":"uint8","name":"support","type":"uint8"}],"name":"castVote","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"actionId","type":"uint256"},{"internalType":"uint8","name":"support","type":"uint8"},{"internalType":"string","name":"reason","type":"string"}],"name":"castVoteWithReason","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"string","name":"nameDescription","type":"string"},{"internalType":"address","name":"targetLaw","type":"address"},{"internalType":"bytes","name":"config","type":"bytes"},{"components":[{"internalType":"uint256","name":"allowedRole","type":"uint256"},{"internalType":"uint16","name":"needCompleted","type":"uint16"},{"internalType":"uint48","name":"delayExecution","type":"uint48"},{"internalType":"uint48","name":"throttleExecution","type":"uint48"},{"internalType":"uint16","name":"readStateFrom","type":"uint16"},{"internalType":"uint32","name":"votingPeriod","type":"uint32"},{"internalType":"uint8","name":"quorum","type":"uint8"},{"internalType":"uint8","name":"succeedAt","type":"uint8"},{"internalType":"uint16","name":"needNotCompleted","type":"uint16"}],"internalType":"struct ILaw.Conditions","name":"conditions","type":"tuple"}],"internalType":"struct PowersTypes.LawInitData[]","name":"constituentLaws","type":"tuple[]"}],"name":"constitute","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":[{"internalType":"uint16","name":"lawId","type":"uint16"},{"internalType":"uint256","name":"actionId","type":"uint256"},{"internalType":"address[]","name":"targets","type":"address[]"},{"internalType":"uint256[]","name":"values","type":"uint256[]"},{"internalType":"bytes[]","name":"calldatas","type":"bytes[]"}],"name":"fulfill","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"actionId","type":"uint256"}],"name":"getActionCalldata","outputs":[{"internalType":"bytes","name":"callData","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"actionId","type":"uint256"}],"name":"getActionData","outputs":[{"internalType":"bool","name":"cancelled","type":"bool"},{"internalType":"bool","name":"requested","type":"bool"},{"internalType":"bool","name":"fulfilled","type":"bool"},{"internalType":"uint16","name":"lawId","type":"uint16"},{"internalType":"uint48","name":"voteStart","type":"uint48"},{"internalType":"uint32","name":"voteDuration","type":"uint32"},{"internalType":"uint256","name":"voteEnd","type":"uint256"},{"internalType":"address","name":"caller","type":"address"},{"internalType":"uint32","name":"againstVotes","type":"uint32"},{"internalType":"uint32","name":"forVotes","type":"uint32"},{"internalType":"uint32","name":"abstainVotes","type":"uint32"},{"internalType":"uint256","name":"nonce","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"actionId","type":"uint256"}],"name":"getActionNonce","outputs":[{"internalType":"uint256","name":"nonce","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"actionId","type":"uint256"}],"name":"getActionUri","outputs":[{"internalType":"string","name":"_uri","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"lawId","type":"uint16"}],"name":"getActiveLaw","outputs":[{"internalType":"address","name":"law","type":"address"},{"internalType":"bytes32","name":"lawHash","type":"bytes32"},{"internalType":"bool","name":"active","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"roleId","type":"uint256"}],"name":"getAmountRoleHolders","outputs":[{"internalType":"uint256","name":"amountMembers","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"actionId","type":"uint256"}],"name":"getProposedActionDeadline","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"roleId","type":"uint256"}],"name":"getRoleLabel","outputs":[{"internalType":"string","name":"label","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"roleId","type":"uint256"}],"name":"hasRoleSince","outputs":[{"internalType":"uint48","name":"since","type":"uint48"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"actionId","type":"uint256"},{"internalType":"address","name":"account","type":"address"}],"name":"hasVoted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"roleId","type":"uint256"},{"internalType":"string","name":"label","type":"string"}],"name":"labelRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"lawCount","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"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":"uint16","name":"lawId","type":"uint16"},{"internalType":"bytes","name":"lawCalldata","type":"bytes"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"string","name":"uriAction","type":"string"}],"name":"propose","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"lawId","type":"uint16"},{"internalType":"bytes","name":"lawCalldata","type":"bytes"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"string","name":"uriAction","type":"string"}],"name":"request","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint16","name":"lawId","type":"uint16"}],"name":"revokeLaw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"roleId","type":"uint256"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"newUri","type":"string"}],"name":"setUri","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"actionId","type":"uint256"}],"name":"state","outputs":[{"internalType":"enum PowersTypes.ActionState","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"uri","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"stateMutability":"payable","type":"receive"}]Contract Creation Code
6101606040526007805462ffff001916610100179055348015610020575f80fd5b50604051613edb380380613edb83398101604081905261003f91610473565b81610060604080518082019091526003815262302e3360e81b602082015290565b61006a825f6101eb565b610120526100798160016101eb565b61014052815160208084019190912060e052815190820120610100524660a05261010560e05161010051604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60208201529081019290925260608201524660808201523060a08201525f9060c00160405160208183030381529060405280519060200120905090565b60805250503060c05281515f0361012f57604051634acb0e6d60e01b815260040160405180910390fd5b600561013b838261055c565b506006610148828261055c565b506101555f33600161021d565b600460205260017f17ef568e3e12ab5b9c7254a8d58478811de00f9e6eb34345acd53bf8fd09d3ed555f195f8190527fd8c80a9840ed58f33f2186a8fbc29ecd8c3610d196f1da047301bd51988eb95d556040517f8e09415123fab1f9e22246686c8d24ad9f84c70288cd5fa338213bccd3c5fb76906101dc903090600590600690610695565b60405180910390a1505061076d565b5f602083511015610206576101ff83610390565b9050610217565b81610211848261055c565b5060ff90505b92915050565b5f8381526004602090815260408083206001600160a01b038616845290915290205465ffffffffffff161560018401610269576040516313d0e80160e31b815260040160405180910390fd5b6001600160a01b038316610290576040516329f62b5d60e11b815260040160405180910390fd5b81156102fb575f8481526004602090815260408083206001600160a01b03871684529091529020805465ffffffffffff19164365ffffffffffff1617905580156102f6575f8481526004602052604081206001018054916102f0836106e8565b91905055505b610350565b5f8481526004602090815260408083206001600160a01b03871684529091529020805465ffffffffffff1916905580610350575f84815260046020526040812060010180549161034a83610700565b91905055505b811515836001600160a01b0316857f294507a8f5830b538faef39fbdd28f1164f27c8338a32fc7b47ddf82e4c8d9e460405160405180910390a450505050565b5f80829050601f815111156103c3578260405163305a27a960e01b81526004016103ba9190610715565b60405180910390fd5b80516103ce8261074a565b179392505050565b634e487b7160e01b5f52604160045260245ffd5b5f82601f8301126103f9575f80fd5b81516001600160401b03811115610412576104126103d6565b604051601f8201601f19908116603f011681016001600160401b0381118282101715610440576104406103d6565b604052818152838201602001851015610457575f80fd5b8160208501602083015e5f918101602001919091529392505050565b5f8060408385031215610484575f80fd5b82516001600160401b03811115610499575f80fd5b6104a5858286016103ea565b602085015190935090506001600160401b038111156104c2575f80fd5b6104ce858286016103ea565b9150509250929050565b600181811c908216806104ec57607f821691505b60208210810361050a57634e487b7160e01b5f52602260045260245ffd5b50919050565b601f82111561055757805f5260205f20601f840160051c810160208510156105355750805b601f840160051c820191505b81811015610554575f8155600101610541565b50505b505050565b81516001600160401b03811115610575576105756103d6565b6105898161058384546104d8565b84610510565b6020601f8211600181146105bb575f83156105a45750848201515b5f19600385901b1c1916600184901b178455610554565b5f84815260208120601f198516915b828110156105ea57878501518255602094850194600190920191016105ca565b508482101561060757868401515f19600387901b60f8161c191681555b50505050600190811b01905550565b5f8154610622816104d8565b80855260018216801561063c57600181146106585761068c565b60ff1983166020870152602082151560051b870101935061068c565b845f5260205f205f5b838110156106835781546020828a010152600182019150602081019050610661565b87016020019450505b50505092915050565b6001600160a01b03841681526060602082018190525f906106b890830185610616565b82810360408401526106ca8185610616565b9695505050505050565b634e487b7160e01b5f52601160045260245ffd5b5f600182016106f9576106f96106d4565b5060010190565b5f8161070e5761070e6106d4565b505f190190565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b8051602080830151919081101561050a575f1960209190910360031b1b16919050565b60805160a05160c05160e05161010051610120516101405161372c6107af5f395f6120cc01525f61209b01525f50505f50505f50505f50505f505061372c5ff3fe60806040526004361061020a575f3560e01c80637b3c71d311610113578063bc197c811161009d578063d902bf3a1161006d578063d902bf3a1461075e578063eac989f81461077d578063ebef6d9714610791578063f23a6e61146107a4578063f2a0bb75146107cf575f80fd5b8063bc197c8114610683578063c37d1d92146106ae578063c661d4be146106e0578063cc5812cf146106ff575f80fd5b8063918f8674116100e3578063918f8674146105e4578063991e2e0a146105f85780639b642de114610617578063ab776bf214610636578063b4324dd314610655575f80fd5b80637b3c71d3146104e757806384b0196e14610506578063857030f41461052d57806388c5ee081461054c575f80fd5b80633ca7c02a1161019457806354fd4d501161016457806354fd4d501461044c5780635678138814610477578063685b824a1461049657806375b238fc146104b55780637a485033146104c8575f80fd5b80633ca7c02a146103a65780633e4f49e6146103ba57806343859632146103e65780634583476b14610415575f80fd5b8063150b7a02116101da578063150b7a02146102d85780631d0b19e71461031b578063237d45b51461033a578063271b05aa146103595780632e2d825314610387575f80fd5b80630398f05f1461024d57806306fdde03146102825780630de6a6011461029657806312561b1a146102ab575f80fd5b3661024957604080513481523360208201527fa0b6ed69c727bcce4cfdf30bc2777d7b7007d936b4a4dea135cbf6622fe4a58c910160405180910390a1005b5f80fd5b348015610258575f80fd5b5061026c610267366004612422565b6107ee565b6040516102799190612467565b60405180910390f35b34801561028d575f80fd5b5061026c610890565b6102a96102a43660046124df565b61091c565b005b3480156102b6575f80fd5b506102ca6102c53660046125d3565b610b99565b604051908152602001610279565b3480156102e3575f80fd5b506103026102f2366004612740565b630a85bd0160e11b949350505050565b6040516001600160e01b03199091168152602001610279565b348015610326575f80fd5b506102a96103353660046127a3565b610c39565b348015610345575f80fd5b506102a9610354366004612977565b610c68565b348015610364575f80fd5b506102ca610373366004612422565b5f9081526002602052604090206005015490565b348015610392575f80fd5b506102ca6103a1366004612a2b565b610d59565b3480156103b1575f80fd5b506102ca5f1981565b3480156103c5575f80fd5b506103d96103d4366004612422565b610e34565b6040516102799190612ac2565b3480156103f1575f80fd5b506104056104003660046127a3565b610efb565b6040519015158152602001610279565b348015610420575f80fd5b5061043461042f366004612422565b610f29565b6040516102799c9b9a99989796959493929190612ae8565b348015610457575f80fd5b50604080518082019091526003815262302e3360e81b602082015261026c565b348015610482575f80fd5b506102a9610491366004612b76565b611026565b3480156104a1575f80fd5b506102a96104b03660046127a3565b611049565b3480156104c0575f80fd5b506102ca5f81565b3480156104d3575f80fd5b506104056104e2366004612ba4565b611075565b3480156104f2575f80fd5b506102a9610501366004612bce565b61113f565b348015610511575f80fd5b5061051a61118c565b6040516102799796959493929190612c25565b348015610538575f80fd5b506102a9610547366004612cbb565b6111ce565b348015610557575f80fd5b506105bd610566366004612cf4565b61ffff165f81815260036020908152604091829020548251308184015280840194909452825180850384018152606090940190925282519201919091206001600160a01b038216929091600160a01b900460ff1690565b604080516001600160a01b0390941684526020840192909252151590820152606001610279565b3480156105ef575f80fd5b506102ca606481565b348015610603575f80fd5b506102ca610612366004612422565b6111fa565b348015610622575f80fd5b506102a9610631366004612d0f565b61123c565b348015610641575f80fd5b506102a9610650366004612d40565b611268565b348015610660575f80fd5b506102ca61066f366004612422565b5f9081526004602052604090206001015490565b34801561068e575f80fd5b5061030261069d366004612de8565b63bc197c8160e01b95945050505050565b3480156106b9575f80fd5b506007546106cd90610100900461ffff1681565b60405161ffff9091168152602001610279565b3480156106eb575f80fd5b506102a96106fa366004612cf4565b61130a565b34801561070a575f80fd5b50610747610719366004612e7b565b5f9081526004602090815260408083206001600160a01b03949094168352929052205465ffffffffffff1690565b60405165ffffffffffff9091168152602001610279565b348015610769575f80fd5b5061026c610778366004612422565b6113ae565b348015610788575f80fd5b5061026c6113cd565b6102a961079f366004612a2b565b6113da565b3480156107af575f80fd5b506103026107be366004612ea3565b63f23a6e6160e01b95945050505050565b3480156107da575f80fd5b5061026c6107e9366004612422565b611667565b5f81815260046020526040902060020180546060919061080d90612ef6565b80601f016020809104026020016040519081016040528092919081815260200182805461083990612ef6565b80156108845780601f1061085b57610100808354040283529160200191610884565b820191905f5260205f20905b81548152906001019060200180831161086757829003601f168201915b50505050509050919050565b6005805461089d90612ef6565b80601f01602080910402602001604051908101604052809291908181526020018280546108c990612ef6565b80156109145780601f106108eb57610100808354040283529160200191610914565b820191905f5260205f20905b8154815290600101906020018083116108f757829003601f168201915b505050505081565b61ffff88165f908152600360205260408120548991600160a01b90910460ff161515900361095d57604051639b7a92d760e01b815260040160405180910390fd5b61ffff89165f908152600360209081526040918290208251808401909352546001600160a01b0381168352600160a01b900460ff1615159082018190526109b757604051639b7a92d760e01b815260040160405180910390fd5b80516001600160a01b031633146109e157604051633e779cf960e01b815260040160405180910390fd5b5f8981526002602052604090205460ff610100909104161515600114610a1a576040516301dd1d1560e71b815260040160405180910390fd5b8685141580610a295750868314155b15610a475760405163dbf15fa560e01b815260040160405180910390fd5b5f898152600260205260408120805462ff00001916620100001790555b87811015610b45575f808a8a84818110610a8057610a80612f2e565b9050602002016020810190610a959190612f42565b6001600160a01b0316898985818110610ab057610ab0612f2e565b90506020020135888886818110610ac957610ac9612f2e565b9050602002810190610adb9190612f5b565b604051610ae9929190612f9d565b5f6040518083038185875af1925050503d805f8114610b23576040519150601f19603f3d011682016040523d82523d5f602084013e610b28565b606091505b5091509150610b378282611686565b505050806001019050610a64565b50888a61ffff167f328d3074f6e96c8ffb9619ec805360a70b6af7ad7e24e7c73fd0968e5dc505c48a8a8a8a8a8a604051610b8596959493929190613068565b60405180910390a350505050505050505050565b61ffff84165f908152600360205260408120548590600160a01b900460ff1615158203610bd957604051639b7a92d760e01b815260040160405180910390fd5b5f610be6878787876116a2565b5f818152600260205260409020600101549091506001600160a01b03163314610c2257604051633e779cf960e01b815260040160405180910390fd5b610c2e878787876116db565b979650505050505050565b333014610c595760405163e890ccbf60e01b815260040160405180910390fd5b610c6482825f611781565b5050565b335f9081527f17ef568e3e12ab5b9c7254a8d58478811de00f9e6eb34345acd53bf8fd09d3ec602052604081205465ffffffffffff169003610cbd57604051633e779cf960e01b815260040160405180910390fd5b60075460ff1615610ce15760405163cc03ce1160e01b815260040160405180910390fd5b6007805460ff191660011790555f5b8151811015610c64575f6001600160a01b0316828281518110610d1557610d15612f2e565b6020026020010151602001516001600160a01b031614610d5157610d51828281518110610d4457610d44612f2e565b60200260200101516118f4565b600101610cf0565b61ffff85165f908152600360205260408120548690600160a01b900460ff1615158203610d9957604051639b7a92d760e01b815260040160405180910390fd5b61ffff87165f908152600360209081526040918290208251808401909352546001600160a01b0381168352600160a01b900460ff161515908201819052610df357604051639b7a92d760e01b815260040160405180910390fd5b610dfd3389611075565b610e1a57604051633e779cf960e01b815260040160405180910390fd5b610e28338989898989611a88565b98975050505050505050565b5f818152600260205260408120805460ff620100008204811691168115610e6057506005949350505050565b8015610e7157506001949350505050565b5f85815260026020526040812054600160281b900465ffffffffffff1690819003610ea25750600695945050505050565b5f610eac876111fa565b9050438110610ec157505f9695505050505050565b610eca87611d2b565b1580610edc5750610eda87611e60565b155b15610eee575060029695505050505050565b5060039695505050505050565b5f8281526002602081815260408084206001600160a01b0386168552909201905290205460ff165b92915050565b5f8181526002602052604081208054829182918291829182918291829182918291829182919060ff80821691610100810482169162010000820416906301000000810461ffff1690600160281b810465ffffffffffff1690600160581b900463ffffffff16610f988183613110565b876001015f9054906101000a90046001600160a01b03168860010160149054906101000a900463ffffffff168960010160189054906101000a900463ffffffff168a600101601c9054906101000a900463ffffffff168b600501548565ffffffffffff1695509c509c509c509c509c509c509c509c509c509c509c509c505091939597999b5091939597999b565b5f33905061104483828460405180602001604052805f815250611f6e565b505050565b3330146110695760405163e890ccbf60e01b815260040160405180910390fd5b610c6482826001611781565b61ffff81165f818152600360205260408082205490516364fa842760e01b81523060048201526024810193909352909182916001600160a01b0316906364fa84279060440161012060405180830381865afa1580156110d6573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906110fa919061315a565b515f8181526004602090815260408083206001600160a01b038916845290915290205490915065ffffffffffff168015158061113657505f1982145b95945050505050565b5f33905061118485828686868080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250611f6e92505050565b505b50505050565b5f6060805f805f606061119d612094565b6111a56120c5565b604080515f80825260208201909252600f60f81b9b939a50919850469750309650945092509050565b3330146111ee5760405163e890ccbf60e01b815260040160405180910390fd5b6111f7816118f4565b50565b5f8181526002602052604081205461122e90600160581b810463ffffffff1690600160281b900465ffffffffffff16613110565b65ffffffffffff1692915050565b33301461125c5760405163e890ccbf60e01b815260040160405180910390fd5b6006610c64828261324e565b3330146112885760405163e890ccbf60e01b815260040160405180910390fd5b81158061129557505f1982145b156112b3576040516329939fd360e21b815260040160405180910390fd5b5f8281526004602052604090206002016112cd828261324e565b50817f4c6d3d4a776b1458bbd518e75903a3f27a0c6f4597b10882784aa64769d56c71826040516112fe9190612467565b60405180910390a25050565b33301461132a5760405163e890ccbf60e01b815260040160405180910390fd5b61ffff81165f90815260036020526040812054600160a01b900460ff161515900361136857604051639b7a92d760e01b815260040160405180910390fd5b61ffff81165f81815260036020526040808220805460ff60a01b19169055517f519eb0bde04fa6068eddea64ada07d654914aa8a6bd2689cf2aeb02c61a4f1359190a250565b5f81815260026020526040902060030180546060919061080d90612ef6565b6006805461089d90612ef6565b61ffff85165f908152600360205260408120548691600160a01b90910460ff161515900361141b57604051639b7a92d760e01b815260040160405180910390fd5b5f611428878787876116a2565b61ffff88165f908152600360209081526040918290208251808401909352546001600160a01b0381168352600160a01b900460ff161515908201529091506114703389611075565b61148d57604051633e779cf960e01b815260040160405180910390fd5b5f82815260026020526040902054610100900460ff1615156001036114c55760405163fc0e49ff60e01b815260040160405180910390fd5b5f8281526002602052604090205460ff1615156001036114f857604051632ec3fe1560e11b815260040160405180910390fd5b5f8281526002602052604090206001810180546001600160a01b03191633179055805461ff001961ffff8b166301000000021664ffff00ff00199091161761010017815560030161154a878983613308565b505f828152600260205260409020600401611565858261324e565b505f8281526002602052604080822060050187905582519051637bf5b2fb60e01b81526001600160a01b0390911690637bf5b2fb906115b09033908d908d908d908d906004016133c1565b6020604051808303815f875af11580156115cc573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906115f09190613401565b9050806116105760405163528af36760e11b815260040160405180910390fd5b8861ffff16336001600160a01b03167f98e1e52af9c2155b4c2b4844cdccf64c85cb13dd804231d177ef6fea4325d4058a8a8a8a6040516116549493929190613420565b60405180910390a3505050505050505050565b5f81815260026020526040902060040180546060919061080d90612ef6565b60608261169b57611696826120f2565b610f23565b5080610f23565b5f848484846040516020016116ba949392919061344b565b60408051601f19818403018152919052805160209091012095945050505050565b5f806116e9868686866116a2565b5f8181526002602052604090205490915062010000900460ff168061171b57505f8181526002602052604090205460ff165b156117395760405163b831530960e01b815260040160405180910390fd5b5f81815260026020526040808220805460ff191660011790555182917f8eb4cfeba12ece86fc1590773502e55423b37db556543430337376b30d27c42b91a295945050505050565b5f8381526004602090815260408083206001600160a01b038616845290915290205465ffffffffffff1615600184016117cd576040516313d0e80160e31b815260040160405180910390fd5b6001600160a01b0383166117f4576040516329f62b5d60e11b815260040160405180910390fd5b811561185f575f8481526004602090815260408083206001600160a01b03871684529091529020805465ffffffffffff19164365ffffffffffff16179055801561185a575f84815260046020526040812060010180549161185483613479565b91905055505b6118b4565b5f8481526004602090815260408083206001600160a01b03871684529091529020805465ffffffffffff19169055806118b4575f8481526004602052604081206001018054916118ae83613491565b91905055505b811515836001600160a01b0316857f294507a8f5830b538faef39fbdd28f1164f27c8338a32fc7b47ddf82e4c8d9e460405160405180910390a450505050565b611909816020015163b095668760e01b61211a565b6119265760405163498a519360e11b815260040160405180910390fd5b6007805461ffff6101009182900481165f908152600360209081526040808320805460ff60a01b1916600160a01b17905590860151855485900484168352912080546001600160a01b039092166001600160a01b031990921691909117905582549190910416906001611998836134a6565b91906101000a81548161ffff021916908361ffff1602179055505080602001516001600160a01b03166380c8c3fb6001600760019054906101000a900461ffff166119e391906134c6565b835f0151846060015185604001516040518563ffffffff1660e01b8152600401611a10949392919061358d565b5f604051808303815f87803b158015611a27575f80fd5b505af1158015611a39573d5f803e3d5ffd5b5050600754611a55925060019150610100900461ffff166134c6565b61ffff167f753b7a99c84c928c5a0d08bebb7564f3f84d39310585ce05f9d043a40084bf8860405160405180910390a250565b61ffff85165f8181526003602090815260408083208151808301835290546001600160a01b038116808352600160a01b90910460ff1615159382019390935290516364fa842760e01b8152306004820152602481019490945291928391906364fa84279060440161012060405180830381865afa158015611b0b573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611b2f919061315a565b9050611b3d888888886116a2565b92508060c0015160ff165f03611b6657604051632dd4cc8d60e01b815260040160405180910390fd5b5f83815260026020526040902054600160281b900465ffffffffffff1615611ba15760405163b831530960e01b815260040160405180910390fd5b81516040516308979f7960e31b81526001600160a01b03909116906344bcfbc890611bda908c9085908c908c908c9030906004016135dc565b5f6040518083038186803b158015611bf0575f80fd5b505afa158015611c02573d5f803e3d5ffd5b5050505f848152600260205260409020905060038101611c23888a83613308565b50805460a08301516affffffffffffffff00000019909116630100000061ffff8c16026affffffffffff0000000000191617600160281b4365ffffffffffff16021763ffffffff60581b1916600160581b63ffffffff909216919091021781556001810180546001600160a01b0319166001600160a01b038c1617905560048101611cae868261324e565b508581600501819055508861ffff168a6001600160a01b0316857fb5856a9700a7e851456d3a16348b4ae0fbb11b06ac0af8dbe8e8652c57cc4cbd8b8b438860a0015163ffffffff1643611d029190613633565b8d8d604051611d1696959493929190613646565b60405180910390a45050509695505050505050565b5f81815260026020908152604080832080546301000000900461ffff16808552600384528285208351808501855290546001600160a01b038116808352600160a01b90910460ff1615159582019590955292516364fa842760e01b81523060048201526024810191909152909284916364fa84279060440161012060405180830381865afa158015611dbf573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611de3919061315a565b80515f9081526004602052604090206001015460c08201519192509060ff161580611e5657506001840154606490611e319063ffffffff600160e01b8204811691600160c01b90041661368a565b63ffffffff16611e4191906136a6565b60c0830151611e539060ff16836136a6565b11155b9695505050505050565b5f81815260026020908152604080832080546301000000900461ffff16808552600384528285208351808501855290546001600160a01b038116808352600160a01b90910460ff1615159582019590955292516364fa842760e01b81523060048201526024810191909152909284916364fa84279060440161012060405180830381865afa158015611ef4573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611f18919061315a565b80515f9081526004602052604090206001015460c08201519192509060ff161580611e5657506001840154611f5c90606490600160c01b900463ffffffff166136a6565b60e0830151611e539060ff16836136a6565b5f604051631f27a4f360e11b8152600481018690523090633e4f49e690602401602060405180830381865afa158015611fa9573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611fcd91906136bd565b6006811115611fde57611fde612aae565b14611ffc576040516322024acd60e21b815260040160405180910390fd5b5f848152600260205260409020546301000000900461ffff1661201f8482611075565b61203c57604051633e779cf960e01b815260040160405180910390fd5b61204785858561213c565b8260ff1685856001600160a01b03167f5be2678cab71c7d94235767eb1df3c57673f19e805cdc0edbd2e74854ae9f0f9856040516120859190612467565b60405180910390a45050505050565b60606120c07f00000000000000000000000000000000000000000000000000000000000000005f612260565b905090565b60606120c07f00000000000000000000000000000000000000000000000000000000000000006001612260565b80511561210157805160208201fd5b60405163d6bda27560e01b815260040160405180910390fd5b5f61212483612309565b80156121355750612135838361233b565b9392505050565b5f8381526002602081815260408084206001600160a01b03871685529283019091529091205460ff16156121835760405163c9e3c8d960e01b815260040160405180910390fd5b6001600160a01b0383165f9081526002820160205260409020805460ff1916600117905560ff82166121f257600181018054600160a01b900463ffffffff169060146121ce836136db565b91906101000a81548163ffffffff021916908363ffffffff16021790555050611186565b5f1960ff83160161221c57600181018054600160c01b900463ffffffff169060186121ce836136db565b60011960ff83160161224757600181018054600160e01b900463ffffffff1690601c6121ce836136db565b6040516333397b4360e11b815260040160405180910390fd5b606060ff831461227a57612273836123be565b9050610f23565b81805461228690612ef6565b80601f01602080910402602001604051908101604052809291908181526020018280546122b290612ef6565b80156122fd5780601f106122d4576101008083540402835291602001916122fd565b820191905f5260205f20905b8154815290600101906020018083116122e057829003601f168201915b50505050509050610f23565b5f61231b826301ffc9a760e01b61233b565b8015610f235750612334826001600160e01b031961233b565b1592915050565b6040516001600160e01b0319821660248201525f90819060440160408051601f19818403018152919052602080820180516001600160e01b03166301ffc9a760e01b17815282519293505f9283928392909183918a617530fa92503d91505f5190508280156123ab575060208210155b8015610c2e575015159695505050505050565b60605f6123ca836123fb565b6040805160208082528183019092529192505f91906020820181803683375050509182525060208101929092525090565b5f60ff8216601f811115610f2357604051632cd44ac360e21b815260040160405180910390fd5b5f60208284031215612432575f80fd5b5035919050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f6121356020830184612439565b61ffff811681146111f7575f80fd5b803561249381612479565b919050565b5f8083601f8401126124a8575f80fd5b5081356001600160401b038111156124be575f80fd5b6020830191508360208260051b85010111156124d8575f80fd5b9250929050565b5f805f805f805f8060a0898b0312156124f6575f80fd5b883561250181612479565b97506020890135965060408901356001600160401b03811115612522575f80fd5b61252e8b828c01612498565b90975095505060608901356001600160401b0381111561254c575f80fd5b6125588b828c01612498565b90955093505060808901356001600160401b03811115612576575f80fd5b6125828b828c01612498565b999c989b5096995094979396929594505050565b5f8083601f8401126125a6575f80fd5b5081356001600160401b038111156125bc575f80fd5b6020830191508360208285010111156124d8575f80fd5b5f805f80606085870312156125e6575f80fd5b84356125f181612479565b935060208501356001600160401b0381111561260b575f80fd5b61261787828801612596565b9598909750949560400135949350505050565b80356001600160a01b0381168114612493575f80fd5b634e487b7160e01b5f52604160045260245ffd5b604051608081016001600160401b038111828210171561267657612676612640565b60405290565b60405161012081016001600160401b038111828210171561267657612676612640565b604051601f8201601f191681016001600160401b03811182821017156126c7576126c7612640565b604052919050565b5f82601f8301126126de575f80fd5b8135602083015f806001600160401b038411156126fd576126fd612640565b50601f8301601f19166020016127128161269f565b915050828152858383011115612726575f80fd5b828260208301375f92810160200192909252509392505050565b5f805f8060808587031215612753575f80fd5b61275c8561262a565b935061276a6020860161262a565b92506040850135915060608501356001600160401b0381111561278b575f80fd5b612797878288016126cf565b91505092959194509250565b5f80604083850312156127b4575f80fd5b823591506127c46020840161262a565b90509250929050565b5f6001600160401b038211156127e5576127e5612640565b5060051b60200190565b65ffffffffffff811681146111f7575f80fd5b8035612493816127ef565b63ffffffff811681146111f7575f80fd5b80356124938161280d565b60ff811681146111f7575f80fd5b803561249381612829565b5f818303610180811215612854575f80fd5b61285c612654565b915082356001600160401b03811115612873575f80fd5b61287f858286016126cf565b83525061288e6020840161262a565b602083015260408301356001600160401b038111156128ab575f80fd5b6128b7858286016126cf565b604084015250610120605f19820112156128cf575f80fd5b506128d861267c565b606083013581526128eb60808401612488565b60208201526128fc60a08401612802565b604082015261290d60c08401612802565b606082015261291e60e08401612488565b6080820152612930610100840161281e565b60a08201526129426101208401612837565b60c08201526129546101408401612837565b60e08201526129666101608401612488565b610100820152606082015292915050565b5f60208284031215612987575f80fd5b81356001600160401b0381111561299c575f80fd5b8201601f810184136129ac575f80fd5b80356129bf6129ba826127cd565b61269f565b8082825260208201915060208360051b8501019250868311156129e0575f80fd5b602084015b83811015612a205780356001600160401b03811115612a02575f80fd5b612a1189602083890101612842565b845250602092830192016129e5565b509695505050505050565b5f805f805f60808688031215612a3f575f80fd5b8535612a4a81612479565b945060208601356001600160401b03811115612a64575f80fd5b612a7088828901612596565b9095509350506040860135915060608601356001600160401b03811115612a95575f80fd5b612aa1888289016126cf565b9150509295509295909350565b634e487b7160e01b5f52602160045260245ffd5b6020810160078310612ae257634e487b7160e01b5f52602160045260245ffd5b91905290565b8c151581528b151560208201528a1515604082015261ffff8a16606082015265ffffffffffff8916608082015263ffffffff881660a082015261018081018760c0830152612b4160e08301886001600160a01b03169052565b63ffffffff95861661010083015293851661012082015291909316610140820152610160019190915298975050505050505050565b5f8060408385031215612b87575f80fd5b823591506020830135612b9981612829565b809150509250929050565b5f8060408385031215612bb5575f80fd5b612bbe8361262a565b91506020830135612b9981612479565b5f805f8060608587031215612be1575f80fd5b843593506020850135612bf381612829565b925060408501356001600160401b03811115612c0d575f80fd5b612c1987828801612596565b95989497509550505050565b60ff60f81b8816815260e060208201525f612c4360e0830189612439565b8281036040840152612c558189612439565b606084018890526001600160a01b038716608085015260a0840186905283810360c0850152845180825260208087019350909101905f5b81811015612caa578351835260209384019390920191600101612c8c565b50909b9a5050505050505050505050565b5f60208284031215612ccb575f80fd5b81356001600160401b03811115612ce0575f80fd5b612cec84828501612842565b949350505050565b5f60208284031215612d04575f80fd5b813561213581612479565b5f60208284031215612d1f575f80fd5b81356001600160401b03811115612d34575f80fd5b612cec848285016126cf565b5f8060408385031215612d51575f80fd5b8235915060208301356001600160401b03811115612d6d575f80fd5b612d79858286016126cf565b9150509250929050565b5f82601f830112612d92575f80fd5b8135612da06129ba826127cd565b8082825260208201915060208360051b860101925085831115612dc1575f80fd5b602085015b83811015612dde578035835260209283019201612dc6565b5095945050505050565b5f805f805f60a08688031215612dfc575f80fd5b612e058661262a565b9450612e136020870161262a565b935060408601356001600160401b03811115612e2d575f80fd5b612e3988828901612d83565b93505060608601356001600160401b03811115612e54575f80fd5b612e6088828901612d83565b92505060808601356001600160401b03811115612a95575f80fd5b5f8060408385031215612e8c575f80fd5b612e958361262a565b946020939093013593505050565b5f805f805f60a08688031215612eb7575f80fd5b612ec08661262a565b9450612ece6020870161262a565b9350604086013592506060860135915060808601356001600160401b03811115612a95575f80fd5b600181811c90821680612f0a57607f821691505b602082108103612f2857634e487b7160e01b5f52602260045260245ffd5b50919050565b634e487b7160e01b5f52603260045260245ffd5b5f60208284031215612f52575f80fd5b6121358261262a565b5f808335601e19843603018112612f70575f80fd5b8301803591506001600160401b03821115612f89575f80fd5b6020019150368190038213156124d8575f80fd5b818382375f9101908152919050565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b5f8383855260208501945060208460051b820101835f5b8681101561305c57838303601f19018852813536879003601e19018112613010575f80fd5b86016020810190356001600160401b0381111561302b575f80fd5b803603821315613039575f80fd5b613044858284612fac565b60209a8b019a90955093909301925050600101612feb565b50909695505050505050565b606080825281018690525f8760808301825b898110156130a8576001600160a01b036130938461262a565b1682526020928301929091019060010161307a565b5083810360208501528681526001600160fb1b038711156130c7575f80fd5b8660051b91508188602083013701828103602090810160408501526130ef9082018587612fd4565b9998505050505050505050565b634e487b7160e01b5f52601160045260245ffd5b65ffffffffffff8181168382160190811115610f2357610f236130fc565b805161249381612479565b8051612493816127ef565b80516124938161280d565b805161249381612829565b5f61012082840312801561316c575f80fd5b5061317561267c565b825181526131856020840161312e565b602082015261319660408401613139565b60408201526131a760608401613139565b60608201526131b86080840161312e565b60808201526131c960a08401613144565b60a08201526131da60c0840161314f565b60c08201526131eb60e0840161314f565b60e08201526131fd610100840161312e565b6101008201529392505050565b601f82111561104457805f5260205f20601f840160051c8101602085101561322f5750805b601f840160051c820191505b81811015611184575f815560010161323b565b81516001600160401b0381111561326757613267612640565b61327b816132758454612ef6565b8461320a565b6020601f8211600181146132ad575f83156132965750848201515b5f19600385901b1c1916600184901b178455611184565b5f84815260208120601f198516915b828110156132dc57878501518255602094850194600190920191016132bc565b50848210156132f957868401515f19600387901b60f8161c191681555b50505050600190811b01905550565b6001600160401b0383111561331f5761331f612640565b6133338361332d8354612ef6565b8361320a565b5f601f841160018114613364575f851561334d5750838201355b5f19600387901b1c1916600186901b178355611184565b5f83815260208120601f198716915b828110156133935786850135825560209485019460019092019101613373565b50868210156133af575f1960f88860031b161c19848701351681555b505060018560011b0183555050505050565b6001600160a01b038616815261ffff851660208201526080604082018190525f906133ef9083018587612fac565b90508260608301529695505050505050565b5f60208284031215613411575f80fd5b81518015158114612135575f80fd5b606081525f613433606083018688612fac565b8460208401528281036040840152610c2e8185612439565b61ffff85168152606060208201525f613468606083018587612fac565b905082604083015295945050505050565b5f6001820161348a5761348a6130fc565b5060010190565b5f8161349f5761349f6130fc565b505f190190565b5f61ffff821661ffff81036134bd576134bd6130fc565b60010192915050565b61ffff8281168282160390811115610f2357610f236130fc565b8051825261ffff602082015116602083015265ffffffffffff6040820151166040830152606081015161351d606084018265ffffffffffff169052565b506080810151613533608084018261ffff169052565b5060a081015161354b60a084018263ffffffff169052565b5060c081015161356060c084018260ff169052565b5060e081015161357560e084018260ff169052565b5061010081015161104461010084018261ffff169052565b61ffff851681526101a060208201525f6135ab6101a0830186612439565b8281038060408501525f82526135c460608501876134e0565b6020810161018085015250610c2e6020820185612439565b6001600160a01b03871681526135f560208201876134e0565b6101a06101408201525f61360e6101a083018688612fac565b610160830194909452506001600160a01b039190911661018090910152949350505050565b80820180821115610f2357610f236130fc565b60c081525f60c082015260e060208201525f61366660e08301888a612fac565b86604084015285606084015284608084015282810360a08401526130ef8185612439565b63ffffffff8181168382160190811115610f2357610f236130fc565b8082028115828204841417610f2357610f236130fc565b5f602082840312156136cd575f80fd5b815160078110612135575f80fd5b5f63ffffffff821663ffffffff81036134bd576134bd6130fc56fea2646970667358221220321a1e1c554b32824d35644e58e765206932888fb8b05560b878507cb2a5a26f64736f6c634300081a0033000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000011506f77657220746f207468652055736572000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007068747470733a2f2f617175612d66616d6f75732d7361696c666973682d3238382e6d7970696e6174612e636c6f75642f697066732f6261666b72656965696f7074666f706d64646770696f7767366475757a7364346e366b6f69627574746865763732646e6d7765637a6a796273347100000000000000000000000000000000
Deployed Bytecode
0x60806040526004361061020a575f3560e01c80637b3c71d311610113578063bc197c811161009d578063d902bf3a1161006d578063d902bf3a1461075e578063eac989f81461077d578063ebef6d9714610791578063f23a6e61146107a4578063f2a0bb75146107cf575f80fd5b8063bc197c8114610683578063c37d1d92146106ae578063c661d4be146106e0578063cc5812cf146106ff575f80fd5b8063918f8674116100e3578063918f8674146105e4578063991e2e0a146105f85780639b642de114610617578063ab776bf214610636578063b4324dd314610655575f80fd5b80637b3c71d3146104e757806384b0196e14610506578063857030f41461052d57806388c5ee081461054c575f80fd5b80633ca7c02a1161019457806354fd4d501161016457806354fd4d501461044c5780635678138814610477578063685b824a1461049657806375b238fc146104b55780637a485033146104c8575f80fd5b80633ca7c02a146103a65780633e4f49e6146103ba57806343859632146103e65780634583476b14610415575f80fd5b8063150b7a02116101da578063150b7a02146102d85780631d0b19e71461031b578063237d45b51461033a578063271b05aa146103595780632e2d825314610387575f80fd5b80630398f05f1461024d57806306fdde03146102825780630de6a6011461029657806312561b1a146102ab575f80fd5b3661024957604080513481523360208201527fa0b6ed69c727bcce4cfdf30bc2777d7b7007d936b4a4dea135cbf6622fe4a58c910160405180910390a1005b5f80fd5b348015610258575f80fd5b5061026c610267366004612422565b6107ee565b6040516102799190612467565b60405180910390f35b34801561028d575f80fd5b5061026c610890565b6102a96102a43660046124df565b61091c565b005b3480156102b6575f80fd5b506102ca6102c53660046125d3565b610b99565b604051908152602001610279565b3480156102e3575f80fd5b506103026102f2366004612740565b630a85bd0160e11b949350505050565b6040516001600160e01b03199091168152602001610279565b348015610326575f80fd5b506102a96103353660046127a3565b610c39565b348015610345575f80fd5b506102a9610354366004612977565b610c68565b348015610364575f80fd5b506102ca610373366004612422565b5f9081526002602052604090206005015490565b348015610392575f80fd5b506102ca6103a1366004612a2b565b610d59565b3480156103b1575f80fd5b506102ca5f1981565b3480156103c5575f80fd5b506103d96103d4366004612422565b610e34565b6040516102799190612ac2565b3480156103f1575f80fd5b506104056104003660046127a3565b610efb565b6040519015158152602001610279565b348015610420575f80fd5b5061043461042f366004612422565b610f29565b6040516102799c9b9a99989796959493929190612ae8565b348015610457575f80fd5b50604080518082019091526003815262302e3360e81b602082015261026c565b348015610482575f80fd5b506102a9610491366004612b76565b611026565b3480156104a1575f80fd5b506102a96104b03660046127a3565b611049565b3480156104c0575f80fd5b506102ca5f81565b3480156104d3575f80fd5b506104056104e2366004612ba4565b611075565b3480156104f2575f80fd5b506102a9610501366004612bce565b61113f565b348015610511575f80fd5b5061051a61118c565b6040516102799796959493929190612c25565b348015610538575f80fd5b506102a9610547366004612cbb565b6111ce565b348015610557575f80fd5b506105bd610566366004612cf4565b61ffff165f81815260036020908152604091829020548251308184015280840194909452825180850384018152606090940190925282519201919091206001600160a01b038216929091600160a01b900460ff1690565b604080516001600160a01b0390941684526020840192909252151590820152606001610279565b3480156105ef575f80fd5b506102ca606481565b348015610603575f80fd5b506102ca610612366004612422565b6111fa565b348015610622575f80fd5b506102a9610631366004612d0f565b61123c565b348015610641575f80fd5b506102a9610650366004612d40565b611268565b348015610660575f80fd5b506102ca61066f366004612422565b5f9081526004602052604090206001015490565b34801561068e575f80fd5b5061030261069d366004612de8565b63bc197c8160e01b95945050505050565b3480156106b9575f80fd5b506007546106cd90610100900461ffff1681565b60405161ffff9091168152602001610279565b3480156106eb575f80fd5b506102a96106fa366004612cf4565b61130a565b34801561070a575f80fd5b50610747610719366004612e7b565b5f9081526004602090815260408083206001600160a01b03949094168352929052205465ffffffffffff1690565b60405165ffffffffffff9091168152602001610279565b348015610769575f80fd5b5061026c610778366004612422565b6113ae565b348015610788575f80fd5b5061026c6113cd565b6102a961079f366004612a2b565b6113da565b3480156107af575f80fd5b506103026107be366004612ea3565b63f23a6e6160e01b95945050505050565b3480156107da575f80fd5b5061026c6107e9366004612422565b611667565b5f81815260046020526040902060020180546060919061080d90612ef6565b80601f016020809104026020016040519081016040528092919081815260200182805461083990612ef6565b80156108845780601f1061085b57610100808354040283529160200191610884565b820191905f5260205f20905b81548152906001019060200180831161086757829003601f168201915b50505050509050919050565b6005805461089d90612ef6565b80601f01602080910402602001604051908101604052809291908181526020018280546108c990612ef6565b80156109145780601f106108eb57610100808354040283529160200191610914565b820191905f5260205f20905b8154815290600101906020018083116108f757829003601f168201915b505050505081565b61ffff88165f908152600360205260408120548991600160a01b90910460ff161515900361095d57604051639b7a92d760e01b815260040160405180910390fd5b61ffff89165f908152600360209081526040918290208251808401909352546001600160a01b0381168352600160a01b900460ff1615159082018190526109b757604051639b7a92d760e01b815260040160405180910390fd5b80516001600160a01b031633146109e157604051633e779cf960e01b815260040160405180910390fd5b5f8981526002602052604090205460ff610100909104161515600114610a1a576040516301dd1d1560e71b815260040160405180910390fd5b8685141580610a295750868314155b15610a475760405163dbf15fa560e01b815260040160405180910390fd5b5f898152600260205260408120805462ff00001916620100001790555b87811015610b45575f808a8a84818110610a8057610a80612f2e565b9050602002016020810190610a959190612f42565b6001600160a01b0316898985818110610ab057610ab0612f2e565b90506020020135888886818110610ac957610ac9612f2e565b9050602002810190610adb9190612f5b565b604051610ae9929190612f9d565b5f6040518083038185875af1925050503d805f8114610b23576040519150601f19603f3d011682016040523d82523d5f602084013e610b28565b606091505b5091509150610b378282611686565b505050806001019050610a64565b50888a61ffff167f328d3074f6e96c8ffb9619ec805360a70b6af7ad7e24e7c73fd0968e5dc505c48a8a8a8a8a8a604051610b8596959493929190613068565b60405180910390a350505050505050505050565b61ffff84165f908152600360205260408120548590600160a01b900460ff1615158203610bd957604051639b7a92d760e01b815260040160405180910390fd5b5f610be6878787876116a2565b5f818152600260205260409020600101549091506001600160a01b03163314610c2257604051633e779cf960e01b815260040160405180910390fd5b610c2e878787876116db565b979650505050505050565b333014610c595760405163e890ccbf60e01b815260040160405180910390fd5b610c6482825f611781565b5050565b335f9081527f17ef568e3e12ab5b9c7254a8d58478811de00f9e6eb34345acd53bf8fd09d3ec602052604081205465ffffffffffff169003610cbd57604051633e779cf960e01b815260040160405180910390fd5b60075460ff1615610ce15760405163cc03ce1160e01b815260040160405180910390fd5b6007805460ff191660011790555f5b8151811015610c64575f6001600160a01b0316828281518110610d1557610d15612f2e565b6020026020010151602001516001600160a01b031614610d5157610d51828281518110610d4457610d44612f2e565b60200260200101516118f4565b600101610cf0565b61ffff85165f908152600360205260408120548690600160a01b900460ff1615158203610d9957604051639b7a92d760e01b815260040160405180910390fd5b61ffff87165f908152600360209081526040918290208251808401909352546001600160a01b0381168352600160a01b900460ff161515908201819052610df357604051639b7a92d760e01b815260040160405180910390fd5b610dfd3389611075565b610e1a57604051633e779cf960e01b815260040160405180910390fd5b610e28338989898989611a88565b98975050505050505050565b5f818152600260205260408120805460ff620100008204811691168115610e6057506005949350505050565b8015610e7157506001949350505050565b5f85815260026020526040812054600160281b900465ffffffffffff1690819003610ea25750600695945050505050565b5f610eac876111fa565b9050438110610ec157505f9695505050505050565b610eca87611d2b565b1580610edc5750610eda87611e60565b155b15610eee575060029695505050505050565b5060039695505050505050565b5f8281526002602081815260408084206001600160a01b0386168552909201905290205460ff165b92915050565b5f8181526002602052604081208054829182918291829182918291829182918291829182919060ff80821691610100810482169162010000820416906301000000810461ffff1690600160281b810465ffffffffffff1690600160581b900463ffffffff16610f988183613110565b876001015f9054906101000a90046001600160a01b03168860010160149054906101000a900463ffffffff168960010160189054906101000a900463ffffffff168a600101601c9054906101000a900463ffffffff168b600501548565ffffffffffff1695509c509c509c509c509c509c509c509c509c509c509c509c505091939597999b5091939597999b565b5f33905061104483828460405180602001604052805f815250611f6e565b505050565b3330146110695760405163e890ccbf60e01b815260040160405180910390fd5b610c6482826001611781565b61ffff81165f818152600360205260408082205490516364fa842760e01b81523060048201526024810193909352909182916001600160a01b0316906364fa84279060440161012060405180830381865afa1580156110d6573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906110fa919061315a565b515f8181526004602090815260408083206001600160a01b038916845290915290205490915065ffffffffffff168015158061113657505f1982145b95945050505050565b5f33905061118485828686868080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250611f6e92505050565b505b50505050565b5f6060805f805f606061119d612094565b6111a56120c5565b604080515f80825260208201909252600f60f81b9b939a50919850469750309650945092509050565b3330146111ee5760405163e890ccbf60e01b815260040160405180910390fd5b6111f7816118f4565b50565b5f8181526002602052604081205461122e90600160581b810463ffffffff1690600160281b900465ffffffffffff16613110565b65ffffffffffff1692915050565b33301461125c5760405163e890ccbf60e01b815260040160405180910390fd5b6006610c64828261324e565b3330146112885760405163e890ccbf60e01b815260040160405180910390fd5b81158061129557505f1982145b156112b3576040516329939fd360e21b815260040160405180910390fd5b5f8281526004602052604090206002016112cd828261324e565b50817f4c6d3d4a776b1458bbd518e75903a3f27a0c6f4597b10882784aa64769d56c71826040516112fe9190612467565b60405180910390a25050565b33301461132a5760405163e890ccbf60e01b815260040160405180910390fd5b61ffff81165f90815260036020526040812054600160a01b900460ff161515900361136857604051639b7a92d760e01b815260040160405180910390fd5b61ffff81165f81815260036020526040808220805460ff60a01b19169055517f519eb0bde04fa6068eddea64ada07d654914aa8a6bd2689cf2aeb02c61a4f1359190a250565b5f81815260026020526040902060030180546060919061080d90612ef6565b6006805461089d90612ef6565b61ffff85165f908152600360205260408120548691600160a01b90910460ff161515900361141b57604051639b7a92d760e01b815260040160405180910390fd5b5f611428878787876116a2565b61ffff88165f908152600360209081526040918290208251808401909352546001600160a01b0381168352600160a01b900460ff161515908201529091506114703389611075565b61148d57604051633e779cf960e01b815260040160405180910390fd5b5f82815260026020526040902054610100900460ff1615156001036114c55760405163fc0e49ff60e01b815260040160405180910390fd5b5f8281526002602052604090205460ff1615156001036114f857604051632ec3fe1560e11b815260040160405180910390fd5b5f8281526002602052604090206001810180546001600160a01b03191633179055805461ff001961ffff8b166301000000021664ffff00ff00199091161761010017815560030161154a878983613308565b505f828152600260205260409020600401611565858261324e565b505f8281526002602052604080822060050187905582519051637bf5b2fb60e01b81526001600160a01b0390911690637bf5b2fb906115b09033908d908d908d908d906004016133c1565b6020604051808303815f875af11580156115cc573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906115f09190613401565b9050806116105760405163528af36760e11b815260040160405180910390fd5b8861ffff16336001600160a01b03167f98e1e52af9c2155b4c2b4844cdccf64c85cb13dd804231d177ef6fea4325d4058a8a8a8a6040516116549493929190613420565b60405180910390a3505050505050505050565b5f81815260026020526040902060040180546060919061080d90612ef6565b60608261169b57611696826120f2565b610f23565b5080610f23565b5f848484846040516020016116ba949392919061344b565b60408051601f19818403018152919052805160209091012095945050505050565b5f806116e9868686866116a2565b5f8181526002602052604090205490915062010000900460ff168061171b57505f8181526002602052604090205460ff165b156117395760405163b831530960e01b815260040160405180910390fd5b5f81815260026020526040808220805460ff191660011790555182917f8eb4cfeba12ece86fc1590773502e55423b37db556543430337376b30d27c42b91a295945050505050565b5f8381526004602090815260408083206001600160a01b038616845290915290205465ffffffffffff1615600184016117cd576040516313d0e80160e31b815260040160405180910390fd5b6001600160a01b0383166117f4576040516329f62b5d60e11b815260040160405180910390fd5b811561185f575f8481526004602090815260408083206001600160a01b03871684529091529020805465ffffffffffff19164365ffffffffffff16179055801561185a575f84815260046020526040812060010180549161185483613479565b91905055505b6118b4565b5f8481526004602090815260408083206001600160a01b03871684529091529020805465ffffffffffff19169055806118b4575f8481526004602052604081206001018054916118ae83613491565b91905055505b811515836001600160a01b0316857f294507a8f5830b538faef39fbdd28f1164f27c8338a32fc7b47ddf82e4c8d9e460405160405180910390a450505050565b611909816020015163b095668760e01b61211a565b6119265760405163498a519360e11b815260040160405180910390fd5b6007805461ffff6101009182900481165f908152600360209081526040808320805460ff60a01b1916600160a01b17905590860151855485900484168352912080546001600160a01b039092166001600160a01b031990921691909117905582549190910416906001611998836134a6565b91906101000a81548161ffff021916908361ffff1602179055505080602001516001600160a01b03166380c8c3fb6001600760019054906101000a900461ffff166119e391906134c6565b835f0151846060015185604001516040518563ffffffff1660e01b8152600401611a10949392919061358d565b5f604051808303815f87803b158015611a27575f80fd5b505af1158015611a39573d5f803e3d5ffd5b5050600754611a55925060019150610100900461ffff166134c6565b61ffff167f753b7a99c84c928c5a0d08bebb7564f3f84d39310585ce05f9d043a40084bf8860405160405180910390a250565b61ffff85165f8181526003602090815260408083208151808301835290546001600160a01b038116808352600160a01b90910460ff1615159382019390935290516364fa842760e01b8152306004820152602481019490945291928391906364fa84279060440161012060405180830381865afa158015611b0b573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611b2f919061315a565b9050611b3d888888886116a2565b92508060c0015160ff165f03611b6657604051632dd4cc8d60e01b815260040160405180910390fd5b5f83815260026020526040902054600160281b900465ffffffffffff1615611ba15760405163b831530960e01b815260040160405180910390fd5b81516040516308979f7960e31b81526001600160a01b03909116906344bcfbc890611bda908c9085908c908c908c9030906004016135dc565b5f6040518083038186803b158015611bf0575f80fd5b505afa158015611c02573d5f803e3d5ffd5b5050505f848152600260205260409020905060038101611c23888a83613308565b50805460a08301516affffffffffffffff00000019909116630100000061ffff8c16026affffffffffff0000000000191617600160281b4365ffffffffffff16021763ffffffff60581b1916600160581b63ffffffff909216919091021781556001810180546001600160a01b0319166001600160a01b038c1617905560048101611cae868261324e565b508581600501819055508861ffff168a6001600160a01b0316857fb5856a9700a7e851456d3a16348b4ae0fbb11b06ac0af8dbe8e8652c57cc4cbd8b8b438860a0015163ffffffff1643611d029190613633565b8d8d604051611d1696959493929190613646565b60405180910390a45050509695505050505050565b5f81815260026020908152604080832080546301000000900461ffff16808552600384528285208351808501855290546001600160a01b038116808352600160a01b90910460ff1615159582019590955292516364fa842760e01b81523060048201526024810191909152909284916364fa84279060440161012060405180830381865afa158015611dbf573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611de3919061315a565b80515f9081526004602052604090206001015460c08201519192509060ff161580611e5657506001840154606490611e319063ffffffff600160e01b8204811691600160c01b90041661368a565b63ffffffff16611e4191906136a6565b60c0830151611e539060ff16836136a6565b11155b9695505050505050565b5f81815260026020908152604080832080546301000000900461ffff16808552600384528285208351808501855290546001600160a01b038116808352600160a01b90910460ff1615159582019590955292516364fa842760e01b81523060048201526024810191909152909284916364fa84279060440161012060405180830381865afa158015611ef4573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611f18919061315a565b80515f9081526004602052604090206001015460c08201519192509060ff161580611e5657506001840154611f5c90606490600160c01b900463ffffffff166136a6565b60e0830151611e539060ff16836136a6565b5f604051631f27a4f360e11b8152600481018690523090633e4f49e690602401602060405180830381865afa158015611fa9573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611fcd91906136bd565b6006811115611fde57611fde612aae565b14611ffc576040516322024acd60e21b815260040160405180910390fd5b5f848152600260205260409020546301000000900461ffff1661201f8482611075565b61203c57604051633e779cf960e01b815260040160405180910390fd5b61204785858561213c565b8260ff1685856001600160a01b03167f5be2678cab71c7d94235767eb1df3c57673f19e805cdc0edbd2e74854ae9f0f9856040516120859190612467565b60405180910390a45050505050565b60606120c07f506f77657220746f2074686520557365720000000000000000000000000000115f612260565b905090565b60606120c07f302e3300000000000000000000000000000000000000000000000000000000036001612260565b80511561210157805160208201fd5b60405163d6bda27560e01b815260040160405180910390fd5b5f61212483612309565b80156121355750612135838361233b565b9392505050565b5f8381526002602081815260408084206001600160a01b03871685529283019091529091205460ff16156121835760405163c9e3c8d960e01b815260040160405180910390fd5b6001600160a01b0383165f9081526002820160205260409020805460ff1916600117905560ff82166121f257600181018054600160a01b900463ffffffff169060146121ce836136db565b91906101000a81548163ffffffff021916908363ffffffff16021790555050611186565b5f1960ff83160161221c57600181018054600160c01b900463ffffffff169060186121ce836136db565b60011960ff83160161224757600181018054600160e01b900463ffffffff1690601c6121ce836136db565b6040516333397b4360e11b815260040160405180910390fd5b606060ff831461227a57612273836123be565b9050610f23565b81805461228690612ef6565b80601f01602080910402602001604051908101604052809291908181526020018280546122b290612ef6565b80156122fd5780601f106122d4576101008083540402835291602001916122fd565b820191905f5260205f20905b8154815290600101906020018083116122e057829003601f168201915b50505050509050610f23565b5f61231b826301ffc9a760e01b61233b565b8015610f235750612334826001600160e01b031961233b565b1592915050565b6040516001600160e01b0319821660248201525f90819060440160408051601f19818403018152919052602080820180516001600160e01b03166301ffc9a760e01b17815282519293505f9283928392909183918a617530fa92503d91505f5190508280156123ab575060208210155b8015610c2e575015159695505050505050565b60605f6123ca836123fb565b6040805160208082528183019092529192505f91906020820181803683375050509182525060208101929092525090565b5f60ff8216601f811115610f2357604051632cd44ac360e21b815260040160405180910390fd5b5f60208284031215612432575f80fd5b5035919050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f6121356020830184612439565b61ffff811681146111f7575f80fd5b803561249381612479565b919050565b5f8083601f8401126124a8575f80fd5b5081356001600160401b038111156124be575f80fd5b6020830191508360208260051b85010111156124d8575f80fd5b9250929050565b5f805f805f805f8060a0898b0312156124f6575f80fd5b883561250181612479565b97506020890135965060408901356001600160401b03811115612522575f80fd5b61252e8b828c01612498565b90975095505060608901356001600160401b0381111561254c575f80fd5b6125588b828c01612498565b90955093505060808901356001600160401b03811115612576575f80fd5b6125828b828c01612498565b999c989b5096995094979396929594505050565b5f8083601f8401126125a6575f80fd5b5081356001600160401b038111156125bc575f80fd5b6020830191508360208285010111156124d8575f80fd5b5f805f80606085870312156125e6575f80fd5b84356125f181612479565b935060208501356001600160401b0381111561260b575f80fd5b61261787828801612596565b9598909750949560400135949350505050565b80356001600160a01b0381168114612493575f80fd5b634e487b7160e01b5f52604160045260245ffd5b604051608081016001600160401b038111828210171561267657612676612640565b60405290565b60405161012081016001600160401b038111828210171561267657612676612640565b604051601f8201601f191681016001600160401b03811182821017156126c7576126c7612640565b604052919050565b5f82601f8301126126de575f80fd5b8135602083015f806001600160401b038411156126fd576126fd612640565b50601f8301601f19166020016127128161269f565b915050828152858383011115612726575f80fd5b828260208301375f92810160200192909252509392505050565b5f805f8060808587031215612753575f80fd5b61275c8561262a565b935061276a6020860161262a565b92506040850135915060608501356001600160401b0381111561278b575f80fd5b612797878288016126cf565b91505092959194509250565b5f80604083850312156127b4575f80fd5b823591506127c46020840161262a565b90509250929050565b5f6001600160401b038211156127e5576127e5612640565b5060051b60200190565b65ffffffffffff811681146111f7575f80fd5b8035612493816127ef565b63ffffffff811681146111f7575f80fd5b80356124938161280d565b60ff811681146111f7575f80fd5b803561249381612829565b5f818303610180811215612854575f80fd5b61285c612654565b915082356001600160401b03811115612873575f80fd5b61287f858286016126cf565b83525061288e6020840161262a565b602083015260408301356001600160401b038111156128ab575f80fd5b6128b7858286016126cf565b604084015250610120605f19820112156128cf575f80fd5b506128d861267c565b606083013581526128eb60808401612488565b60208201526128fc60a08401612802565b604082015261290d60c08401612802565b606082015261291e60e08401612488565b6080820152612930610100840161281e565b60a08201526129426101208401612837565b60c08201526129546101408401612837565b60e08201526129666101608401612488565b610100820152606082015292915050565b5f60208284031215612987575f80fd5b81356001600160401b0381111561299c575f80fd5b8201601f810184136129ac575f80fd5b80356129bf6129ba826127cd565b61269f565b8082825260208201915060208360051b8501019250868311156129e0575f80fd5b602084015b83811015612a205780356001600160401b03811115612a02575f80fd5b612a1189602083890101612842565b845250602092830192016129e5565b509695505050505050565b5f805f805f60808688031215612a3f575f80fd5b8535612a4a81612479565b945060208601356001600160401b03811115612a64575f80fd5b612a7088828901612596565b9095509350506040860135915060608601356001600160401b03811115612a95575f80fd5b612aa1888289016126cf565b9150509295509295909350565b634e487b7160e01b5f52602160045260245ffd5b6020810160078310612ae257634e487b7160e01b5f52602160045260245ffd5b91905290565b8c151581528b151560208201528a1515604082015261ffff8a16606082015265ffffffffffff8916608082015263ffffffff881660a082015261018081018760c0830152612b4160e08301886001600160a01b03169052565b63ffffffff95861661010083015293851661012082015291909316610140820152610160019190915298975050505050505050565b5f8060408385031215612b87575f80fd5b823591506020830135612b9981612829565b809150509250929050565b5f8060408385031215612bb5575f80fd5b612bbe8361262a565b91506020830135612b9981612479565b5f805f8060608587031215612be1575f80fd5b843593506020850135612bf381612829565b925060408501356001600160401b03811115612c0d575f80fd5b612c1987828801612596565b95989497509550505050565b60ff60f81b8816815260e060208201525f612c4360e0830189612439565b8281036040840152612c558189612439565b606084018890526001600160a01b038716608085015260a0840186905283810360c0850152845180825260208087019350909101905f5b81811015612caa578351835260209384019390920191600101612c8c565b50909b9a5050505050505050505050565b5f60208284031215612ccb575f80fd5b81356001600160401b03811115612ce0575f80fd5b612cec84828501612842565b949350505050565b5f60208284031215612d04575f80fd5b813561213581612479565b5f60208284031215612d1f575f80fd5b81356001600160401b03811115612d34575f80fd5b612cec848285016126cf565b5f8060408385031215612d51575f80fd5b8235915060208301356001600160401b03811115612d6d575f80fd5b612d79858286016126cf565b9150509250929050565b5f82601f830112612d92575f80fd5b8135612da06129ba826127cd565b8082825260208201915060208360051b860101925085831115612dc1575f80fd5b602085015b83811015612dde578035835260209283019201612dc6565b5095945050505050565b5f805f805f60a08688031215612dfc575f80fd5b612e058661262a565b9450612e136020870161262a565b935060408601356001600160401b03811115612e2d575f80fd5b612e3988828901612d83565b93505060608601356001600160401b03811115612e54575f80fd5b612e6088828901612d83565b92505060808601356001600160401b03811115612a95575f80fd5b5f8060408385031215612e8c575f80fd5b612e958361262a565b946020939093013593505050565b5f805f805f60a08688031215612eb7575f80fd5b612ec08661262a565b9450612ece6020870161262a565b9350604086013592506060860135915060808601356001600160401b03811115612a95575f80fd5b600181811c90821680612f0a57607f821691505b602082108103612f2857634e487b7160e01b5f52602260045260245ffd5b50919050565b634e487b7160e01b5f52603260045260245ffd5b5f60208284031215612f52575f80fd5b6121358261262a565b5f808335601e19843603018112612f70575f80fd5b8301803591506001600160401b03821115612f89575f80fd5b6020019150368190038213156124d8575f80fd5b818382375f9101908152919050565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b5f8383855260208501945060208460051b820101835f5b8681101561305c57838303601f19018852813536879003601e19018112613010575f80fd5b86016020810190356001600160401b0381111561302b575f80fd5b803603821315613039575f80fd5b613044858284612fac565b60209a8b019a90955093909301925050600101612feb565b50909695505050505050565b606080825281018690525f8760808301825b898110156130a8576001600160a01b036130938461262a565b1682526020928301929091019060010161307a565b5083810360208501528681526001600160fb1b038711156130c7575f80fd5b8660051b91508188602083013701828103602090810160408501526130ef9082018587612fd4565b9998505050505050505050565b634e487b7160e01b5f52601160045260245ffd5b65ffffffffffff8181168382160190811115610f2357610f236130fc565b805161249381612479565b8051612493816127ef565b80516124938161280d565b805161249381612829565b5f61012082840312801561316c575f80fd5b5061317561267c565b825181526131856020840161312e565b602082015261319660408401613139565b60408201526131a760608401613139565b60608201526131b86080840161312e565b60808201526131c960a08401613144565b60a08201526131da60c0840161314f565b60c08201526131eb60e0840161314f565b60e08201526131fd610100840161312e565b6101008201529392505050565b601f82111561104457805f5260205f20601f840160051c8101602085101561322f5750805b601f840160051c820191505b81811015611184575f815560010161323b565b81516001600160401b0381111561326757613267612640565b61327b816132758454612ef6565b8461320a565b6020601f8211600181146132ad575f83156132965750848201515b5f19600385901b1c1916600184901b178455611184565b5f84815260208120601f198516915b828110156132dc57878501518255602094850194600190920191016132bc565b50848210156132f957868401515f19600387901b60f8161c191681555b50505050600190811b01905550565b6001600160401b0383111561331f5761331f612640565b6133338361332d8354612ef6565b8361320a565b5f601f841160018114613364575f851561334d5750838201355b5f19600387901b1c1916600186901b178355611184565b5f83815260208120601f198716915b828110156133935786850135825560209485019460019092019101613373565b50868210156133af575f1960f88860031b161c19848701351681555b505060018560011b0183555050505050565b6001600160a01b038616815261ffff851660208201526080604082018190525f906133ef9083018587612fac565b90508260608301529695505050505050565b5f60208284031215613411575f80fd5b81518015158114612135575f80fd5b606081525f613433606083018688612fac565b8460208401528281036040840152610c2e8185612439565b61ffff85168152606060208201525f613468606083018587612fac565b905082604083015295945050505050565b5f6001820161348a5761348a6130fc565b5060010190565b5f8161349f5761349f6130fc565b505f190190565b5f61ffff821661ffff81036134bd576134bd6130fc565b60010192915050565b61ffff8281168282160390811115610f2357610f236130fc565b8051825261ffff602082015116602083015265ffffffffffff6040820151166040830152606081015161351d606084018265ffffffffffff169052565b506080810151613533608084018261ffff169052565b5060a081015161354b60a084018263ffffffff169052565b5060c081015161356060c084018260ff169052565b5060e081015161357560e084018260ff169052565b5061010081015161104461010084018261ffff169052565b61ffff851681526101a060208201525f6135ab6101a0830186612439565b8281038060408501525f82526135c460608501876134e0565b6020810161018085015250610c2e6020820185612439565b6001600160a01b03871681526135f560208201876134e0565b6101a06101408201525f61360e6101a083018688612fac565b610160830194909452506001600160a01b039190911661018090910152949350505050565b80820180821115610f2357610f236130fc565b60c081525f60c082015260e060208201525f61366660e08301888a612fac565b86604084015285606084015284608084015282810360a08401526130ef8185612439565b63ffffffff8181168382160190811115610f2357610f236130fc565b8082028115828204841417610f2357610f236130fc565b5f602082840312156136cd575f80fd5b815160078110612135575f80fd5b5f63ffffffff821663ffffffff81036134bd576134bd6130fc56fea2646970667358221220321a1e1c554b32824d35644e58e765206932888fb8b05560b878507cb2a5a26f64736f6c634300081a0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000011506f77657220746f207468652055736572000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007068747470733a2f2f617175612d66616d6f75732d7361696c666973682d3238382e6d7970696e6174612e636c6f75642f697066732f6261666b72656965696f7074666f706d64646770696f7767366475757a7364346e366b6f69627574746865763732646e6d7765637a6a796273347100000000000000000000000000000000
-----Decoded View---------------
Arg [0] : name_ (string): Power to the User
Arg [1] : uri_ (string): https://aqua-famous-sailfish-288.mypinata.cloud/ipfs/bafkreieioptfopmddgpiowg6duuzsd4n6koibutthev72dnmweczjybs4q
-----Encoded View---------------
9 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000040
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000080
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000011
Arg [3] : 506f77657220746f207468652055736572000000000000000000000000000000
Arg [4] : 0000000000000000000000000000000000000000000000000000000000000070
Arg [5] : 68747470733a2f2f617175612d66616d6f75732d7361696c666973682d323838
Arg [6] : 2e6d7970696e6174612e636c6f75642f697066732f6261666b72656965696f70
Arg [7] : 74666f706d64646770696f7767366475757a7364346e366b6f69627574746865
Arg [8] : 763732646e6d7765637a6a796273347100000000000000000000000000000000
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.