Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 9 from a total of 9 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Register MKR For | 18742050 | 302 days ago | IN | 0 ETH | 0.00495978 | ||||
Register MKR For | 18742030 | 302 days ago | IN | 0 ETH | 0.00556397 | ||||
Register MKR For | 18741948 | 302 days ago | IN | 0 ETH | 0.00359925 | ||||
Register MKR For | 18741947 | 302 days ago | IN | 0 ETH | 0.00362914 | ||||
Register MKR For | 18536680 | 331 days ago | IN | 0 ETH | 0.00357252 | ||||
Register MKR For | 18536649 | 331 days ago | IN | 0 ETH | 0.00362395 | ||||
Register MKR For | 18536634 | 331 days ago | IN | 0 ETH | 0.00354644 | ||||
Register MKR For | 18536607 | 331 days ago | IN | 0 ETH | 0.00296252 | ||||
Register MKR For | 18536497 | 331 days ago | IN | 0 ETH | 0.00375083 |
Latest 1 internal transaction
Advanced mode:
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
18524509 | 333 days ago | Contract Creation | 0 ETH |
Loading...
Loading
Contract Name:
MKRVerifier
Compiler Version
v0.8.21+commit.d9974bed
Optimization Enabled:
Yes with 1000000 runs
Other Settings:
shanghai EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.8.19; // import { console2 } from "forge-std/Test.sol"; // comment out before deploy import { IHatsEligibility } from "hats-protocol/Interfaces/IHatsEligibility.sol"; import { IHats } from "hats-protocol/Interfaces/IHats.sol"; import { SignatureCheckerLib } from "solady/utils/SignatureCheckerLib.sol"; interface ERC20Like { function balanceOf(address account) external view returns (uint256); } /** * @title MKRVerifier * @author spengrah * @notice This contract is used to verify that a MakerDAO ecosystem actor has a balance of at least the amount of MKR * they claim to have. * It also serves as an eligibility module for Hats Protocol, and as such be used to determine * whether an ecosystem actor is eligible to hold a particular role within the MakerDAO ecosystem. */ contract MKRVerifier is IHatsEligibility { /*////////////////////////////////////////////////////////////// CUSTOM ERRORS //////////////////////////////////////////////////////////////*/ /// @dev Thrown when an ecosystem actor tries to register more MKR than they have error InsufficientMKR(); /// @dev Thrown when a non-facilitator tries to register MKR for an ecosystem actor error Unauthorized(); /// @dev Thrown when a signature is invalid error InvalidSignature(); /*////////////////////////////////////////////////////////////// EVENTS //////////////////////////////////////////////////////////////*/ /** * @notice Emitted when MKR is registered for an ecosystem actor via this contract * @param ecosystemActor The ecosystem actor whose MKR was registered * @param amount The amount of MKR that was registered * @param message Raw string representation of the recognition submission message required by * [MIP113-5.2.1.2.3](https://mips.makerdao.com/mips/details/MIP113#5-2-1-2-3). */ event MKRRegistered(address ecosystemActor, uint256 amount, string message); /*////////////////////////////////////////////////////////////// CONSTANTS //////////////////////////////////////////////////////////////*/ /// @notice The MKR token contract ERC20Like public immutable MKR; /// @notice The Hats Protocol contract IHats public constant HATS = IHats(0x3bc1A0Ad72417f2d411118085256fC53CBdDd137); // v1.hatsprotocol.eth /*////////////////////////////////////////////////////////////// MUTABLE STATE //////////////////////////////////////////////////////////////*/ /// @notice The hat ID of the facilitator role uint256 public immutable FACILITATOR_HAT; /// @notice The amount of MKR an ecosystem actor has registered with this contract mapping(address ecosystemActor => uint256 registeredAmount) public registeredMKR; /*////////////////////////////////////////////////////////////// CONSTRUCTOR //////////////////////////////////////////////////////////////*/ /** * @notice Create a new MKRVerifier contract * @param _facilitatorHat The hat ID of the facilitator role */ constructor(address _MKR, uint256 _facilitatorHat) { MKR = ERC20Like(_MKR); FACILITATOR_HAT = _facilitatorHat; } /*////////////////////////////////////////////////////////////// HATS ELIGIBILITY FUNCTION //////////////////////////////////////////////////////////////*/ /// @inheritdoc IHatsEligibility function getWearerStatus(address _wearer, uint256 /*_hatId */ ) public view virtual override returns (bool eligible, bool standing) { /// @dev this module doesn't deal with standing, so we default it to true standing = true; /** * @dev wearers are eligible if they have at least some verified MKR, ie... * 1) they have registered some MKR with this contract, and * 2) their present MKR balance is greater than or equal to their amount registered */ eligible = getVerifiedMKR(_wearer) > 0; } /*////////////////////////////////////////////////////////////// PUBLIC FUNCTIONS //////////////////////////////////////////////////////////////*/ /** * @notice Register an amount of MKR to be used for eligibility verification. The caller must have at least as much * MKR as they are trying to register. * This function can also be used by an ecosystem actor to update their registered amount. * @param _amount The amount of MKR to register * @param _message Raw string representation of the recognition submission message required by * [MIP113-5.2.1.2.3](https://mips.makerdao.com/mips/details/MIP113#5-2-1-2-3). */ function registerMKR(uint256 _amount, string calldata _message) public { _registerMKR(msg.sender, _amount, _message); } /*////////////////////////////////////////////////////////////// facilitator FUNCTIONS //////////////////////////////////////////////////////////////*/ /** * @notice Register an amount of MKR to be used for eligibility verification for an `_ecosystemActor`. The * `_ecosystemActor` must have at least as much MKR as the registration `_amount`. Can only be called by a wearer of * the facilitator hat. * @param _ecosystemActor The ecosystem actor to register MKR for. * @param _amount The amount of MKR to register. Must be <= the ecosystem actor's MKR balance. * @param _message Raw string representation of the recognition submission message required by * [MIP113-5.2.1.2.3](https://mips.makerdao.com/mips/details/MIP113#5-2-1-2-3). * @param _sig An EIP-191-compatible signature by `_ecosystemActor` of the EIP-191-compatible hash of `_message`. * @custom:version Next version should use EIP712 signatures */ function registerMKRFor(address _ecosystemActor, uint256 _amount, string calldata _message, bytes calldata _sig) public { // only the facilitator can register MKR for an ecosystem actor if (!HATS.isWearerOfHat(msg.sender, FACILITATOR_HAT)) revert Unauthorized(); // verify the signature if (!_verifySig(_ecosystemActor, _message, _sig)) revert InvalidSignature(); // check balance and register the MKR _registerMKR(_ecosystemActor, _amount, _message); } /*////////////////////////////////////////////////////////////// VIEW FUNCTIONS //////////////////////////////////////////////////////////////*/ /** * @notice Get the amount of verified MKR an ecosystem actor. An ecosystem actor's verified MKR is the amount of MKR * they have registered with this contract, as long as their present MKR balance is greater than or equal to that * amount. If their balance is lower than their registered amount, their verified amount is 0. * @param _ecosystemActor The ecosystem actor to check. * @return verifiedAmount The amount of verified MKR the ecosystem actor has. */ function getVerifiedMKR(address _ecosystemActor) public view returns (uint256 verifiedAmount) { uint256 registeredAmount = registeredMKR[_ecosystemActor]; // set verified amount to registered amount if their balance covers the registered amount // otherwise, verified amount remains 0 (as initialized) if (MKR.balanceOf(_ecosystemActor) >= registeredAmount) verifiedAmount = registeredAmount; } /*////////////////////////////////////////////////////////////// INTERNAL FUNCTIONS //////////////////////////////////////////////////////////////*/ /** * @dev Check an `ecosystemActor`'s MKR balance and register the MKR if they have enough * @param _ecosystemActor The ecosystem actor to register MKR for. * @param _amount The amount of MKR to register. Must be <= the ecosystem actor's MKR balance. */ function _registerMKR(address _ecosystemActor, uint256 _amount, string calldata _message) internal { // the ecosystem actor must have at least as much MKR as they are trying to register if (MKR.balanceOf(_ecosystemActor) < _amount) revert InsufficientMKR(); // set the ecosystem actor's registered amount registeredMKR[_ecosystemActor] = _amount; // log the registration emit MKRRegistered(_ecosystemActor, _amount, _message); } /** * @dev Verify whether `_sig` is a valid EIP-191 signature of `_message` by `_ecosystemActor`. First converts the * `_message` to an EIP-191-compatible message hash, then checks the signature against that hash. * @param _ecosystemActor The ecosystem actor who signed the message. * @param _message A raw string message. * @param _sig An EIP-191-compatible signature by `_ecosystemActor` of the EIP-191-compatible hash of `_message`. */ function _verifySig(address _ecosystemActor, string calldata _message, bytes calldata _sig) internal view returns (bool) { return SignatureCheckerLib.isValidSignatureNowCalldata( _ecosystemActor, SignatureCheckerLib.toEthSignedMessageHash(abi.encodePacked(_message)), _sig ); } }
// SPDX-License-Identifier: AGPL-3.0 // Copyright (C) 2023 Haberdasher Labs // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Affero General Public License for more details. // // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see <https://www.gnu.org/licenses/>. pragma solidity >=0.8.13; interface IHatsEligibility { /// @notice Returns the status of a wearer for a given hat /// @dev If standing is false, eligibility MUST also be false /// @param _wearer The address of the current or prospective Hat wearer /// @param _hatId The id of the hat in question /// @return eligible Whether the _wearer is eligible to wear the hat /// @return standing Whether the _wearer is in goog standing function getWearerStatus(address _wearer, uint256 _hatId) external view returns (bool eligible, bool standing); }
// SPDX-License-Identifier: AGPL-3.0 // Copyright (C) 2023 Haberdasher Labs // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Affero General Public License for more details. // // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see <https://www.gnu.org/licenses/>. pragma solidity >=0.8.13; import "./IHatsIdUtilities.sol"; import "./HatsErrors.sol"; import "./HatsEvents.sol"; interface IHats is IHatsIdUtilities, HatsErrors, HatsEvents { function mintTopHat(address _target, string memory _details, string memory _imageURI) external returns (uint256 topHatId); function createHat( uint256 _admin, string calldata _details, uint32 _maxSupply, address _eligibility, address _toggle, bool _mutable, string calldata _imageURI ) external returns (uint256 newHatId); function batchCreateHats( uint256[] calldata _admins, string[] calldata _details, uint32[] calldata _maxSupplies, address[] memory _eligibilityModules, address[] memory _toggleModules, bool[] calldata _mutables, string[] calldata _imageURIs ) external returns (bool success); function getNextId(uint256 _admin) external view returns (uint256 nextId); function mintHat(uint256 _hatId, address _wearer) external returns (bool success); function batchMintHats(uint256[] calldata _hatIds, address[] calldata _wearers) external returns (bool success); function setHatStatus(uint256 _hatId, bool _newStatus) external returns (bool toggled); function checkHatStatus(uint256 _hatId) external returns (bool toggled); function setHatWearerStatus(uint256 _hatId, address _wearer, bool _eligible, bool _standing) external returns (bool updated); function checkHatWearerStatus(uint256 _hatId, address _wearer) external returns (bool updated); function renounceHat(uint256 _hatId) external; function transferHat(uint256 _hatId, address _from, address _to) external; /*////////////////////////////////////////////////////////////// HATS ADMIN FUNCTIONS //////////////////////////////////////////////////////////////*/ function makeHatImmutable(uint256 _hatId) external; function changeHatDetails(uint256 _hatId, string memory _newDetails) external; function changeHatEligibility(uint256 _hatId, address _newEligibility) external; function changeHatToggle(uint256 _hatId, address _newToggle) external; function changeHatImageURI(uint256 _hatId, string memory _newImageURI) external; function changeHatMaxSupply(uint256 _hatId, uint32 _newMaxSupply) external; function requestLinkTopHatToTree(uint32 _topHatId, uint256 _newAdminHat) external; function approveLinkTopHatToTree( uint32 _topHatId, uint256 _newAdminHat, address _eligibility, address _toggle, string calldata _details, string calldata _imageURI ) external; function unlinkTopHatFromTree(uint32 _topHatId, address _wearer) external; function relinkTopHatWithinTree( uint32 _topHatDomain, uint256 _newAdminHat, address _eligibility, address _toggle, string calldata _details, string calldata _imageURI ) external; /*////////////////////////////////////////////////////////////// VIEW FUNCTIONS //////////////////////////////////////////////////////////////*/ function viewHat(uint256 _hatId) external view returns ( string memory details, uint32 maxSupply, uint32 supply, address eligibility, address toggle, string memory imageURI, uint16 lastHatId, bool mutable_, bool active ); function isWearerOfHat(address _user, uint256 _hatId) external view returns (bool isWearer); function isAdminOfHat(address _user, uint256 _hatId) external view returns (bool isAdmin); function isInGoodStanding(address _wearer, uint256 _hatId) external view returns (bool standing); function isEligible(address _wearer, uint256 _hatId) external view returns (bool eligible); function getHatEligibilityModule(uint256 _hatId) external view returns (address eligibility); function getHatToggleModule(uint256 _hatId) external view returns (address toggle); function getHatMaxSupply(uint256 _hatId) external view returns (uint32 maxSupply); function hatSupply(uint256 _hatId) external view returns (uint32 supply); function getImageURIForHat(uint256 _hatId) external view returns (string memory _uri); function balanceOf(address wearer, uint256 hatId) external view returns (uint256 balance); function balanceOfBatch(address[] calldata _wearers, uint256[] calldata _hatIds) external view returns (uint256[] memory); function uri(uint256 id) external view returns (string memory _uri); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; /// @notice Signature verification helper that supports both ECDSA signatures from EOAs /// and ERC1271 signatures from smart contract wallets like Argent and Gnosis safe. /// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/SignatureCheckerLib.sol) /// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/cryptography/SignatureChecker.sol) /// /// @dev Note: /// - The signature checking functions use the ecrecover precompile (0x1). /// - The `bytes memory signature` variants use the identity precompile (0x4) /// to copy memory internally. /// - Unlike ECDSA signatures, contract signatures are revocable. /// /// WARNING! Do NOT use signatures as unique identifiers. /// Please use EIP712 with a nonce included in the digest to prevent replay attacks. /// This implementation does NOT check if a signature is non-malleable. library SignatureCheckerLib { /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* SIGNATURE CHECKING OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns whether `signature` is valid for `signer` and `hash`. /// If `signer` is a smart contract, the signature is validated with ERC1271. /// Otherwise, the signature is validated with `ECDSA.recover`. function isValidSignatureNow(address signer, bytes32 hash, bytes memory signature) internal view returns (bool isValid) { /// @solidity memory-safe-assembly assembly { // Clean the upper 96 bits of `signer` in case they are dirty. for { signer := shr(96, shl(96, signer)) } signer {} { let m := mload(0x40) if eq(mload(signature), 65) { mstore(0x00, hash) mstore(0x20, byte(0, mload(add(signature, 0x60)))) // `v`. mstore(0x40, mload(add(signature, 0x20))) // `r`. mstore(0x60, mload(add(signature, 0x40))) // `s`. let t := staticcall( gas(), // Amount of gas left for the transaction. 1, // Address of `ecrecover`. 0x00, // Start of input. 0x80, // Size of input. 0x01, // Start of output. 0x20 // Size of output. ) // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise. if iszero(or(iszero(returndatasize()), xor(signer, mload(t)))) { isValid := 1 mstore(0x60, 0) // Restore the zero slot. mstore(0x40, m) // Restore the free memory pointer. break } } mstore(0x60, 0) // Restore the zero slot. mstore(0x40, m) // Restore the free memory pointer. let f := shl(224, 0x1626ba7e) mstore(m, f) // `bytes4(keccak256("isValidSignature(bytes32,bytes)"))`. mstore(add(m, 0x04), hash) let d := add(m, 0x24) mstore(d, 0x40) // The offset of the `signature` in the calldata. // Copy the `signature` over. let n := add(0x20, mload(signature)) pop(staticcall(gas(), 4, signature, n, add(m, 0x44), n)) // forgefmt: disable-next-item isValid := and( // Whether the returndata is the magic value `0x1626ba7e` (left-aligned). eq(mload(d), f), // Whether the staticcall does not revert. // This must be placed at the end of the `and` clause, // as the arguments are evaluated from right to left. staticcall( gas(), // Remaining gas. signer, // The `signer` address. m, // Offset of calldata in memory. add(returndatasize(), 0x44), // Length of calldata in memory. d, // Offset of returndata. 0x20 // Length of returndata to write. ) ) break } } } /// @dev Returns whether `signature` is valid for `signer` and `hash`. /// If `signer` is a smart contract, the signature is validated with ERC1271. /// Otherwise, the signature is validated with `ECDSA.recover`. function isValidSignatureNowCalldata(address signer, bytes32 hash, bytes calldata signature) internal view returns (bool isValid) { /// @solidity memory-safe-assembly assembly { // Clean the upper 96 bits of `signer` in case they are dirty. for { signer := shr(96, shl(96, signer)) } signer {} { let m := mload(0x40) if eq(signature.length, 65) { mstore(0x00, hash) mstore(0x20, byte(0, calldataload(add(signature.offset, 0x40)))) // `v`. calldatacopy(0x40, signature.offset, 0x40) // `r`, `s`. let t := staticcall( gas(), // Amount of gas left for the transaction. 1, // Address of `ecrecover`. 0x00, // Start of input. 0x80, // Size of input. 0x01, // Start of output. 0x20 // Size of output. ) // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise. if iszero(or(iszero(returndatasize()), xor(signer, mload(t)))) { isValid := 1 mstore(0x60, 0) // Restore the zero slot. mstore(0x40, m) // Restore the free memory pointer. break } } mstore(0x60, 0) // Restore the zero slot. mstore(0x40, m) // Restore the free memory pointer. let f := shl(224, 0x1626ba7e) mstore(m, f) // `bytes4(keccak256("isValidSignature(bytes32,bytes)"))`. mstore(add(m, 0x04), hash) let d := add(m, 0x24) mstore(d, 0x40) // The offset of the `signature` in the calldata. mstore(add(m, 0x44), signature.length) // Copy the `signature` over. calldatacopy(add(m, 0x64), signature.offset, signature.length) // forgefmt: disable-next-item isValid := and( // Whether the returndata is the magic value `0x1626ba7e` (left-aligned). eq(mload(d), f), // Whether the staticcall does not revert. // This must be placed at the end of the `and` clause, // as the arguments are evaluated from right to left. staticcall( gas(), // Remaining gas. signer, // The `signer` address. m, // Offset of calldata in memory. add(signature.length, 0x64), // Length of calldata in memory. d, // Offset of returndata. 0x20 // Length of returndata to write. ) ) break } } } /// @dev Returns whether the signature (`r`, `vs`) is valid for `signer` and `hash`. /// If `signer` is a smart contract, the signature is validated with ERC1271. /// Otherwise, the signature is validated with `ECDSA.recover`. function isValidSignatureNow(address signer, bytes32 hash, bytes32 r, bytes32 vs) internal view returns (bool isValid) { /// @solidity memory-safe-assembly assembly { // Clean the upper 96 bits of `signer` in case they are dirty. for { signer := shr(96, shl(96, signer)) } signer {} { let m := mload(0x40) mstore(0x00, hash) mstore(0x20, add(shr(255, vs), 27)) // `v`. mstore(0x40, r) // `r`. mstore(0x60, shr(1, shl(1, vs))) // `s`. let t := staticcall( gas(), // Amount of gas left for the transaction. 1, // Address of `ecrecover`. 0x00, // Start of input. 0x80, // Size of input. 0x01, // Start of output. 0x20 // Size of output. ) // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise. if iszero(or(iszero(returndatasize()), xor(signer, mload(t)))) { isValid := 1 mstore(0x60, 0) // Restore the zero slot. mstore(0x40, m) // Restore the free memory pointer. break } let f := shl(224, 0x1626ba7e) mstore(m, f) // `bytes4(keccak256("isValidSignature(bytes32,bytes)"))`. mstore(add(m, 0x04), hash) let d := add(m, 0x24) mstore(d, 0x40) // The offset of the `signature` in the calldata. mstore(add(m, 0x44), 65) // Length of the signature. mstore(add(m, 0x64), r) // `r`. mstore(add(m, 0x84), mload(0x60)) // `s`. mstore8(add(m, 0xa4), mload(0x20)) // `v`. // forgefmt: disable-next-item isValid := and( // Whether the returndata is the magic value `0x1626ba7e` (left-aligned). eq(mload(d), f), // Whether the staticcall does not revert. // This must be placed at the end of the `and` clause, // as the arguments are evaluated from right to left. staticcall( gas(), // Remaining gas. signer, // The `signer` address. m, // Offset of calldata in memory. 0xa5, // Length of calldata in memory. d, // Offset of returndata. 0x20 // Length of returndata to write. ) ) mstore(0x60, 0) // Restore the zero slot. mstore(0x40, m) // Restore the free memory pointer. break } } } /// @dev Returns whether the signature (`v`, `r`, `s`) is valid for `signer` and `hash`. /// If `signer` is a smart contract, the signature is validated with ERC1271. /// Otherwise, the signature is validated with `ECDSA.recover`. function isValidSignatureNow(address signer, bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal view returns (bool isValid) { /// @solidity memory-safe-assembly assembly { // Clean the upper 96 bits of `signer` in case they are dirty. for { signer := shr(96, shl(96, signer)) } signer {} { let m := mload(0x40) mstore(0x00, hash) mstore(0x20, and(v, 0xff)) // `v`. mstore(0x40, r) // `r`. mstore(0x60, s) // `s`. let t := staticcall( gas(), // Amount of gas left for the transaction. 1, // Address of `ecrecover`. 0x00, // Start of input. 0x80, // Size of input. 0x01, // Start of output. 0x20 // Size of output. ) // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise. if iszero(or(iszero(returndatasize()), xor(signer, mload(t)))) { isValid := 1 mstore(0x60, 0) // Restore the zero slot. mstore(0x40, m) // Restore the free memory pointer. break } let f := shl(224, 0x1626ba7e) mstore(m, f) // `bytes4(keccak256("isValidSignature(bytes32,bytes)"))`. mstore(add(m, 0x04), hash) let d := add(m, 0x24) mstore(d, 0x40) // The offset of the `signature` in the calldata. mstore(add(m, 0x44), 65) // Length of the signature. mstore(add(m, 0x64), r) // `r`. mstore(add(m, 0x84), s) // `s`. mstore8(add(m, 0xa4), v) // `v`. // forgefmt: disable-next-item isValid := and( // Whether the returndata is the magic value `0x1626ba7e` (left-aligned). eq(mload(d), f), // Whether the staticcall does not revert. // This must be placed at the end of the `and` clause, // as the arguments are evaluated from right to left. staticcall( gas(), // Remaining gas. signer, // The `signer` address. m, // Offset of calldata in memory. 0xa5, // Length of calldata in memory. d, // Offset of returndata. 0x20 // Length of returndata to write. ) ) mstore(0x60, 0) // Restore the zero slot. mstore(0x40, m) // Restore the free memory pointer. break } } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* ERC1271 OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns whether `signature` is valid for `hash` /// for an ERC1271 `signer` contract. function isValidERC1271SignatureNow(address signer, bytes32 hash, bytes memory signature) internal view returns (bool isValid) { /// @solidity memory-safe-assembly assembly { let m := mload(0x40) let f := shl(224, 0x1626ba7e) mstore(m, f) // `bytes4(keccak256("isValidSignature(bytes32,bytes)"))`. mstore(add(m, 0x04), hash) let d := add(m, 0x24) mstore(d, 0x40) // The offset of the `signature` in the calldata. // Copy the `signature` over. let n := add(0x20, mload(signature)) pop(staticcall(gas(), 4, signature, n, add(m, 0x44), n)) // forgefmt: disable-next-item isValid := and( // Whether the returndata is the magic value `0x1626ba7e` (left-aligned). eq(mload(d), f), // Whether the staticcall does not revert. // This must be placed at the end of the `and` clause, // as the arguments are evaluated from right to left. staticcall( gas(), // Remaining gas. signer, // The `signer` address. m, // Offset of calldata in memory. add(returndatasize(), 0x44), // Length of calldata in memory. d, // Offset of returndata. 0x20 // Length of returndata to write. ) ) } } /// @dev Returns whether `signature` is valid for `hash` /// for an ERC1271 `signer` contract. function isValidERC1271SignatureNowCalldata( address signer, bytes32 hash, bytes calldata signature ) internal view returns (bool isValid) { /// @solidity memory-safe-assembly assembly { let m := mload(0x40) let f := shl(224, 0x1626ba7e) mstore(m, f) // `bytes4(keccak256("isValidSignature(bytes32,bytes)"))`. mstore(add(m, 0x04), hash) let d := add(m, 0x24) mstore(d, 0x40) // The offset of the `signature` in the calldata. mstore(add(m, 0x44), signature.length) // Copy the `signature` over. calldatacopy(add(m, 0x64), signature.offset, signature.length) // forgefmt: disable-next-item isValid := and( // Whether the returndata is the magic value `0x1626ba7e` (left-aligned). eq(mload(d), f), // Whether the staticcall does not revert. // This must be placed at the end of the `and` clause, // as the arguments are evaluated from right to left. staticcall( gas(), // Remaining gas. signer, // The `signer` address. m, // Offset of calldata in memory. add(signature.length, 0x64), // Length of calldata in memory. d, // Offset of returndata. 0x20 // Length of returndata to write. ) ) } } /// @dev Returns whether the signature (`r`, `vs`) is valid for `hash` /// for an ERC1271 `signer` contract. function isValidERC1271SignatureNow(address signer, bytes32 hash, bytes32 r, bytes32 vs) internal view returns (bool isValid) { /// @solidity memory-safe-assembly assembly { let m := mload(0x40) let f := shl(224, 0x1626ba7e) mstore(m, f) // `bytes4(keccak256("isValidSignature(bytes32,bytes)"))`. mstore(add(m, 0x04), hash) let d := add(m, 0x24) mstore(d, 0x40) // The offset of the `signature` in the calldata. mstore(add(m, 0x44), 65) // Length of the signature. mstore(add(m, 0x64), r) // `r`. mstore(add(m, 0x84), shr(1, shl(1, vs))) // `s`. mstore8(add(m, 0xa4), add(shr(255, vs), 27)) // `v`. // forgefmt: disable-next-item isValid := and( // Whether the returndata is the magic value `0x1626ba7e` (left-aligned). eq(mload(d), f), // Whether the staticcall does not revert. // This must be placed at the end of the `and` clause, // as the arguments are evaluated from right to left. staticcall( gas(), // Remaining gas. signer, // The `signer` address. m, // Offset of calldata in memory. 0xa5, // Length of calldata in memory. d, // Offset of returndata. 0x20 // Length of returndata to write. ) ) } } /// @dev Returns whether the signature (`v`, `r`, `s`) is valid for `hash` /// for an ERC1271 `signer` contract. function isValidERC1271SignatureNow(address signer, bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal view returns (bool isValid) { /// @solidity memory-safe-assembly assembly { let m := mload(0x40) let f := shl(224, 0x1626ba7e) mstore(m, f) // `bytes4(keccak256("isValidSignature(bytes32,bytes)"))`. mstore(add(m, 0x04), hash) let d := add(m, 0x24) mstore(d, 0x40) // The offset of the `signature` in the calldata. mstore(add(m, 0x44), 65) // Length of the signature. mstore(add(m, 0x64), r) // `r`. mstore(add(m, 0x84), s) // `s`. mstore8(add(m, 0xa4), v) // `v`. // forgefmt: disable-next-item isValid := and( // Whether the returndata is the magic value `0x1626ba7e` (left-aligned). eq(mload(d), f), // Whether the staticcall does not revert. // This must be placed at the end of the `and` clause, // as the arguments are evaluated from right to left. staticcall( gas(), // Remaining gas. signer, // The `signer` address. m, // Offset of calldata in memory. 0xa5, // Length of calldata in memory. d, // Offset of returndata. 0x20 // Length of returndata to write. ) ) } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* HASHING OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns an Ethereum Signed Message, created from a `hash`. /// This produces a hash corresponding to the one signed with the /// [`eth_sign`](https://eth.wiki/json-rpc/API#eth_sign) /// JSON-RPC method as part of EIP-191. function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32 result) { /// @solidity memory-safe-assembly assembly { mstore(0x20, hash) // Store into scratch space for keccak256. mstore(0x00, "\x00\x00\x00\x00\x19Ethereum Signed Message:\n32") // 28 bytes. result := keccak256(0x04, 0x3c) // `32 * 2 - (32 - 28) = 60 = 0x3c`. } } /// @dev Returns an Ethereum Signed Message, created from `s`. /// This produces a hash corresponding to the one signed with the /// [`eth_sign`](https://eth.wiki/json-rpc/API#eth_sign) /// JSON-RPC method as part of EIP-191. /// Note: Supports lengths of `s` up to 999999 bytes. function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32 result) { /// @solidity memory-safe-assembly assembly { let sLength := mload(s) let o := 0x20 mstore(o, "\x19Ethereum Signed Message:\n") // 26 bytes, zero-right-padded. mstore(0x00, 0x00) // Convert the `s.length` to ASCII decimal representation: `base10(s.length)`. for { let temp := sLength } 1 {} { o := sub(o, 1) mstore8(o, add(48, mod(temp, 10))) temp := div(temp, 10) if iszero(temp) { break } } let n := sub(0x3a, o) // Header length: `26 + 32 - o`. // Throw an out-of-offset error (consumes all gas) if the header exceeds 32 bytes. returndatacopy(returndatasize(), returndatasize(), gt(n, 0x20)) mstore(s, or(mload(0x00), mload(n))) // Temporarily store the header. result := keccak256(add(s, sub(0x20, n)), add(n, sLength)) mstore(s, sLength) // Restore the length. } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* EMPTY CALLDATA HELPERS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns an empty calldata bytes. function emptySignature() internal pure returns (bytes calldata signature) { /// @solidity memory-safe-assembly assembly { signature.length := 0 } } }
// SPDX-License-Identifier: AGPL-3.0 // Copyright (C) 2023 Haberdasher Labs // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Affero General Public License for more details. // // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see <https://www.gnu.org/licenses/>. pragma solidity >=0.8.13; interface IHatsIdUtilities { function buildHatId(uint256 _admin, uint16 _newHat) external pure returns (uint256 id); function getHatLevel(uint256 _hatId) external view returns (uint32 level); function getLocalHatLevel(uint256 _hatId) external pure returns (uint32 level); function isTopHat(uint256 _hatId) external view returns (bool _topHat); function isLocalTopHat(uint256 _hatId) external pure returns (bool _localTopHat); function isValidHatId(uint256 _hatId) external view returns (bool validHatId); function getAdminAtLevel(uint256 _hatId, uint32 _level) external view returns (uint256 admin); function getAdminAtLocalLevel(uint256 _hatId, uint32 _level) external pure returns (uint256 admin); function getTopHatDomain(uint256 _hatId) external view returns (uint32 domain); function getTippyTopHatDomain(uint32 _topHatDomain) external view returns (uint32 domain); function noCircularLinkage(uint32 _topHatDomain, uint256 _linkedAdmin) external view returns (bool notCircular); function sameTippyTopHatDomain(uint32 _topHatDomain, uint256 _newAdminHat) external view returns (bool sameDomain); }
// SPDX-License-Identifier: AGPL-3.0 // Copyright (C) 2023 Haberdasher Labs // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Affero General Public License for more details. // // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see <https://www.gnu.org/licenses/>. pragma solidity >=0.8.13; interface HatsErrors { /// @notice Emitted when `user` is attempting to perform an action on `hatId` but is not wearing one of `hatId`'s admin hats /// @dev Can be equivalent to `NotHatWearer(buildHatId(hatId))`, such as when emitted by `approveLinkTopHatToTree` or `relinkTopHatToTree` error NotAdmin(address user, uint256 hatId); /// @notice Emitted when attempting to perform an action as or for an account that is not a wearer of a given hat error NotHatWearer(); /// @notice Emitted when attempting to perform an action that requires being either an admin or wearer of a given hat error NotAdminOrWearer(); /// @notice Emitted when attempting to mint `hatId` but `hatId`'s maxSupply has been reached error AllHatsWorn(uint256 hatId); /// @notice Emitted when attempting to create a hat with a level 14 hat as its admin error MaxLevelsReached(); /// @notice Emitted when an attempted hat id has empty intermediate level(s) error InvalidHatId(); /// @notice Emitted when attempting to mint `hatId` to a `wearer` who is already wearing the hat error AlreadyWearingHat(address wearer, uint256 hatId); /// @notice Emitted when attempting to mint a non-existant hat error HatDoesNotExist(uint256 hatId); /// @notice Emmitted when attempting to mint or transfer a hat that is not active error HatNotActive(); /// @notice Emitted when attempting to mint or transfer a hat to an ineligible wearer error NotEligible(); /// @notice Emitted when attempting to check or set a hat's status from an account that is not that hat's toggle module error NotHatsToggle(); /// @notice Emitted when attempting to check or set a hat wearer's status from an account that is not that hat's eligibility module error NotHatsEligibility(); /// @notice Emitted when array arguments to a batch function have mismatching lengths error BatchArrayLengthMismatch(); /// @notice Emitted when attempting to mutate or transfer an immutable hat error Immutable(); /// @notice Emitted when attempting to change a hat's maxSupply to a value lower than its current supply error NewMaxSupplyTooLow(); /// @notice Emitted when attempting to link a tophat to a new admin for which the tophat serves as an admin error CircularLinkage(); /// @notice Emitted when attempting to link or relink a tophat to a separate tree error CrossTreeLinkage(); /// @notice Emitted when attempting to link a tophat without a request error LinkageNotRequested(); /// @notice Emitted when attempting to unlink a tophat that does not have a wearer /// @dev This ensures that unlinking never results in a bricked tophat error InvalidUnlink(); /// @notice Emmited when attempting to change a hat's eligibility or toggle module to the zero address error ZeroAddress(); /// @notice Emmitted when attempting to change a hat's details or imageURI to a string with over 7000 bytes (~characters) /// @dev This protects against a DOS attack where an admin iteratively extend's a hat's details or imageURI /// to be so long that reading it exceeds the block gas limit, breaking `uri()` and `viewHat()` error StringTooLong(); }
// SPDX-License-Identifier: AGPL-3.0 // Copyright (C) 2023 Haberdasher Labs // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Affero General Public License for more details. // // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see <https://www.gnu.org/licenses/>. pragma solidity >=0.8.13; interface HatsEvents { /// @notice Emitted when a new hat is created /// @param id The id for the new hat /// @param details A description of the Hat /// @param maxSupply The total instances of the Hat that can be worn at once /// @param eligibility The address that can report on the Hat wearer's status /// @param toggle The address that can deactivate the Hat /// @param mutable_ Whether the hat's properties are changeable after creation /// @param imageURI The image uri for this hat and the fallback for its event HatCreated( uint256 id, string details, uint32 maxSupply, address eligibility, address toggle, bool mutable_, string imageURI ); /// @notice Emitted when a hat wearer's standing is updated /// @dev Eligibility is excluded since the source of truth for eligibility is the eligibility module and may change without a transaction /// @param hatId The id of the wearer's hat /// @param wearer The wearer's address /// @param wearerStanding Whether the wearer is in good standing for the hat event WearerStandingChanged(uint256 hatId, address wearer, bool wearerStanding); /// @notice Emitted when a hat's status is updated /// @param hatId The id of the hat /// @param newStatus Whether the hat is active event HatStatusChanged(uint256 hatId, bool newStatus); /// @notice Emitted when a hat's details are updated /// @param hatId The id of the hat /// @param newDetails The updated details event HatDetailsChanged(uint256 hatId, string newDetails); /// @notice Emitted when a hat's eligibility module is updated /// @param hatId The id of the hat /// @param newEligibility The updated eligibiliy module event HatEligibilityChanged(uint256 hatId, address newEligibility); /// @notice Emitted when a hat's toggle module is updated /// @param hatId The id of the hat /// @param newToggle The updated toggle module event HatToggleChanged(uint256 hatId, address newToggle); /// @notice Emitted when a hat's mutability is updated /// @param hatId The id of the hat event HatMutabilityChanged(uint256 hatId); /// @notice Emitted when a hat's maximum supply is updated /// @param hatId The id of the hat /// @param newMaxSupply The updated max supply event HatMaxSupplyChanged(uint256 hatId, uint32 newMaxSupply); /// @notice Emitted when a hat's image URI is updated /// @param hatId The id of the hat /// @param newImageURI The updated image URI event HatImageURIChanged(uint256 hatId, string newImageURI); /// @notice Emitted when a tophat linkage is requested by its admin /// @param domain The domain of the tree tophat to link /// @param newAdmin The tophat's would-be admin in the parent tree event TopHatLinkRequested(uint32 domain, uint256 newAdmin); /// @notice Emitted when a tophat is linked to a another tree /// @param domain The domain of the newly-linked tophat /// @param newAdmin The tophat's new admin in the parent tree event TopHatLinked(uint32 domain, uint256 newAdmin); }
{ "remappings": [ "ds-test/=lib/forge-std/lib/ds-test/src/", "forge-std/=lib/forge-std/src/", "hats-protocol/=lib/hats-protocol/src/", "solady/=lib/solady/src/", "ERC1155/=lib/hats-protocol/lib/ERC1155/", "solbase/=lib/hats-protocol/lib/solbase/src/", "utils/=lib/hats-protocol/lib/utils/" ], "optimizer": { "enabled": true, "runs": 1000000 }, "metadata": { "useLiteralContent": false, "bytecodeHash": "none", "appendCBOR": true }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "shanghai", "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"_MKR","type":"address"},{"internalType":"uint256","name":"_facilitatorHat","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"InsufficientMKR","type":"error"},{"inputs":[],"name":"InvalidSignature","type":"error"},{"inputs":[],"name":"Unauthorized","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"ecosystemActor","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"string","name":"message","type":"string"}],"name":"MKRRegistered","type":"event"},{"inputs":[],"name":"FACILITATOR_HAT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"HATS","outputs":[{"internalType":"contract IHats","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MKR","outputs":[{"internalType":"contract ERC20Like","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_ecosystemActor","type":"address"}],"name":"getVerifiedMKR","outputs":[{"internalType":"uint256","name":"verifiedAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_wearer","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"getWearerStatus","outputs":[{"internalType":"bool","name":"eligible","type":"bool"},{"internalType":"bool","name":"standing","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"string","name":"_message","type":"string"}],"name":"registerMKR","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_ecosystemActor","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"string","name":"_message","type":"string"},{"internalType":"bytes","name":"_sig","type":"bytes"}],"name":"registerMKRFor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"ecosystemActor","type":"address"}],"name":"registeredMKR","outputs":[{"internalType":"uint256","name":"registeredAmount","type":"uint256"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
60c060405234801561000f575f80fd5b5060405161098838038061098883398101604081905261002e91610044565b6001600160a01b0390911660805260a05261007b565b5f8060408385031215610055575f80fd5b82516001600160a01b038116811461006b575f80fd5b6020939093015192949293505050565b60805160a0516108d86100b05f395f818161018c01526101ed01525f818160a301528181610358015261042e01526108d85ff3fe608060405234801561000f575f80fd5b5060043610610085575f3560e01c80637150ef88116100585780637150ef881461012f578063739586aa1461014a578063bd6838721461015d578063bef59a0c14610187575f80fd5b8063102d282e146100895780633d31a4af1461009e57806341a49356146100ef57806358c655be1461011c575b5f80fd5b61009c6100973660046106da565b6101ae565b005b6100c57f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b61010e6100fd36600461074a565b5f6020819052908152604090205481565b6040519081526020016100e6565b61009c61012a36600461076a565b6101bf565b6100c5733bc1a0ad72417f2d411118085256fc53cbddd13781565b61010e61015836600461074a565b6102fc565b61017061016b3660046107ee565b6103d0565b6040805192151583529015156020830152016100e6565b61010e7f000000000000000000000000000000000000000000000000000000000000000081565b6101ba338484846103e7565b505050565b6040517f4352409a0000000000000000000000000000000000000000000000000000000081523360048201527f00000000000000000000000000000000000000000000000000000000000000006024820152733bc1a0ad72417f2d411118085256fc53cbddd13790634352409a90604401602060405180830381865afa15801561024b573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061026f9190610816565b6102a5576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6102b2868585858561053b565b6102e8576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6102f4868686866103e7565b505050505050565b73ffffffffffffffffffffffffffffffffffffffff8181165f818152602081905260408082205490517f70a0823100000000000000000000000000000000000000000000000000000000815260048101939093529092909182917f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa15801561039d573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103c19190610835565b106103ca578091505b50919050565b5f6001816103dd856102fc565b1191509250929050565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff858116600483015284917f0000000000000000000000000000000000000000000000000000000000000000909116906370a0823190602401602060405180830381865afa158015610475573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104999190610835565b10156104d1576040517f62adb94f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff84165f9081526020819052604090819020849055517ea36578399109fd77650bd7a46592880be61181e7fc62cce6211c9c12d9aa449061052d90869086908690869061084c565b60405180910390a150505050565b5f6105718661056a87876040516020016105569291906108bc565b60405160208183030381529060405261057b565b85856105e4565b9695505050505050565b5f815160207f19457468657265756d205369676e6564204d6573736167653a0a00000000000081525f8052815b600182039150600a81066030018253600a9004806105a85750603a03602081113d3d3e80515f5117845281810160209190910384012092525090565b73ffffffffffffffffffffffffffffffffffffffff909316925f841561068d576040516041830361064a57845f5260408401355f1a6020526040846040376020600160805f60015afa805187183d151761064857505f60605260405250600161068d565b505b5f60605280604052631626ba7e60e01b80825285600483015260248201604081528460448401528486606485013760208160648701858b5afa9051909114169150505b949350505050565b5f8083601f8401126106a5575f80fd5b50813567ffffffffffffffff8111156106bc575f80fd5b6020830191508360208285010111156106d3575f80fd5b9250929050565b5f805f604084860312156106ec575f80fd5b83359250602084013567ffffffffffffffff811115610709575f80fd5b61071586828701610695565b9497909650939450505050565b803573ffffffffffffffffffffffffffffffffffffffff81168114610745575f80fd5b919050565b5f6020828403121561075a575f80fd5b61076382610722565b9392505050565b5f805f805f806080878903121561077f575f80fd5b61078887610722565b955060208701359450604087013567ffffffffffffffff808211156107ab575f80fd5b6107b78a838b01610695565b909650945060608901359150808211156107cf575f80fd5b506107dc89828a01610695565b979a9699509497509295939492505050565b5f80604083850312156107ff575f80fd5b61080883610722565b946020939093013593505050565b5f60208284031215610826575f80fd5b81518015158114610763575f80fd5b5f60208284031215610845575f80fd5b5051919050565b73ffffffffffffffffffffffffffffffffffffffff8516815283602082015260606040820152816060820152818360808301375f818301608090810191909152601f9092017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01601019392505050565b818382375f910190815291905056fea164736f6c6343000815000a0000000000000000000000009f8f72aa9304c8b593d555f12ef6589cc3a579a20000000c00010002000100000000000000000000000000000000000000000000
Deployed Bytecode
0x608060405234801561000f575f80fd5b5060043610610085575f3560e01c80637150ef88116100585780637150ef881461012f578063739586aa1461014a578063bd6838721461015d578063bef59a0c14610187575f80fd5b8063102d282e146100895780633d31a4af1461009e57806341a49356146100ef57806358c655be1461011c575b5f80fd5b61009c6100973660046106da565b6101ae565b005b6100c57f0000000000000000000000009f8f72aa9304c8b593d555f12ef6589cc3a579a281565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b61010e6100fd36600461074a565b5f6020819052908152604090205481565b6040519081526020016100e6565b61009c61012a36600461076a565b6101bf565b6100c5733bc1a0ad72417f2d411118085256fc53cbddd13781565b61010e61015836600461074a565b6102fc565b61017061016b3660046107ee565b6103d0565b6040805192151583529015156020830152016100e6565b61010e7f0000000c0001000200010000000000000000000000000000000000000000000081565b6101ba338484846103e7565b505050565b6040517f4352409a0000000000000000000000000000000000000000000000000000000081523360048201527f0000000c000100020001000000000000000000000000000000000000000000006024820152733bc1a0ad72417f2d411118085256fc53cbddd13790634352409a90604401602060405180830381865afa15801561024b573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061026f9190610816565b6102a5576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6102b2868585858561053b565b6102e8576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6102f4868686866103e7565b505050505050565b73ffffffffffffffffffffffffffffffffffffffff8181165f818152602081905260408082205490517f70a0823100000000000000000000000000000000000000000000000000000000815260048101939093529092909182917f0000000000000000000000009f8f72aa9304c8b593d555f12ef6589cc3a579a216906370a0823190602401602060405180830381865afa15801561039d573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103c19190610835565b106103ca578091505b50919050565b5f6001816103dd856102fc565b1191509250929050565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff858116600483015284917f0000000000000000000000009f8f72aa9304c8b593d555f12ef6589cc3a579a2909116906370a0823190602401602060405180830381865afa158015610475573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104999190610835565b10156104d1576040517f62adb94f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff84165f9081526020819052604090819020849055517ea36578399109fd77650bd7a46592880be61181e7fc62cce6211c9c12d9aa449061052d90869086908690869061084c565b60405180910390a150505050565b5f6105718661056a87876040516020016105569291906108bc565b60405160208183030381529060405261057b565b85856105e4565b9695505050505050565b5f815160207f19457468657265756d205369676e6564204d6573736167653a0a00000000000081525f8052815b600182039150600a81066030018253600a9004806105a85750603a03602081113d3d3e80515f5117845281810160209190910384012092525090565b73ffffffffffffffffffffffffffffffffffffffff909316925f841561068d576040516041830361064a57845f5260408401355f1a6020526040846040376020600160805f60015afa805187183d151761064857505f60605260405250600161068d565b505b5f60605280604052631626ba7e60e01b80825285600483015260248201604081528460448401528486606485013760208160648701858b5afa9051909114169150505b949350505050565b5f8083601f8401126106a5575f80fd5b50813567ffffffffffffffff8111156106bc575f80fd5b6020830191508360208285010111156106d3575f80fd5b9250929050565b5f805f604084860312156106ec575f80fd5b83359250602084013567ffffffffffffffff811115610709575f80fd5b61071586828701610695565b9497909650939450505050565b803573ffffffffffffffffffffffffffffffffffffffff81168114610745575f80fd5b919050565b5f6020828403121561075a575f80fd5b61076382610722565b9392505050565b5f805f805f806080878903121561077f575f80fd5b61078887610722565b955060208701359450604087013567ffffffffffffffff808211156107ab575f80fd5b6107b78a838b01610695565b909650945060608901359150808211156107cf575f80fd5b506107dc89828a01610695565b979a9699509497509295939492505050565b5f80604083850312156107ff575f80fd5b61080883610722565b946020939093013593505050565b5f60208284031215610826575f80fd5b81518015158114610763575f80fd5b5f60208284031215610845575f80fd5b5051919050565b73ffffffffffffffffffffffffffffffffffffffff8516815283602082015260606040820152816060820152818360808301375f818301608090810191909152601f9092017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01601019392505050565b818382375f910190815291905056fea164736f6c6343000815000a
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000009f8f72aa9304c8b593d555f12ef6589cc3a579a20000000c00010002000100000000000000000000000000000000000000000000
-----Decoded View---------------
Arg [0] : _MKR (address): 0x9f8F72aA9304c8B593d555F12eF6589cC3A579A2
Arg [1] : _facilitatorHat (uint256): 323519771394501307089259385432256433664376508480981965228332365643776
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 0000000000000000000000009f8f72aa9304c8b593d555f12ef6589cc3a579a2
Arg [1] : 0000000c00010002000100000000000000000000000000000000000000000000
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 27 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.